quickshell: uniform panelGap token + card-style notifications/toast

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-07-08 14:05:05 +01:00
parent 0342cbe59a
commit 1158a36d1a

View file

@ -184,6 +184,7 @@ in
readonly property int radiusSmall: 6 // workspace dots, pill buttons
readonly property int radiusTiny: 4 // hover rows, action chips
readonly property int cardPad: 8 // card inner padding (inset = 2×)
readonly property int panelGap: 8 // gap between panel border and cards (all dropdowns/menus/toast)
// Animation duration tokens (ms)
readonly property int animMorph: 280 // panel grow / slide (OutExpo)
@ -949,8 +950,8 @@ in
// Both axes animate so the panel expands from a small
// point on the column (like the top dropdowns' stub seed)
// instead of rolling out at full height.
property real openW: open ? 64 : 0
property real openH: open ? sessionCard.height + 24 : 36
property real openW: open ? sessionCard.width + 2 * Theme.panelGap : 0
property real openH: open ? sessionCard.height + 2 * Theme.panelGap : 36
Behavior on openW {
NumberAnimation { duration: Theme.animMorph; easing.type: Easing.OutExpo }
}
@ -1009,7 +1010,7 @@ in
id: sessionCard
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 8
anchors.rightMargin: Theme.panelGap
width: 48
height: sessionCol.height + 8
radius: Theme.radius
@ -2048,8 +2049,8 @@ in
id: contextMenu
alignRight: true
property var trayItem: null
fullWidth: menuItems.width + 24
fullHeight: menuItems.height + 16
fullWidth: menuItems.width + 2 * Theme.panelGap
fullHeight: menuItems.height + 2 * Theme.panelGap
onVisibleChanged: {
if (!visible) menuOpener.menu = null;
@ -2132,8 +2133,8 @@ in
BarDropdown {
id: volDropdown
alignRight: true
fullWidth: volDropdownCol.width + 28
fullHeight: volDropdownCol.height + 20
fullWidth: volDropdownCol.width + 2 * Theme.panelGap
fullHeight: volDropdownCol.height + 2 * Theme.panelGap
Column {
id: volDropdownCol
@ -2289,8 +2290,8 @@ in
BarDropdown {
id: netDropdown
alignRight: true
fullWidth: netDropdownCol.width + 28
fullHeight: netDropdownCol.height + 20
fullWidth: netDropdownCol.width + 2 * Theme.panelGap
fullHeight: netDropdownCol.height + 2 * Theme.panelGap
Column {
id: netDropdownCol
@ -2424,8 +2425,8 @@ in
BarDropdown {
id: batteryDropdown
alignRight: true
fullWidth: batteryDropdownCol.width + 28
fullHeight: batteryDropdownCol.height + 20
fullWidth: batteryDropdownCol.width + 2 * Theme.panelGap
fullHeight: batteryDropdownCol.height + 2 * Theme.panelGap
Column {
id: batteryDropdownCol
@ -2624,8 +2625,8 @@ in
BarDropdown {
id: qsDropdown
alignRight: true
fullWidth: qsCol.width + 28
fullHeight: qsCol.height + 20
fullWidth: qsCol.width + 2 * Theme.panelGap
fullHeight: qsCol.height + 2 * Theme.panelGap
Column {
id: qsCol
@ -2645,8 +2646,8 @@ in
dropdownX: bar.width / 2
// ceil: Text metrics give fractional sizes; fractional rect
// edges render as soft 2px lines
fullWidth: Math.ceil(calRow.width) + 24
fullHeight: Math.ceil(calRow.height + 8 + notifCard.height) + 24
fullWidth: Math.ceil(calRow.width) + 2 * Theme.panelGap
fullHeight: Math.ceil(calRow.height + 8 + notifCard.height) + 2 * Theme.panelGap
// Month being viewed; reset to today when the popup opens
// (via the setup function passed to bar.toggleDropdown).
@ -3060,27 +3061,31 @@ in
}
}
// Notifications: spans both columns, below the panes
Card {
// Notifications: spans both columns, below the panes.
// Header + one Card per notification, matching the media
// cards instead of base02 blocks nested inside a big card.
Column {
id: notifCard
anchors.top: calRow.bottom
anchors.topMargin: 8
anchors.horizontalCenter: parent.horizontalCenter
width: calRow.width
opacity: calRow.opacity
cardSpacing: 6
spacing: 8
Item {
width: parent.width
height: 20
SText {
anchors.left: parent.left
anchors.leftMargin: Theme.cardPad
anchors.verticalCenter: parent.verticalCenter
text: "Notifications"
font.weight: Font.Medium
}
SText {
anchors.right: parent.right
anchors.rightMargin: Theme.cardPad
anchors.verticalCenter: parent.verticalCenter
text: bar.notifServer.trackedNotifications.values.length > 0 ? "Clear all" : ""
color: Theme.base04
@ -3109,55 +3114,56 @@ in
Repeater {
model: bar.notifServer.trackedNotifications
Rectangle {
Card {
id: notifItem
required property var modelData
readonly property string previewSource: bar.notifPreviewSource(notifItem.modelData)
width: parent.width
height: Math.max(notifPreview.visible ? 48 : 0, ncBody.height) + 16
radius: Theme.radiusSmall
color: Theme.base02
// Image preview (album art, screenshot thumb)
ClippingRectangle {
id: notifPreview
visible: notifItem.previewSource !== ""
anchors.left: parent.left
anchors.top: parent.top
anchors.margins: 8
width: 48; height: 48
radius: Theme.radiusTiny
color: Theme.base01
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: notifItem.previewSource
Item {
width: parent.width
height: Math.max(notifPreview.visible ? 48 : 0, ncBody.height)
// Image preview (album art, screenshot thumb)
ClippingRectangle {
id: notifPreview
visible: notifItem.previewSource !== ""
anchors.left: parent.left
anchors.top: parent.top
width: 48; height: 48
radius: Theme.radiusTiny
color: Theme.base01
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: notifItem.previewSource
}
}
}
NotifContent {
id: ncBody
notif: notifItem.modelData
anchors.left: notifPreview.visible ? notifPreview.right : parent.left
anchors.right: dismissBtn.left
anchors.top: parent.top
anchors.margins: 8
}
NotifContent {
id: ncBody
notif: notifItem.modelData
anchors.left: notifPreview.visible ? notifPreview.right : parent.left
anchors.leftMargin: notifPreview.visible ? 8 : 0
anchors.right: dismissBtn.left
anchors.rightMargin: 8
anchors.top: parent.top
}
SIcon {
id: dismissBtn
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 8
text: "close"
color: dismissMa.containsMouse ? Theme.base05 : Theme.base03
font.pixelSize: 15
MouseArea {
id: dismissMa
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: notifItem.modelData.dismiss()
SIcon {
id: dismissBtn
anchors.right: parent.right
anchors.top: parent.top
text: "close"
color: dismissMa.containsMouse ? Theme.base05 : Theme.base03
font.pixelSize: 15
MouseArea {
id: dismissMa
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: notifItem.modelData.dismiss()
}
}
}
}
@ -3248,24 +3254,24 @@ in
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: 320
height: toastItem.toastOpen ? toastCard.height + 12 : 0
height: toastItem.toastOpen ? toastCard.height + 2 * Theme.panelGap : 0
clip: true
Behavior on height {
NumberAnimation { duration: Theme.animMorph; easing.type: Easing.OutExpo }
}
// Notification sits in a base02 rounded card, matching
// the calendar list. Inset 6px so the melt panel frames it.
// Notification sits in a cardBg card like every other
// dropdown surface, inset panelGap from the melt panel.
Rectangle {
id: toastCard
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 6
anchors.margins: Theme.panelGap
height: Math.max(toastPreview.visible ? 48 : 0, toastCol.height) + 16
radius: Theme.radiusSmall
color: Theme.base02
radius: Theme.radius
color: Theme.cardBg
property string previewSource: bar.notifPreviewSource(toastItem.currentNotif)