summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets
diff options
context:
space:
mode:
authorNippy <nippy@rp1.hu>2026-05-08 19:50:49 +0200
committerNippy <nippy@rp1.hu>2026-05-08 19:50:49 +0200
commit3462bcc46ecf74f576ea4397f16492c16bd75b10 (patch)
treec5ab7aef4498647e057bda8d49c11e5f9dda74c9 /raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets
parent56616f693b4f263cbf0d47da43b67424efa6022d (diff)
downloadRaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.tar.gz
RaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.zip
raveos update
Diffstat (limited to 'raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets')
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/AudioSliderRow.qml103
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BatteryPill.qml46
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BrightnessSliderRow.qml194
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ColorPickerPill.qml29
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompactSlider.qml71
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompoundPill.qml205
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DetailView.qml23
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DiskUsagePill.qml76
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ErrorPill.qml56
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/InputAudioSliderRow.qml87
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallBatteryButton.qml113
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallDiskUsageButton.qml129
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallToggleButton.qml90
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ToggleButton.qml134
14 files changed, 1356 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/AudioSliderRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/AudioSliderRow.qml
new file mode 100644
index 0000000..81d346d
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/AudioSliderRow.qml
@@ -0,0 +1,103 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Row {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property var defaultSink: AudioService.sink
+ property color sliderTrackColor: "transparent"
+
+ height: 40
+ spacing: 0
+
+ Rectangle {
+ width: Theme.iconSize + Theme.spacingS * 2
+ height: Theme.iconSize + Theme.spacingS * 2
+ anchors.verticalCenter: parent.verticalCenter
+ radius: (Theme.iconSize + Theme.spacingS * 2) / 2
+ color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0)
+
+ DankRipple {
+ id: iconRipple
+ cornerRadius: parent.radius
+ }
+
+ MouseArea {
+ id: iconArea
+ anchors.fill: parent
+ visible: defaultSink !== null
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y)
+ onClicked: {
+ if (defaultSink) {
+ SessionData.suppressOSDTemporarily();
+ defaultSink.audio.muted = !defaultSink.audio.muted;
+ }
+ }
+ }
+
+ DankIcon {
+ anchors.centerIn: parent
+ name: {
+ if (!defaultSink)
+ return "volume_off";
+
+ let volume = defaultSink.audio.volume;
+ let muted = defaultSink.audio.muted;
+
+ if (muted)
+ return "volume_off";
+ if (volume === 0.0)
+ return "volume_mute";
+ if (volume <= 0.33)
+ return "volume_down";
+ if (volume <= 0.66)
+ return "volume_up";
+ return "volume_up";
+ }
+ size: Theme.iconSize
+ color: defaultSink && !defaultSink.audio.muted && defaultSink.audio.volume > 0 ? Theme.primary : Theme.surfaceText
+ }
+ }
+
+ DankSlider {
+ id: volumeSlider
+
+ readonly property real actualVolumePercent: defaultSink ? Math.round(defaultSink.audio.volume * 100) : 0
+
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width - (Theme.iconSize + Theme.spacingS * 2)
+ enabled: defaultSink !== null
+ minimum: 0
+ maximum: AudioService.sinkMaxVolume
+ showValue: true
+ unit: "%"
+ valueOverride: actualVolumePercent
+ thumbOutlineColor: Theme.surfaceContainer
+ trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+
+ onSliderValueChanged: function (newValue) {
+ if (defaultSink) {
+ SessionData.suppressOSDTemporarily();
+ defaultSink.audio.volume = newValue / 100.0;
+ if (newValue > 0 && defaultSink.audio.muted) {
+ defaultSink.audio.muted = false;
+ }
+ AudioService.playVolumeChangeSoundIfEnabled();
+ }
+ }
+ }
+
+ Binding {
+ target: volumeSlider
+ property: "value"
+ value: defaultSink ? Math.min(AudioService.sinkMaxVolume, Math.round(defaultSink.audio.volume * 100)) : 0
+ when: !volumeSlider.isDragging
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BatteryPill.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BatteryPill.qml
new file mode 100644
index 0000000..c14c308
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BatteryPill.qml
@@ -0,0 +1,46 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Modules.ControlCenter.Widgets
+
+CompoundPill {
+ id: root
+
+ iconName: BatteryService.getBatteryIcon()
+
+ isActive: BatteryService.batteryAvailable && (BatteryService.isCharging || BatteryService.isPluggedIn)
+
+ primaryText: {
+ if (!BatteryService.batteryAvailable) {
+ return I18n.tr("No battery");
+ }
+ return I18n.tr("Battery");
+ }
+
+ secondaryText: {
+ if (!BatteryService.batteryAvailable) {
+ return I18n.tr("Not available");
+ }
+ if (BatteryService.isCharging) {
+ return `${BatteryService.batteryLevel}% • ` + I18n.tr("Charging");
+ }
+ if (BatteryService.isPluggedIn) {
+ return `${BatteryService.batteryLevel}% • ` + I18n.tr("Plugged in");
+ }
+ return `${BatteryService.batteryLevel}%`;
+ }
+
+ iconColor: {
+ if (BatteryService.isLowBattery && !BatteryService.isCharging) {
+ return Theme.error;
+ }
+ if (BatteryService.isCharging || BatteryService.isPluggedIn) {
+ return Theme.primary;
+ }
+ return Theme.surfaceText;
+ }
+
+ onToggled: {
+ expandClicked();
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BrightnessSliderRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BrightnessSliderRow.qml
new file mode 100644
index 0000000..037c08f
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/BrightnessSliderRow.qml
@@ -0,0 +1,194 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Row {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property string deviceName: ""
+ property string instanceId: ""
+ property string screenName: ""
+ property var parentScreen: null
+
+ signal iconClicked
+
+ height: 40
+ spacing: 0
+
+ DankTooltipV2 {
+ id: sharedTooltip
+ }
+
+ property string targetDeviceName: {
+ if (!DisplayService.brightnessAvailable || !DisplayService.devices || DisplayService.devices.length === 0) {
+ return "";
+ }
+
+ if (screenName && screenName.length > 0) {
+ const pins = SettingsData.brightnessDevicePins || {};
+ const pinnedDevice = pins[screenName];
+ if (pinnedDevice && pinnedDevice.length > 0) {
+ const found = DisplayService.devices.find(dev => dev.name === pinnedDevice);
+ if (found) {
+ return found.name;
+ }
+ }
+ }
+
+ if (deviceName && deviceName.length > 0) {
+ const found = DisplayService.devices.find(dev => dev.name === deviceName);
+ if (found) {
+ return found.name;
+ }
+ }
+
+ const currentDeviceName = DisplayService.currentDevice;
+ if (currentDeviceName) {
+ const found = DisplayService.devices.find(dev => dev.name === currentDeviceName);
+ if (found) {
+ return found.name;
+ }
+ }
+
+ const backlight = DisplayService.devices.find(d => d.class === "backlight");
+ if (backlight) {
+ return backlight.name;
+ }
+
+ const ddc = DisplayService.devices.find(d => d.class === "ddc");
+ if (ddc) {
+ return ddc.name;
+ }
+
+ return DisplayService.devices.length > 0 ? DisplayService.devices[0].name : "";
+ }
+
+ property var targetDevice: {
+ if (!targetDeviceName || !DisplayService.devices) {
+ return null;
+ }
+
+ return DisplayService.devices.find(dev => dev.name === targetDeviceName) || null;
+ }
+
+ property real targetBrightness: {
+ DisplayService.brightnessVersion;
+ if (!targetDeviceName) {
+ return 0;
+ }
+
+ return DisplayService.getDeviceBrightness(targetDeviceName);
+ }
+
+ Rectangle {
+ width: Theme.iconSize + Theme.spacingS * 2
+ height: Theme.iconSize + Theme.spacingS * 2
+ anchors.verticalCenter: parent.verticalCenter
+ radius: (Theme.iconSize + Theme.spacingS * 2) / 2
+ color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0)
+
+ DankRipple {
+ id: iconRipple
+ cornerRadius: parent.radius
+ }
+
+ MouseArea {
+ id: iconArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: DisplayService.devices && DisplayService.devices.length > 1 ? Qt.PointingHandCursor : Qt.ArrowCursor
+
+ onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y)
+ onClicked: {
+ if (DisplayService.devices && DisplayService.devices.length > 1) {
+ root.iconClicked();
+ }
+ }
+
+ onEntered: {
+ const tooltipText = targetDevice ? "bl device: " + targetDevice.name : "Backlight Control";
+ sharedTooltip.show(tooltipText, iconArea, 0, 0, "bottom");
+ }
+
+ onExited: {
+ sharedTooltip.hide();
+ }
+
+ DankIcon {
+ anchors.centerIn: parent
+ name: {
+ if (!DisplayService.brightnessAvailable || !targetDevice) {
+ return "brightness_low";
+ }
+
+ if (targetDevice.class === "backlight" || targetDevice.class === "ddc") {
+ const brightness = targetBrightness;
+ if (brightness <= 33)
+ return "brightness_low";
+ if (brightness <= 66)
+ return "brightness_medium";
+ return "brightness_high";
+ } else if (targetDevice.name.includes("kbd")) {
+ return "keyboard";
+ } else {
+ return "lightbulb";
+ }
+ }
+ size: Theme.iconSize
+ color: DisplayService.brightnessAvailable && targetDevice && targetBrightness > 0 ? Theme.primary : Theme.surfaceText
+ }
+ }
+ }
+
+ DankSlider {
+ id: brightnessSlider
+
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width - (Theme.iconSize + Theme.spacingS * 2)
+ enabled: DisplayService.brightnessAvailable && targetDeviceName.length > 0
+ minimum: {
+ if (!targetDevice)
+ return 1;
+ const isExponential = SessionData.getBrightnessExponential(targetDevice.id);
+ if (isExponential) {
+ return 1;
+ }
+ return (targetDevice.class === "backlight" || targetDevice.class === "ddc") ? 1 : 0;
+ }
+ maximum: {
+ if (!targetDevice)
+ return 100;
+ const isExponential = SessionData.getBrightnessExponential(targetDevice.id);
+ if (isExponential) {
+ return 100;
+ }
+ return targetDevice.displayMax || 100;
+ }
+ showValue: true
+ unit: {
+ if (!targetDevice)
+ return "%";
+ const isExponential = SessionData.getBrightnessExponential(targetDevice.id);
+ if (isExponential) {
+ return "%";
+ }
+ return targetDevice.class === "ddc" ? "" : "%";
+ }
+ onSliderValueChanged: function (newValue) {
+ if (DisplayService.brightnessAvailable && targetDeviceName) {
+ DisplayService.setBrightness(newValue, targetDeviceName, true);
+ }
+ }
+ thumbOutlineColor: Theme.surfaceContainer
+ trackColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+
+ Binding on value {
+ value: root.targetBrightness
+ when: !brightnessSlider.isDragging
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ColorPickerPill.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ColorPickerPill.qml
new file mode 100644
index 0000000..a95410b
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ColorPickerPill.qml
@@ -0,0 +1,29 @@
+import QtQuick
+import qs.Common
+import qs.Modules.ControlCenter.Widgets
+
+CompoundPill {
+ id: root
+
+ property var colorPickerModal: null
+
+ isActive: true
+ iconName: "palette"
+ iconColor: Theme.primary
+ primaryText: I18n.tr("Color Picker")
+ secondaryText: I18n.tr("Choose a color")
+
+ onToggled: {
+ console.log("ColorPickerPill toggled, modal:", colorPickerModal);
+ if (colorPickerModal) {
+ colorPickerModal.show();
+ }
+ }
+
+ onExpandClicked: {
+ console.log("ColorPickerPill expandClicked, modal:", colorPickerModal);
+ if (colorPickerModal) {
+ colorPickerModal.show();
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompactSlider.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompactSlider.qml
new file mode 100644
index 0000000..eeed4c4
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompactSlider.qml
@@ -0,0 +1,71 @@
+import QtQuick
+import qs.Common
+import qs.Widgets
+
+Rectangle {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property string iconName: ""
+ property color iconColor: Theme.surfaceText
+ property string labelText: ""
+ property real value: 0.0
+ property real maximumValue: 1.0
+ property real minimumValue: 0.0
+ property bool enabled: true
+
+ signal sliderValueChanged(real value)
+
+ width: parent ? parent.width : 200
+ height: 60
+ radius: Theme.cornerRadius
+ color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+ border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
+ border.width: 0
+ opacity: enabled ? 1.0 : 0.6
+
+ Row {
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.leftMargin: Theme.spacingM
+ anchors.right: sliderContainer.left
+ anchors.rightMargin: Theme.spacingS
+ spacing: Theme.spacingS
+
+ DankIcon {
+ name: root.iconName
+ size: Theme.iconSize
+ color: root.iconColor
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ StyledText {
+ text: root.labelText
+ font.pixelSize: Theme.fontSizeMedium
+ color: Theme.surfaceText
+ font.weight: Font.Medium
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ Rectangle {
+ id: sliderContainer
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.rightMargin: Theme.spacingM
+ width: 120
+ height: parent.height - Theme.spacingS * 2
+
+ DankSlider {
+ anchors.centerIn: parent
+ width: parent.width
+ enabled: root.enabled
+ minimum: Math.round(root.minimumValue * 100)
+ maximum: Math.round(root.maximumValue * 100)
+ value: Math.round(root.value * 100)
+ onSliderValueChanged: root.sliderValueChanged(newValue / 100.0)
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompoundPill.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompoundPill.qml
new file mode 100644
index 0000000..9165ec4
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/CompoundPill.qml
@@ -0,0 +1,205 @@
+import QtQuick
+import qs.Common
+import qs.Widgets
+
+Rectangle {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property string iconName: ""
+ property color iconColor: Theme.surfaceText
+ property string primaryText: ""
+ property string secondaryText: ""
+ property bool expanded: false
+ property bool isActive: false
+ property bool showExpandArea: true
+
+ signal toggled
+ signal expandClicked
+ signal wheelEvent(var wheelEvent)
+
+ width: parent ? parent.width : 220
+ height: 60
+ radius: Theme.cornerRadius
+
+ function hoverTint(base) {
+ const factor = 1.2;
+ return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
+ }
+
+ readonly property color _containerBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+
+ color: {
+ const baseColor = bodyMouse.containsMouse ? Theme.primaryPressed : _containerBg;
+ return baseColor;
+ }
+ border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.10)
+ border.width: 0
+ antialiasing: true
+
+ readonly property color _labelPrimary: Theme.surfaceText
+ readonly property color _labelSecondary: Theme.surfaceVariantText
+ readonly property color _tileBgActive: Theme.ccTileActiveBg
+ readonly property color _tileBgInactive: {
+ const transparency = Theme.popupTransparency;
+ const surface = Theme.surfaceContainer || Qt.rgba(0.1, 0.1, 0.1, 1);
+ return Qt.rgba(surface.r, surface.g, surface.b, transparency);
+ }
+ readonly property color _tileRingActive: Theme.ccTileRing
+ readonly property color _tileRingInactive: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.18)
+ readonly property color _tileIconActive: Theme.ccTileActiveText
+ readonly property color _tileIconInactive: Theme.ccTileInactiveIcon
+
+ property int _padH: Theme.spacingS
+ property int _tileSize: 48
+ property int _tileRadius: Theme.cornerRadius
+
+ Rectangle {
+ id: rightHoverOverlay
+ anchors.fill: parent
+ radius: root.radius
+ z: 0
+ visible: false
+ color: hoverTint(_containerBg)
+ opacity: 0.08
+ antialiasing: true
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ }
+ }
+ }
+
+ DankRipple {
+ id: bodyRipple
+ cornerRadius: root.radius
+ }
+
+ Row {
+ id: row
+ anchors.fill: parent
+ anchors.leftMargin: _padH
+ anchors.rightMargin: Theme.spacingM
+ spacing: Theme.spacingM
+
+ Rectangle {
+ id: iconTile
+ z: 1
+ width: _tileSize
+ height: _tileSize
+ anchors.verticalCenter: parent.verticalCenter
+ radius: _tileRadius
+ color: isActive ? _tileBgActive : _tileBgInactive
+ border.color: isActive ? _tileRingActive : "transparent"
+ border.width: isActive ? 1 : 0
+ antialiasing: true
+
+ Rectangle {
+ anchors.fill: parent
+ radius: _tileRadius
+ color: hoverTint(iconTile.color)
+ opacity: tileMouse.pressed ? 0.3 : (tileMouse.containsMouse ? 0.2 : 0.0)
+ visible: opacity > 0
+ antialiasing: true
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ }
+ }
+ }
+
+ DankIcon {
+ anchors.centerIn: parent
+ name: iconName
+ size: Theme.iconSize
+ color: isActive ? _tileIconActive : _tileIconInactive
+ }
+
+ DankRipple {
+ id: tileRipple
+ cornerRadius: _tileRadius
+ }
+
+ MouseArea {
+ id: tileMouse
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onPressed: mouse => tileRipple.trigger(mouse.x, mouse.y)
+ onClicked: root.toggled()
+ }
+ }
+
+ Item {
+ id: body
+ width: row.width - iconTile.width - row.spacing
+ height: row.height
+
+ Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 2
+
+ StyledText {
+ width: parent.width
+ text: root.primaryText
+ color: _labelPrimary
+ font.pixelSize: Theme.fontSizeMedium
+ font.weight: Font.Medium
+ elide: Text.ElideRight
+ wrapMode: Text.NoWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+ StyledText {
+ width: parent.width
+ text: root.secondaryText
+ color: _labelSecondary
+ font.pixelSize: Theme.fontSizeSmall
+ visible: text.length > 0
+ elide: Text.ElideRight
+ wrapMode: Text.NoWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+
+ MouseArea {
+ id: bodyMouse
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onEntered: {
+ rightHoverOverlay.visible = true;
+ rightHoverOverlay.opacity = 0.08;
+ }
+ onExited: {
+ rightHoverOverlay.opacity = 0.0;
+ rightHoverOverlay.visible = false;
+ }
+ onPressed: mouse => {
+ const pos = mapToItem(root, mouse.x, mouse.y);
+ bodyRipple.trigger(pos.x, pos.y);
+ rightHoverOverlay.opacity = 0.16;
+ }
+ onReleased: rightHoverOverlay.opacity = containsMouse ? 0.08 : 0.0
+ onClicked: root.expandClicked()
+ onWheel: function (ev) {
+ root.wheelEvent(ev);
+ }
+ }
+ }
+ }
+
+ focus: true
+ Keys.onPressed: function (ev) {
+ if (ev.key === Qt.Key_Space || ev.key === Qt.Key_Return) {
+ root.toggled();
+ ev.accepted = true;
+ } else if (ev.key === Qt.Key_Right) {
+ root.expandClicked();
+ ev.accepted = true;
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DetailView.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DetailView.qml
new file mode 100644
index 0000000..2d946f3
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DetailView.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Rectangle {
+ id: root
+
+ property string title: ""
+ property Component content: null
+ property bool isVisible: true
+ property int contentHeight: 300
+
+ width: parent ? parent.width : 400
+ implicitHeight: isVisible ? contentHeight : 0
+ height: implicitHeight
+ color: "transparent"
+ clip: true
+
+ Loader {
+ id: contentLoader
+ anchors.fill: parent
+ sourceComponent: root.content
+ asynchronous: true
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DiskUsagePill.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DiskUsagePill.qml
new file mode 100644
index 0000000..827df4e
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/DiskUsagePill.qml
@@ -0,0 +1,76 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Modules.ControlCenter.Widgets
+
+CompoundPill {
+ id: root
+
+ property string mountPath: "/"
+ property string instanceId: ""
+
+ iconName: "storage"
+
+ property var selectedMount: {
+ if (!DgopService.diskMounts || DgopService.diskMounts.length === 0) {
+ return null;
+ }
+
+ const targetMount = DgopService.diskMounts.find(mount => mount.mount === mountPath);
+ return targetMount || DgopService.diskMounts.find(mount => mount.mount === "/") || DgopService.diskMounts[0];
+ }
+
+ property real usagePercent: {
+ if (!selectedMount || !selectedMount.percent) {
+ return 0;
+ }
+ const percentStr = selectedMount.percent.replace("%", "");
+ return parseFloat(percentStr) || 0;
+ }
+
+ isActive: DgopService.dgopAvailable && selectedMount !== null
+
+ primaryText: {
+ if (!DgopService.dgopAvailable) {
+ return I18n.tr("Disk Usage");
+ }
+ if (!selectedMount) {
+ return I18n.tr("No disk data");
+ }
+ return selectedMount.mount;
+ }
+
+ secondaryText: {
+ if (!DgopService.dgopAvailable) {
+ return I18n.tr("dgop not available");
+ }
+ if (!selectedMount) {
+ return I18n.tr("No disk data available");
+ }
+ return `${selectedMount.used} / ${selectedMount.size} (${usagePercent.toFixed(0)}%)`;
+ }
+
+ iconColor: {
+ if (!DgopService.dgopAvailable || !selectedMount) {
+ return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5);
+ }
+ if (usagePercent > 90) {
+ return Theme.error;
+ }
+ if (usagePercent > 75) {
+ return Theme.warning;
+ }
+ return Theme.surfaceText;
+ }
+
+ Component.onCompleted: {
+ DgopService.addRef(["diskmounts"]);
+ }
+ Component.onDestruction: {
+ DgopService.removeRef(["diskmounts"]);
+ }
+
+ onToggled: {
+ expandClicked();
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ErrorPill.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ErrorPill.qml
new file mode 100644
index 0000000..cece467
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ErrorPill.qml
@@ -0,0 +1,56 @@
+import QtQuick
+import qs.Common
+import qs.Widgets
+
+StyledRect {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property string primaryMessage: ""
+ property string secondaryMessage: ""
+
+ radius: Theme.cornerRadius
+ color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.1)
+ border.color: Theme.warning
+ border.width: 1
+
+ Row {
+ anchors.fill: parent
+ anchors.margins: Theme.spacingM
+ spacing: Theme.spacingXS
+
+ DankIcon {
+ name: "warning"
+ size: 16
+ color: Theme.warning
+ anchors.top: parent.top
+ anchors.topMargin: 2
+ }
+
+ Column {
+ width: parent.width - 16 - parent.spacing
+ spacing: Theme.spacingXS
+
+ StyledText {
+ width: parent.width
+ text: root.primaryMessage
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.warning
+ font.weight: Font.Medium
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ StyledText {
+ width: parent.width
+ text: root.secondaryMessage
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.warning
+ visible: text.length > 0
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/InputAudioSliderRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/InputAudioSliderRow.qml
new file mode 100644
index 0000000..49ea30e
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/InputAudioSliderRow.qml
@@ -0,0 +1,87 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Row {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property var defaultSource: AudioService.source
+ property color sliderTrackColor: "transparent"
+
+ height: 40
+ spacing: 0
+
+ Rectangle {
+ width: Theme.iconSize + Theme.spacingS * 2
+ height: Theme.iconSize + Theme.spacingS * 2
+ anchors.verticalCenter: parent.verticalCenter
+ radius: (Theme.iconSize + Theme.spacingS * 2) / 2
+ color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0)
+
+ DankRipple {
+ id: iconRipple
+ cornerRadius: parent.radius
+ }
+
+ MouseArea {
+ id: iconArea
+ anchors.fill: parent
+ visible: defaultSource !== null
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y)
+ onClicked: {
+ if (defaultSource) {
+ SessionData.suppressOSDTemporarily();
+ defaultSource.audio.muted = !defaultSource.audio.muted;
+ }
+ }
+ }
+
+ DankIcon {
+ anchors.centerIn: parent
+ name: {
+ if (!defaultSource)
+ return "mic_off";
+
+ let volume = defaultSource.audio.volume;
+ let muted = defaultSource.audio.muted;
+
+ if (muted || volume === 0.0)
+ return "mic_off";
+ return "mic";
+ }
+ size: Theme.iconSize
+ color: defaultSource && !defaultSource.audio.muted && defaultSource.audio.volume > 0 ? Theme.primary : Theme.surfaceText
+ }
+ }
+
+ DankSlider {
+ readonly property real actualVolumePercent: defaultSource ? Math.round(defaultSource.audio.volume * 100) : 0
+
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width - (Theme.iconSize + Theme.spacingS * 2)
+ enabled: defaultSource !== null
+ minimum: 0
+ maximum: 100
+ value: defaultSource ? Math.min(100, Math.round(defaultSource.audio.volume * 100)) : 0
+ showValue: true
+ unit: "%"
+ valueOverride: actualVolumePercent
+ thumbOutlineColor: Theme.surfaceContainer
+ trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+ onSliderValueChanged: function (newValue) {
+ if (defaultSource) {
+ SessionData.suppressOSDTemporarily();
+ defaultSource.audio.volume = newValue / 100.0;
+ if (newValue > 0 && defaultSource.audio.muted) {
+ defaultSource.audio.muted = false;
+ }
+ }
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallBatteryButton.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallBatteryButton.qml
new file mode 100644
index 0000000..02da286
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallBatteryButton.qml
@@ -0,0 +1,113 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Rectangle {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property bool isActive: BatteryService.batteryAvailable && (BatteryService.isCharging || BatteryService.isPluggedIn)
+ property bool enabled: BatteryService.batteryAvailable
+
+ signal clicked
+
+ width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48
+ height: 48
+ radius: {
+ if (Theme.cornerRadius === 0)
+ return 0;
+ return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4;
+ }
+
+ function hoverTint(base) {
+ const factor = 1.2;
+ return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
+ }
+
+ readonly property color _tileBgActive: Theme.ccTileActiveBg
+ readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+ readonly property color _tileRingActive: Theme.ccTileRing
+ readonly property color _tileIconActive: Theme.ccTileActiveText
+ readonly property color _tileIconInactive: Theme.ccTileInactiveIcon
+
+ color: {
+ if (isActive)
+ return _tileBgActive;
+ const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive;
+ return baseColor;
+ }
+ border.color: isActive ? _tileRingActive : "transparent"
+ border.width: isActive ? 1 : 0
+ antialiasing: true
+ opacity: enabled ? 1.0 : 0.6
+
+ Rectangle {
+ anchors.fill: parent
+ radius: parent.radius
+ color: hoverTint(root.color)
+ opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
+ visible: opacity > 0
+ antialiasing: true
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ }
+ }
+ }
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 4
+
+ DankIcon {
+ name: BatteryService.getBatteryIcon()
+ size: parent.parent.width * 0.25
+ color: {
+ if (BatteryService.isLowBattery && !BatteryService.isCharging) {
+ return Theme.error;
+ }
+ return isActive ? _tileIconActive : _tileIconInactive;
+ }
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ StyledText {
+ text: BatteryService.batteryAvailable ? `${BatteryService.batteryLevel}%` : ""
+ font.pixelSize: parent.parent.width * 0.15
+ font.weight: Font.Medium
+ color: {
+ if (BatteryService.isLowBattery && !BatteryService.isCharging) {
+ return Theme.error;
+ }
+ return isActive ? _tileIconActive : _tileIconInactive;
+ }
+ anchors.verticalCenter: parent.verticalCenter
+ visible: BatteryService.batteryAvailable
+ }
+ }
+
+ DankRipple {
+ id: ripple
+ cornerRadius: root.radius
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ enabled: root.enabled
+ onPressed: mouse => ripple.trigger(mouse.x, mouse.y)
+ onClicked: root.clicked()
+ }
+
+ Behavior on radius {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallDiskUsageButton.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallDiskUsageButton.qml
new file mode 100644
index 0000000..30c4e36
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallDiskUsageButton.qml
@@ -0,0 +1,129 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Rectangle {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property string mountPath: "/"
+ property string instanceId: ""
+
+ property var selectedMount: {
+ if (!DgopService.diskMounts || DgopService.diskMounts.length === 0)
+ return null;
+ const targetMount = DgopService.diskMounts.find(mount => mount.mount === mountPath);
+ return targetMount || DgopService.diskMounts.find(mount => mount.mount === "/") || DgopService.diskMounts[0];
+ }
+
+ property real usagePercent: {
+ if (!selectedMount?.percent)
+ return 0;
+ return parseFloat(selectedMount.percent.replace("%", "")) || 0;
+ }
+
+ property bool enabled: DgopService.dgopAvailable
+
+ signal clicked
+
+ width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48
+ height: 48
+ radius: Theme.cornerRadius + 4
+
+ function hoverTint(base) {
+ const factor = 1.2;
+ return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
+ }
+
+ readonly property color _tileBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+
+ color: mouseArea.containsMouse ? Theme.primaryPressed : _tileBg
+ border.color: "transparent"
+ border.width: 0
+ antialiasing: true
+ opacity: enabled ? 1.0 : 0.6
+
+ Rectangle {
+ anchors.fill: parent
+ radius: parent.radius
+ color: hoverTint(root.color)
+ opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
+ visible: opacity > 0
+ antialiasing: true
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ }
+ }
+ }
+
+ Row {
+ anchors.centerIn: parent
+ spacing: Theme.spacingXS
+
+ DankIcon {
+ anchors.verticalCenter: parent.verticalCenter
+ name: "storage"
+ size: Theme.iconSizeSmall
+ color: {
+ if (root.usagePercent > 90)
+ return Theme.error;
+ if (root.usagePercent > 75)
+ return Theme.warning;
+ return Theme.ccTileInactiveIcon;
+ }
+ }
+
+ Column {
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 0
+
+ StyledText {
+ text: root.selectedMount?.mount || root.mountPath
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.surfaceVariantText
+ elide: Text.ElideMiddle
+ width: Math.min(implicitWidth, root.width - Theme.iconSizeSmall - Theme.spacingM)
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ StyledText {
+ text: `${root.usagePercent.toFixed(0)}%`
+ font.pixelSize: Theme.fontSizeSmall
+ font.weight: Font.Bold
+ color: {
+ if (root.usagePercent > 90)
+ return Theme.error;
+ if (root.usagePercent > 75)
+ return Theme.warning;
+ return Theme.ccTileInactiveIcon;
+ }
+ }
+ }
+ }
+
+ DankRipple {
+ id: ripple
+ cornerRadius: root.radius
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ enabled: root.enabled
+ onPressed: mouse => ripple.trigger(mouse.x, mouse.y)
+ onClicked: root.clicked()
+ }
+
+ Component.onCompleted: {
+ DgopService.addRef(["diskmounts"]);
+ }
+ Component.onDestruction: {
+ DgopService.removeRef(["diskmounts"]);
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallToggleButton.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallToggleButton.qml
new file mode 100644
index 0000000..7d86947
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/SmallToggleButton.qml
@@ -0,0 +1,90 @@
+import QtQuick
+import qs.Common
+import qs.Widgets
+
+Rectangle {
+ id: root
+
+ property string iconName: ""
+ property bool isActive: false
+ property bool enabled: true
+ property real iconRotation: 0
+
+ signal clicked
+ signal iconRotationCompleted
+
+ width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48
+ height: 48
+ radius: {
+ if (Theme.cornerRadius === 0)
+ return 0;
+ return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4;
+ }
+
+ function hoverTint(base) {
+ const factor = 1.2;
+ return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
+ }
+
+ readonly property color _tileBgActive: Theme.ccTileActiveBg
+ readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+ readonly property color _tileRingActive: Theme.ccTileRing
+ readonly property color _tileIconActive: Theme.ccTileActiveText
+ readonly property color _tileIconInactive: Theme.ccTileInactiveIcon
+
+ color: {
+ if (isActive)
+ return _tileBgActive;
+ const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive;
+ return baseColor;
+ }
+ border.color: isActive ? _tileRingActive : "transparent"
+ border.width: isActive ? 1 : 0
+ antialiasing: true
+ opacity: enabled ? 1.0 : 0.6
+
+ Rectangle {
+ anchors.fill: parent
+ radius: parent.radius
+ color: hoverTint(root.color)
+ opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0)
+ visible: opacity > 0
+ antialiasing: true
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ }
+ }
+ }
+
+ DankIcon {
+ anchors.centerIn: parent
+ name: iconName
+ size: Theme.iconSize
+ color: isActive ? _tileIconActive : _tileIconInactive
+ rotation: iconRotation
+ onRotationCompleted: root.iconRotationCompleted()
+ }
+
+ DankRipple {
+ id: ripple
+ cornerRadius: root.radius
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ enabled: root.enabled
+ onPressed: mouse => ripple.trigger(mouse.x, mouse.y)
+ onClicked: root.clicked()
+ }
+
+ Behavior on radius {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ToggleButton.qml b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ToggleButton.qml
new file mode 100644
index 0000000..b8adda8
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/ControlCenter/Widgets/ToggleButton.qml
@@ -0,0 +1,134 @@
+import QtQuick
+import qs.Common
+import qs.Widgets
+
+Rectangle {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property string iconName: ""
+ property string text: ""
+ property bool isActive: false
+ property bool enabled: true
+ property string secondaryText: ""
+ property real iconRotation: 0
+
+ signal clicked
+ signal iconRotationCompleted
+
+ width: parent ? parent.width : 200
+ height: 60
+ radius: {
+ if (Theme.cornerRadius === 0)
+ return 0;
+ return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4;
+ }
+
+ readonly property color _tileBgActive: Theme.ccTileActiveBg
+ readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+ readonly property color _tileRingActive: Theme.ccTileRing
+
+ color: {
+ if (isActive)
+ return _tileBgActive;
+ const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive;
+ return baseColor;
+ }
+ border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
+ border.width: 0
+ opacity: enabled ? 1.0 : 0.6
+
+ function hoverTint(base) {
+ const factor = 1.2;
+ return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
+ }
+
+ readonly property color _containerBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
+
+ Rectangle {
+ anchors.fill: parent
+ radius: Theme.cornerRadius
+ color: mouseArea.containsMouse ? hoverTint(_containerBg) : Theme.withAlpha(_containerBg, 0)
+ opacity: mouseArea.containsMouse ? 0.08 : 0.0
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ }
+ }
+ }
+
+ Row {
+ anchors.fill: parent
+ anchors.leftMargin: Theme.spacingL + 2
+ anchors.rightMargin: Theme.spacingM
+ spacing: Theme.spacingM
+
+ DankIcon {
+ name: root.iconName
+ size: Theme.iconSize
+ color: isActive ? Theme.ccTileActiveText : Theme.ccTileInactiveIcon
+ anchors.verticalCenter: parent.verticalCenter
+ rotation: root.iconRotation
+ onRotationCompleted: root.iconRotationCompleted()
+ }
+
+ Item {
+ width: parent.width - Theme.iconSize - parent.spacing
+ height: parent.height
+
+ Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 2
+
+ StyledText {
+ width: parent.width
+ text: root.text
+ font.pixelSize: Theme.fontSizeMedium
+ color: isActive ? Theme.ccTileActiveText : Theme.surfaceText
+ font.weight: Font.Medium
+ elide: Text.ElideRight
+ wrapMode: Text.NoWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ StyledText {
+ width: parent.width
+ text: root.secondaryText
+ font.pixelSize: Theme.fontSizeSmall
+ color: isActive ? Theme.ccTileActiveText : Theme.surfaceVariantText
+ visible: text.length > 0
+ elide: Text.ElideRight
+ wrapMode: Text.NoWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ }
+ }
+
+ DankRipple {
+ id: ripple
+ cornerRadius: root.radius
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ enabled: root.enabled
+ onPressed: mouse => ripple.trigger(mouse.x, mouse.y)
+ onClicked: root.clicked()
+ }
+
+ Behavior on radius {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+}