feat: initial commit for pixel-snapping components and helpers

This commit is contained in:
2026-10-29 17:34:57 +01:00
parent 9d8bde1413
commit 9cbb90f9e1
163 changed files with 2671 additions and 951 deletions
+83 -90
View File
@@ -5,6 +5,7 @@ import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import ZShell.Config
import ZShell.Components
import qs.Components
import qs.Effects
import qs.Services
@@ -16,115 +17,107 @@ Item {
required property NotifServer.Notif notif
Layout.fillWidth: true
implicitHeight: flickable.contentHeight
implicitHeight: actionList.implicitHeight
CustomFlickable {
id: flickable
SnapLayout {
id: actionList
anchors.fill: parent
contentHeight: actionList.implicitHeight
contentWidth: Math.max(width, actionList.implicitWidth)
spacing: Tokens.spacing.extraSmall
RowLayout {
id: actionList
Repeater {
model: [
{
isClose: true
},
...(root.notif?.actions ?? []),
{
isCopy: true
}
]
anchors.fill: parent
spacing: Tokens.spacing.extraSmall
CustomRect {
id: action
Repeater {
model: [
{
isClose: true
},
...(root.notif?.actions ?? []),
{
isCopy: true
required property var modelData
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: implicitWidth + (actionStateLayer.pressed ? Tokens.padding.large : 0)
color: Colors.layer(Colors.palette.m3surfaceContainerHighest, 4)
implicitHeight: actionInner.implicitHeight + Tokens.padding.small
implicitWidth: actionInner.implicitWidth + Tokens.padding.medium * 2
radius: actionStateLayer.pressed ? Tokens.rounding.medium / 2 : Tokens.rounding.large
Behavior on Layout.preferredWidth {
Anim {
type: Anim.FastSpatial
}
]
}
Behavior on radius {
Anim {
type: Anim.FastSpatial
}
}
CustomRect {
id: action
Timer {
id: copyTimer
required property var modelData
interval: 3000
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: implicitWidth + (actionStateLayer.pressed ? Tokens.padding.large : 0)
color: Colors.layer(Colors.palette.m3surfaceContainerHighest, 4)
implicitHeight: actionInner.implicitHeight + Tokens.padding.small
implicitWidth: actionInner.implicitWidth + Tokens.padding.medium * 2
radius: actionStateLayer.pressed ? Tokens.rounding.medium / 2 : Tokens.rounding.large
onTriggered: actionInner.item.text = "content_copy"
}
Behavior on Layout.preferredWidth {
Anim {
type: Anim.FastSpatial
StateLayer {
id: actionStateLayer
onClicked: {
if (action.modelData.isClose) {
root.notif.close();
} else if (action.modelData.isCopy) {
Quickshell.clipboardText = root.notif.body;
actionInner.item.text = "inventory";
copyTimer.start();
} else if (action.modelData.invoke) {
action.modelData.invoke();
} else if (!root.notif.resident) {
root.notif.close();
}
}
Behavior on radius {
Anim {
type: Anim.FastSpatial
}
}
Loader {
id: actionInner
anchors.centerIn: parent
sourceComponent: action.modelData.isClose || action.modelData.isCopy ? iconBtn : root.notif?.hasActionIcons ? iconComp : textComp
}
Component {
id: iconBtn
MaterialIcon {
animate: action.modelData.isCopy ?? false
color: Colors.palette.m3onSurfaceVariant
text: action.modelData.isCopy ? "content_copy" : "close"
}
}
Timer {
id: copyTimer
Component {
id: iconComp
interval: 3000
onTriggered: actionInner.item.text = "content_copy"
IconImage {
asynchronous: true
source: Quickshell.iconPath(action.modelData.identifier)
}
}
StateLayer {
id: actionStateLayer
Component {
id: textComp
onClicked: {
if (action.modelData.isClose) {
root.notif.close();
} else if (action.modelData.isCopy) {
Quickshell.clipboardText = root.notif.body;
actionInner.item.text = "inventory";
copyTimer.start();
} else if (action.modelData.invoke) {
action.modelData.invoke();
} else if (!root.notif.resident) {
root.notif.close();
}
}
}
Loader {
id: actionInner
anchors.centerIn: parent
sourceComponent: action.modelData.isClose || action.modelData.isCopy ? iconBtn : root.notif?.hasActionIcons ? iconComp : textComp
}
Component {
id: iconBtn
MaterialIcon {
animate: action.modelData.isCopy ?? false
color: Colors.palette.m3onSurfaceVariant
text: action.modelData.isCopy ? "content_copy" : "close"
}
}
Component {
id: iconComp
IconImage {
asynchronous: true
source: Quickshell.iconPath(action.modelData.identifier)
}
}
Component {
id: textComp
CustomText {
color: Colors.palette.m3onSurfaceVariant
text: action.modelData.text
}
CustomText {
color: Colors.palette.m3onSurfaceVariant
text: action.modelData.text
}
}
}