summaryrefslogtreecommitdiff
path: root/modules/controlcenter/appearance/sections
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2026-01-03 17:53:06 +1100
committerGitHub <noreply@github.com>2026-01-03 17:53:06 +1100
commitbdcd13222fc6edc77c779a396900ab909e7d5439 (patch)
treef9457f3c91c05ec852f974f239d06aca52a3918e /modules/controlcenter/appearance/sections
parent[CI] chore: update flake (diff)
parentMerge branch 'caelestia-dots:main' into main (diff)
downloadcaelestia-shell-bdcd13222fc6edc77c779a396900ab909e7d5439.tar.gz
caelestia-shell-bdcd13222fc6edc77c779a396900ab909e7d5439.tar.bz2
caelestia-shell-bdcd13222fc6edc77c779a396900ab909e7d5439.zip
Merge pull request #906 from atdma/main
controlcenter: many setting panes and minor features
Diffstat (limited to 'modules/controlcenter/appearance/sections')
-rw-r--r--modules/controlcenter/appearance/sections/AnimationsSection.qml42
-rw-r--r--modules/controlcenter/appearance/sections/BackgroundSection.qml105
-rw-r--r--modules/controlcenter/appearance/sections/BorderSection.qml63
-rw-r--r--modules/controlcenter/appearance/sections/ColorSchemeSection.qml147
-rw-r--r--modules/controlcenter/appearance/sections/ColorVariantSection.qml92
-rw-r--r--modules/controlcenter/appearance/sections/FontsSection.qml286
-rw-r--r--modules/controlcenter/appearance/sections/ScalesSection.qml84
-rw-r--r--modules/controlcenter/appearance/sections/ThemeModeSection.qml24
-rw-r--r--modules/controlcenter/appearance/sections/TransparencySection.qml74
9 files changed, 917 insertions, 0 deletions
diff --git a/modules/controlcenter/appearance/sections/AnimationsSection.qml b/modules/controlcenter/appearance/sections/AnimationsSection.qml
new file mode 100644
index 0000000..03fc2b1
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/AnimationsSection.qml
@@ -0,0 +1,42 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../components"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ id: root
+
+ required property var rootPane
+
+ title: qsTr("Animations")
+ showBackground: true
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Animation duration scale")
+ value: rootPane.animDurationsScale
+ from: 0.1
+ to: 5.0
+ decimals: 1
+ suffix: "×"
+ validator: DoubleValidator { bottom: 0.1; top: 5.0 }
+
+ onValueModified: (newValue) => {
+ rootPane.animDurationsScale = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/BackgroundSection.qml b/modules/controlcenter/appearance/sections/BackgroundSection.qml
new file mode 100644
index 0000000..8754e73
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/BackgroundSection.qml
@@ -0,0 +1,105 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../components"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ id: root
+
+ required property var rootPane
+
+ title: qsTr("Background")
+ showBackground: true
+
+ SwitchRow {
+ label: qsTr("Desktop clock")
+ checked: rootPane.desktopClockEnabled
+ onToggled: checked => {
+ rootPane.desktopClockEnabled = checked;
+ rootPane.saveConfig();
+ }
+ }
+
+ SwitchRow {
+ label: qsTr("Background enabled")
+ checked: rootPane.backgroundEnabled
+ onToggled: checked => {
+ rootPane.backgroundEnabled = checked;
+ rootPane.saveConfig();
+ }
+ }
+
+ StyledText {
+ Layout.topMargin: Appearance.spacing.normal
+ text: qsTr("Visualiser")
+ font.pointSize: Appearance.font.size.larger
+ font.weight: 500
+ }
+
+ SwitchRow {
+ label: qsTr("Visualiser enabled")
+ checked: rootPane.visualiserEnabled
+ onToggled: checked => {
+ rootPane.visualiserEnabled = checked;
+ rootPane.saveConfig();
+ }
+ }
+
+ SwitchRow {
+ label: qsTr("Visualiser auto hide")
+ checked: rootPane.visualiserAutoHide
+ onToggled: checked => {
+ rootPane.visualiserAutoHide = checked;
+ rootPane.saveConfig();
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Visualiser rounding")
+ value: rootPane.visualiserRounding
+ from: 0
+ to: 10
+ stepSize: 1
+ validator: IntValidator { bottom: 0; top: 10 }
+ formatValueFunction: (val) => Math.round(val).toString()
+ parseValueFunction: (text) => parseInt(text)
+
+ onValueModified: (newValue) => {
+ rootPane.visualiserRounding = Math.round(newValue);
+ rootPane.saveConfig();
+ }
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Visualiser spacing")
+ value: rootPane.visualiserSpacing
+ from: 0
+ to: 2
+ validator: DoubleValidator { bottom: 0; top: 2 }
+
+ onValueModified: (newValue) => {
+ rootPane.visualiserSpacing = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/BorderSection.qml b/modules/controlcenter/appearance/sections/BorderSection.qml
new file mode 100644
index 0000000..dae26c3
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/BorderSection.qml
@@ -0,0 +1,63 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../components"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ id: root
+
+ required property var rootPane
+
+ title: qsTr("Border")
+ showBackground: true
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Border rounding")
+ value: rootPane.borderRounding
+ from: 0.1
+ to: 100
+ decimals: 1
+ suffix: "px"
+ validator: DoubleValidator { bottom: 0.1; top: 100 }
+
+ onValueModified: (newValue) => {
+ rootPane.borderRounding = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Border thickness")
+ value: rootPane.borderThickness
+ from: 0.1
+ to: 100
+ decimals: 1
+ suffix: "px"
+ validator: DoubleValidator { bottom: 0.1; top: 100 }
+
+ onValueModified: (newValue) => {
+ rootPane.borderThickness = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/ColorSchemeSection.qml b/modules/controlcenter/appearance/sections/ColorSchemeSection.qml
new file mode 100644
index 0000000..c0e5eb5
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/ColorSchemeSection.qml
@@ -0,0 +1,147 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../../launcher/services"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import Quickshell
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ title: qsTr("Color scheme")
+ description: qsTr("Available color schemes")
+ showBackground: true
+
+ ColumnLayout {
+ Layout.fillWidth: true
+ spacing: Appearance.spacing.small / 2
+
+ Repeater {
+ model: Schemes.list
+
+ delegate: StyledRect {
+ required property var modelData
+
+ Layout.fillWidth: true
+
+ readonly property string schemeKey: `${modelData.name} ${modelData.flavour}`
+ readonly property bool isCurrent: schemeKey === Schemes.currentScheme
+
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
+ radius: Appearance.rounding.normal
+ border.width: isCurrent ? 1 : 0
+ border.color: Colours.palette.m3primary
+
+ StateLayer {
+ function onClicked(): void {
+ const name = modelData.name;
+ const flavour = modelData.flavour;
+ const schemeKey = `${name} ${flavour}`;
+
+ Schemes.currentScheme = schemeKey;
+ Quickshell.execDetached(["caelestia", "scheme", "set", "-n", name, "-f", flavour]);
+
+ Qt.callLater(() => {
+ reloadTimer.restart();
+ });
+ }
+ }
+
+ Timer {
+ id: reloadTimer
+ interval: 300
+ onTriggered: {
+ Schemes.reload();
+ }
+ }
+
+ RowLayout {
+ id: schemeRow
+
+ anchors.fill: parent
+ anchors.margins: Appearance.padding.normal
+
+ spacing: Appearance.spacing.normal
+
+ StyledRect {
+ id: preview
+
+ Layout.alignment: Qt.AlignVCenter
+
+ border.width: 1
+ border.color: Qt.alpha(`#${modelData.colours?.outline}`, 0.5)
+
+ color: `#${modelData.colours?.surface}`
+ radius: Appearance.rounding.full
+ implicitWidth: iconPlaceholder.implicitWidth
+ implicitHeight: iconPlaceholder.implicitWidth
+
+ MaterialIcon {
+ id: iconPlaceholder
+ visible: false
+ text: "circle"
+ font.pointSize: Appearance.font.size.large
+ }
+
+ Item {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+
+ implicitWidth: parent.implicitWidth / 2
+ clip: true
+
+ StyledRect {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+
+ implicitWidth: preview.implicitWidth
+ color: `#${modelData.colours?.primary}`
+ radius: Appearance.rounding.full
+ }
+ }
+ }
+
+ Column {
+ Layout.fillWidth: true
+ spacing: 0
+
+ StyledText {
+ text: modelData.flavour ?? ""
+ font.pointSize: Appearance.font.size.normal
+ }
+
+ StyledText {
+ text: modelData.name ?? ""
+ font.pointSize: Appearance.font.size.small
+ color: Colours.palette.m3outline
+
+ elide: Text.ElideRight
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+ }
+
+ Loader {
+ active: isCurrent
+ asynchronous: true
+
+ sourceComponent: MaterialIcon {
+ text: "check"
+ color: Colours.palette.m3onSurfaceVariant
+ font.pointSize: Appearance.font.size.large
+ }
+ }
+ }
+
+ implicitHeight: schemeRow.implicitHeight + Appearance.padding.normal * 2
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/ColorVariantSection.qml b/modules/controlcenter/appearance/sections/ColorVariantSection.qml
new file mode 100644
index 0000000..98c3d7c
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/ColorVariantSection.qml
@@ -0,0 +1,92 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../../launcher/services"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import Quickshell
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ title: qsTr("Color variant")
+ description: qsTr("Material theme variant")
+ showBackground: true
+
+ ColumnLayout {
+ Layout.fillWidth: true
+ spacing: Appearance.spacing.small / 2
+
+ Repeater {
+ model: M3Variants.list
+
+ delegate: StyledRect {
+ required property var modelData
+
+ Layout.fillWidth: true
+
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, modelData.variant === Schemes.currentVariant ? Colours.tPalette.m3surfaceContainer.a : 0)
+ radius: Appearance.rounding.normal
+ border.width: modelData.variant === Schemes.currentVariant ? 1 : 0
+ border.color: Colours.palette.m3primary
+
+ StateLayer {
+ function onClicked(): void {
+ const variant = modelData.variant;
+
+ Schemes.currentVariant = variant;
+ Quickshell.execDetached(["caelestia", "scheme", "set", "-v", variant]);
+
+ Qt.callLater(() => {
+ reloadTimer.restart();
+ });
+ }
+ }
+
+ Timer {
+ id: reloadTimer
+ interval: 300
+ onTriggered: {
+ Schemes.reload();
+ }
+ }
+
+ RowLayout {
+ id: variantRow
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.margins: Appearance.padding.normal
+
+ spacing: Appearance.spacing.normal
+
+ MaterialIcon {
+ text: modelData.icon
+ font.pointSize: Appearance.font.size.large
+ fill: modelData.variant === Schemes.currentVariant ? 1 : 0
+ }
+
+ StyledText {
+ Layout.fillWidth: true
+ text: modelData.name
+ font.weight: modelData.variant === Schemes.currentVariant ? 500 : 400
+ }
+
+ MaterialIcon {
+ visible: modelData.variant === Schemes.currentVariant
+ text: "check"
+ color: Colours.palette.m3primary
+ font.pointSize: Appearance.font.size.large
+ }
+ }
+
+ implicitHeight: variantRow.implicitHeight + Appearance.padding.normal * 2
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/FontsSection.qml b/modules/controlcenter/appearance/sections/FontsSection.qml
new file mode 100644
index 0000000..57b10ff
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/FontsSection.qml
@@ -0,0 +1,286 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../components"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ id: root
+
+ required property var rootPane
+
+ title: qsTr("Fonts")
+ showBackground: true
+
+ CollapsibleSection {
+ id: materialFontSection
+ title: qsTr("Material font family")
+ expanded: true
+ showBackground: true
+ nested: true
+
+ Loader {
+ id: materialFontLoader
+ Layout.fillWidth: true
+ Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0
+ asynchronous: true
+ active: materialFontSection.expanded
+
+ sourceComponent: StyledListView {
+ id: materialFontList
+ property alias contentHeight: materialFontList.contentHeight
+
+ clip: true
+ spacing: Appearance.spacing.small / 2
+ model: Qt.fontFamilies()
+
+ StyledScrollBar.vertical: StyledScrollBar {
+ flickable: materialFontList
+ }
+
+ delegate: StyledRect {
+ required property string modelData
+ required property int index
+
+ width: ListView.view.width
+
+ readonly property bool isCurrent: modelData === rootPane.fontFamilyMaterial
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
+ radius: Appearance.rounding.normal
+ border.width: isCurrent ? 1 : 0
+ border.color: Colours.palette.m3primary
+
+ StateLayer {
+ function onClicked(): void {
+ rootPane.fontFamilyMaterial = modelData;
+ rootPane.saveConfig();
+ }
+ }
+
+ RowLayout {
+ id: fontFamilyMaterialRow
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.margins: Appearance.padding.normal
+
+ spacing: Appearance.spacing.normal
+
+ StyledText {
+ text: modelData
+ font.pointSize: Appearance.font.size.normal
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Loader {
+ active: isCurrent
+ asynchronous: true
+
+ sourceComponent: MaterialIcon {
+ text: "check"
+ color: Colours.palette.m3onSurfaceVariant
+ font.pointSize: Appearance.font.size.large
+ }
+ }
+ }
+
+ implicitHeight: fontFamilyMaterialRow.implicitHeight + Appearance.padding.normal * 2
+ }
+ }
+ }
+ }
+
+ CollapsibleSection {
+ id: monoFontSection
+ title: qsTr("Monospace font family")
+ expanded: false
+ showBackground: true
+ nested: true
+
+ Loader {
+ Layout.fillWidth: true
+ Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0
+ asynchronous: true
+ active: monoFontSection.expanded
+
+ sourceComponent: StyledListView {
+ id: monoFontList
+ property alias contentHeight: monoFontList.contentHeight
+
+ clip: true
+ spacing: Appearance.spacing.small / 2
+ model: Qt.fontFamilies()
+
+ StyledScrollBar.vertical: StyledScrollBar {
+ flickable: monoFontList
+ }
+
+ delegate: StyledRect {
+ required property string modelData
+ required property int index
+
+ width: ListView.view.width
+
+ readonly property bool isCurrent: modelData === rootPane.fontFamilyMono
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
+ radius: Appearance.rounding.normal
+ border.width: isCurrent ? 1 : 0
+ border.color: Colours.palette.m3primary
+
+ StateLayer {
+ function onClicked(): void {
+ rootPane.fontFamilyMono = modelData;
+ rootPane.saveConfig();
+ }
+ }
+
+ RowLayout {
+ id: fontFamilyMonoRow
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.margins: Appearance.padding.normal
+
+ spacing: Appearance.spacing.normal
+
+ StyledText {
+ text: modelData
+ font.pointSize: Appearance.font.size.normal
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Loader {
+ active: isCurrent
+ asynchronous: true
+
+ sourceComponent: MaterialIcon {
+ text: "check"
+ color: Colours.palette.m3onSurfaceVariant
+ font.pointSize: Appearance.font.size.large
+ }
+ }
+ }
+
+ implicitHeight: fontFamilyMonoRow.implicitHeight + Appearance.padding.normal * 2
+ }
+ }
+ }
+ }
+
+ CollapsibleSection {
+ id: sansFontSection
+ title: qsTr("Sans-serif font family")
+ expanded: false
+ showBackground: true
+ nested: true
+
+ Loader {
+ Layout.fillWidth: true
+ Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0
+ asynchronous: true
+ active: sansFontSection.expanded
+
+ sourceComponent: StyledListView {
+ id: sansFontList
+ property alias contentHeight: sansFontList.contentHeight
+
+ clip: true
+ spacing: Appearance.spacing.small / 2
+ model: Qt.fontFamilies()
+
+ StyledScrollBar.vertical: StyledScrollBar {
+ flickable: sansFontList
+ }
+
+ delegate: StyledRect {
+ required property string modelData
+ required property int index
+
+ width: ListView.view.width
+
+ readonly property bool isCurrent: modelData === rootPane.fontFamilySans
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
+ radius: Appearance.rounding.normal
+ border.width: isCurrent ? 1 : 0
+ border.color: Colours.palette.m3primary
+
+ StateLayer {
+ function onClicked(): void {
+ rootPane.fontFamilySans = modelData;
+ rootPane.saveConfig();
+ }
+ }
+
+ RowLayout {
+ id: fontFamilySansRow
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.margins: Appearance.padding.normal
+
+ spacing: Appearance.spacing.normal
+
+ StyledText {
+ text: modelData
+ font.pointSize: Appearance.font.size.normal
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Loader {
+ active: isCurrent
+ asynchronous: true
+
+ sourceComponent: MaterialIcon {
+ text: "check"
+ color: Colours.palette.m3onSurfaceVariant
+ font.pointSize: Appearance.font.size.large
+ }
+ }
+ }
+
+ implicitHeight: fontFamilySansRow.implicitHeight + Appearance.padding.normal * 2
+ }
+ }
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Font size scale")
+ value: rootPane.fontSizeScale
+ from: 0.7
+ to: 1.5
+ decimals: 2
+ suffix: "×"
+ validator: DoubleValidator { bottom: 0.7; top: 1.5 }
+
+ onValueModified: (newValue) => {
+ rootPane.fontSizeScale = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/ScalesSection.qml b/modules/controlcenter/appearance/sections/ScalesSection.qml
new file mode 100644
index 0000000..f74923b
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/ScalesSection.qml
@@ -0,0 +1,84 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../components"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ id: root
+
+ required property var rootPane
+
+ title: qsTr("Scales")
+ showBackground: true
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Padding scale")
+ value: rootPane.paddingScale
+ from: 0.5
+ to: 2.0
+ decimals: 1
+ suffix: "×"
+ validator: DoubleValidator { bottom: 0.5; top: 2.0 }
+
+ onValueModified: (newValue) => {
+ rootPane.paddingScale = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Rounding scale")
+ value: rootPane.roundingScale
+ from: 0.1
+ to: 5.0
+ decimals: 1
+ suffix: "×"
+ validator: DoubleValidator { bottom: 0.1; top: 5.0 }
+
+ onValueModified: (newValue) => {
+ rootPane.roundingScale = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Spacing scale")
+ value: rootPane.spacingScale
+ from: 0.1
+ to: 2.0
+ decimals: 1
+ suffix: "×"
+ validator: DoubleValidator { bottom: 0.1; top: 2.0 }
+
+ onValueModified: (newValue) => {
+ rootPane.spacingScale = newValue;
+ rootPane.saveConfig();
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/ThemeModeSection.qml b/modules/controlcenter/appearance/sections/ThemeModeSection.qml
new file mode 100644
index 0000000..c136437
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/ThemeModeSection.qml
@@ -0,0 +1,24 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+
+CollapsibleSection {
+ title: qsTr("Theme mode")
+ description: qsTr("Light or dark theme")
+ showBackground: true
+
+ SwitchRow {
+ label: qsTr("Dark mode")
+ checked: !Colours.currentLight
+ onToggled: checked => {
+ Colours.setMode(checked ? "dark" : "light");
+ }
+ }
+}
+
diff --git a/modules/controlcenter/appearance/sections/TransparencySection.qml b/modules/controlcenter/appearance/sections/TransparencySection.qml
new file mode 100644
index 0000000..c9dbfb8
--- /dev/null
+++ b/modules/controlcenter/appearance/sections/TransparencySection.qml
@@ -0,0 +1,74 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../../components"
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+CollapsibleSection {
+ id: root
+
+ required property var rootPane
+
+ title: qsTr("Transparency")
+ showBackground: true
+
+ SwitchRow {
+ label: qsTr("Transparency enabled")
+ checked: rootPane.transparencyEnabled
+ onToggled: checked => {
+ rootPane.transparencyEnabled = checked;
+ rootPane.saveConfig();
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Transparency base")
+ value: rootPane.transparencyBase * 100
+ from: 0
+ to: 100
+ suffix: "%"
+ validator: IntValidator { bottom: 0; top: 100 }
+ formatValueFunction: (val) => Math.round(val).toString()
+ parseValueFunction: (text) => parseInt(text)
+
+ onValueModified: (newValue) => {
+ rootPane.transparencyBase = newValue / 100;
+ rootPane.saveConfig();
+ }
+ }
+ }
+
+ SectionContainer {
+ contentSpacing: Appearance.spacing.normal
+
+ SliderInput {
+ Layout.fillWidth: true
+
+ label: qsTr("Transparency layers")
+ value: rootPane.transparencyLayers * 100
+ from: 0
+ to: 100
+ suffix: "%"
+ validator: IntValidator { bottom: 0; top: 100 }
+ formatValueFunction: (val) => Math.round(val).toString()
+ parseValueFunction: (text) => parseInt(text)
+
+ onValueModified: (newValue) => {
+ rootPane.transparencyLayers = newValue / 100;
+ rootPane.saveConfig();
+ }
+ }
+ }
+}
+