summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankButtonGroup.qml
diff options
context:
space:
mode:
authorAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
committerAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
commit70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch)
treeab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankButtonGroup.qml
parent5d94c0a7d44a2255b81815a52a7056a94a39842d (diff)
downloadRaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz
RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankButtonGroup.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankButtonGroup.qml236
1 files changed, 236 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankButtonGroup.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankButtonGroup.qml
new file mode 100644
index 0000000..02e145e
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Widgets/DankButtonGroup.qml
@@ -0,0 +1,236 @@
+import QtQuick
+import Quickshell
+import qs.Common
+import qs.Widgets
+
+Row {
+ id: root
+
+ property var model: []
+ property int currentIndex: -1
+ property string selectionMode: "single"
+ property bool multiSelect: selectionMode === "multi"
+ property var initialSelection: []
+ property var currentSelection: initialSelection
+ property bool checkEnabled: true
+ property int buttonHeight: 40
+ property int minButtonWidth: 64
+ property int buttonPadding: Theme.spacingL
+ property int checkIconSize: Theme.iconSizeSmall
+ property int textSize: Theme.fontSizeMedium
+ property bool userInteracted: false
+
+ signal selectionChanged(int index, bool selected)
+ signal animationCompleted
+
+ spacing: Theme.spacingXS
+
+ Timer {
+ id: animationTimer
+ interval: Theme.shortDuration
+ onTriggered: {
+ root.userInteracted = false;
+ root.animationCompleted();
+ }
+ }
+
+ function isSelected(index) {
+ if (multiSelect) {
+ return repeater.itemAt(index)?.selected || false;
+ }
+ return index === currentIndex;
+ }
+
+ function selectItem(index) {
+ userInteracted = true;
+ if (multiSelect) {
+ const modelValue = model[index];
+ let newSelection = [...currentSelection];
+ const isCurrentlySelected = newSelection.includes(modelValue);
+
+ if (isCurrentlySelected) {
+ newSelection = newSelection.filter(item => item !== modelValue);
+ } else {
+ newSelection.push(modelValue);
+ }
+
+ currentSelection = newSelection;
+ selectionChanged(index, !isCurrentlySelected);
+ animationTimer.restart();
+ } else {
+ const oldIndex = currentIndex;
+ selectionChanged(index, true);
+ if (oldIndex !== index && oldIndex >= 0) {
+ selectionChanged(oldIndex, false);
+ }
+ animationTimer.restart();
+ }
+ }
+
+ Repeater {
+ id: repeater
+ model: ScriptModel {
+ values: root.model
+ }
+
+ delegate: Rectangle {
+ id: segment
+
+ property bool selected: multiSelect ? root.currentSelection.includes(modelData) : (index === root.currentIndex)
+ property bool hovered: mouseArea.containsMouse
+ property bool pressed: mouseArea.pressed
+ property bool isFirst: index === 0
+ property bool isLast: index === repeater.count - 1
+ property bool visualFirst: I18n.isRtl ? isLast : isFirst
+ property bool visualLast: I18n.isRtl ? isFirst : isLast
+ property bool prevSelected: index > 0 ? root.isSelected(index - 1) : false
+ property bool nextSelected: index < repeater.count - 1 ? root.isSelected(index + 1) : false
+
+ width: Math.max(contentItem.implicitWidth + root.buttonPadding * 2, root.minButtonWidth) + (selected ? 4 : 0)
+ height: root.buttonHeight
+
+ color: selected ? Theme.buttonBg : Theme.withAlpha(Theme.surfaceVariant, Theme.popupTransparency)
+ border.color: "transparent"
+ border.width: 0
+
+ topLeftRadius: (visualFirst || selected) ? Theme.cornerRadius : Math.min(4, Theme.cornerRadius)
+ bottomLeftRadius: (visualFirst || selected) ? Theme.cornerRadius : Math.min(4, Theme.cornerRadius)
+ topRightRadius: (visualLast || selected) ? Theme.cornerRadius : Math.min(4, Theme.cornerRadius)
+ bottomRightRadius: (visualLast || selected) ? Theme.cornerRadius : Math.min(4, Theme.cornerRadius)
+
+ Behavior on width {
+ enabled: root.userInteracted
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on topLeftRadius {
+ enabled: root.userInteracted
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on topRightRadius {
+ enabled: root.userInteracted
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on bottomLeftRadius {
+ enabled: root.userInteracted
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on bottomRightRadius {
+ enabled: root.userInteracted
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on color {
+ enabled: root.userInteracted
+ ColorAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Rectangle {
+ id: stateLayer
+ anchors.fill: parent
+ topLeftRadius: parent.topLeftRadius
+ bottomLeftRadius: parent.bottomLeftRadius
+ topRightRadius: parent.topRightRadius
+ bottomRightRadius: parent.bottomRightRadius
+ color: {
+ if (pressed)
+ return selected ? Theme.buttonPressed : Theme.surfaceTextHover;
+ if (hovered)
+ return selected ? Theme.buttonHover : Theme.surfaceTextHover;
+ return "transparent";
+ }
+
+ Behavior on color {
+ ColorAnimation {
+ duration: Theme.shorterDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+ }
+
+ DankRipple {
+ id: segmentRipple
+ cornerRadius: Theme.cornerRadius
+ rippleColor: segment.selected ? Theme.buttonText : Theme.surfaceVariantText
+ }
+
+ Item {
+ id: contentItem
+ anchors.centerIn: parent
+ implicitWidth: contentRow.implicitWidth
+ implicitHeight: contentRow.implicitHeight
+
+ Row {
+ id: contentRow
+ spacing: Theme.spacingS
+
+ DankIcon {
+ id: checkIcon
+ name: "check"
+ size: root.checkIconSize
+ color: segment.selected ? Theme.buttonText : Theme.surfaceVariantText
+ visible: root.checkEnabled && segment.selected
+ opacity: segment.selected ? 1 : 0
+ scale: segment.selected ? 1 : 0.6
+ anchors.verticalCenter: parent.verticalCenter
+
+ Behavior on opacity {
+ enabled: root.userInteracted
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on scale {
+ enabled: root.userInteracted
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.emphasizedEasing
+ }
+ }
+ }
+
+ StyledText {
+ id: buttonText
+ text: typeof modelData === "string" ? modelData : modelData.text || ""
+ font.pixelSize: root.textSize
+ font.weight: segment.selected ? Font.Medium : Font.Normal
+ color: segment.selected ? Theme.buttonText : Theme.surfaceVariantText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onPressed: mouse => segmentRipple.trigger(mouse.x, mouse.y)
+ onClicked: root.selectItem(index)
+ }
+ }
+ }
+}