feat: sdf blob based drawers

This commit is contained in:
2 * r + 2 * t 2026-03-25 12:04:55 +11:00
parent f15b902c0e
commit 87f33d55ee
11 changed files with 273 additions and 114 deletions

View file

@ -15,7 +15,8 @@ Item {
required property ShellScreen screen
readonly property real nonAnimWidth: x > 0 || hasCurrent ? children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth : 0
readonly property real shownWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth
readonly property real nonAnimWidth: x > 0 || hasCurrent ? shownWidth : 0
readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight
readonly property Item current: (content.item as Content)?.current ?? null

View file

@ -30,8 +30,9 @@ Item {
readonly property real nonAnimHeight: state === "visible" ? ((content.item as Content)?.nonAnimHeight ?? 0) : 0
visible: height > 0
implicitHeight: 0
visible: anchors.topMargin > -implicitHeight - 5
anchors.topMargin: -implicitHeight - 5
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth
onStateChanged: {
@ -46,32 +47,35 @@ Item {
when: root.visibilities.dashboard && Config.dashboard.enabled
PropertyChanges {
root.implicitHeight: content.implicitHeight
// root.implicitHeight: content.implicitHeight
root.anchors.topMargin: 0
}
}
transitions: [
Transition {
from: ""
to: "visible"
// from: ""
// to: "visible"
Anim {
target: root
property: "implicitHeight"
target: root.anchors
property: "topMargin"
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
},
Transition {
from: "visible"
to: ""
Anim {
target: root
property: "implicitHeight"
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
// Transition {
// from: "visible"
// to: ""
// Anim {
// target: root.anchors
// property: "topMargin"
// easing.bezierCurve: Appearance.anim.curves.emphasized
// }
// }
]
Timer {

View file

@ -6,6 +6,7 @@ import QtQuick.Effects
import Quickshell
import Quickshell.Hyprland
import Quickshell.Wayland
import Caelestia.Blobs
import qs.components
import qs.components.containers
import qs.services
@ -123,13 +124,113 @@ Variants {
shadowColor: Qt.alpha(Colours.palette.m3shadow, 0.7)
}
Border {
// Border {
// bar: bar
// }
// Backgrounds {
// panels: panels
// bar: bar
// }
BlobGroup {
id: blobGroup
color: Colours.palette.m3surface
}
BlobInvertedRect {
anchors.fill: parent
anchors.margins: -50 // Make border thicker to smooth out bulge from closed drawers
group: blobGroup
radius: Config.border.rounding
borderLeft: bar.implicitWidth - anchors.margins
borderRight: Config.border.thickness - anchors.margins
borderTop: Config.border.thickness - anchors.margins
borderBottom: Config.border.thickness - anchors.margins
}
PanelBg {
id: dashBg
group: blobGroup
panel: panels.dashboard
bar: bar
}
Backgrounds {
panels: panels
PanelBg {
id: launcherBg
group: blobGroup
panel: panels.launcher
bar: bar
deformAmount: 0.1
}
PanelBg {
id: sessionBg
group: blobGroup
panel: panels.session
bar: bar
}
PanelBg {
id: sidebarBg
group: blobGroup
panel: panels.sidebar
bar: bar
deformAmount: 0
}
PanelBg {
id: osdBg
group: blobGroup
panel: panels.osd
bar: bar
}
PanelBg {
id: notifsBg
group: blobGroup
panel: panels.notifications
bar: bar
}
PanelBg {
id: utilsBg
group: blobGroup
panel: panels.utilities
bar: bar
}
PanelBg {
id: popoutBg
group: blobGroup
panel: panels.popouts
bar: bar
x: bar.implicitWidth - (panels.popouts.isDetached ? -(win.width - panels.popouts.shownWidth) / 2 : panels.popouts.hasCurrent ? 0 : panels.popouts.shownWidth + 5)
implicitWidth: panels.popouts.shownWidth
Behavior on x {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on implicitWidth {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
}
}
@ -152,6 +253,31 @@ Variants {
screen: scope.modelData
visibilities: visibilities
bar: bar
dashboard.transform: Matrix4x4 {
matrix: dashBg.deformMatrix
}
launcher.transform: Matrix4x4 {
matrix: launcherBg.deformMatrix
}
session.transform: Matrix4x4 {
matrix: sessionBg.deformMatrix
}
sidebar.transform: Matrix4x4 {
matrix: sidebarBg.deformMatrix
}
osd.transform: Matrix4x4 {
matrix: osdBg.deformMatrix
}
notifications.transform: Matrix4x4 {
matrix: notifsBg.deformMatrix
}
utilities.transform: Matrix4x4 {
matrix: utilsBg.deformMatrix
}
popouts.transform: Matrix4x4 {
matrix: popoutBg.deformMatrix
}
}
BarWrapper {
@ -171,4 +297,17 @@ Variants {
}
}
}
component PanelBg: BlobRect {
required property Item panel
required property Item bar
property real deformAmount: 0.15
x: panel.x + bar.implicitWidth
y: panel.y + Config.border.thickness
implicitWidth: panel.width
implicitHeight: panel.height
radius: Config.border.rounding
deformScale: deformAmount / 10000
}
}

View file

@ -102,7 +102,7 @@ CustomMouseArea {
visibilities.bar = false;
}
if (panels.sidebar.width === 0) {
if (panels.sidebar.anchors.rightMargin === -panels.sidebar.implicitWidth - 5) {
// Show osd on hover
const showOsd = inRightPanel(panels.osd, x, y);

View file

@ -42,8 +42,8 @@ Item {
visibilities: root.visibilities
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: session.width + sidebar.width
anchors.right: session.left
// anchors.rightMargin: session.width + sidebar.width
}
Notifications.Wrapper {
@ -66,8 +66,8 @@ Item {
panels: root
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: sidebar.width
anchors.right: sidebar.left
// anchors.rightMargin: sidebar.width
}
Launcher.Wrapper {

View file

@ -24,8 +24,9 @@ Item {
onMaxHeightChanged: timer.start()
visible: height > 0
implicitHeight: 0
visible: anchors.bottomMargin > -implicitHeight - 5
anchors.bottomMargin: -implicitHeight - 5
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth
onShouldBeActiveChanged: {
@ -43,28 +44,30 @@ Item {
id: showAnim
Anim {
target: root
property: "implicitHeight"
to: root.contentHeight
target: root.anchors
property: "bottomMargin"
to: 0
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
ScriptAction {
script: root.implicitHeight = Qt.binding(() => content.implicitHeight)
}
// ScriptAction {
// script: root.implicitHeight = Qt.binding(() => content.implicitHeight)
// }
}
SequentialAnimation {
id: hideAnim
ScriptAction {
script: root.implicitHeight = root.implicitHeight
}
// ScriptAction {
// script: root.implicitHeight = root.implicitHeight
// }
Anim {
target: root
property: "implicitHeight"
to: 0
easing.bezierCurve: Appearance.anim.curves.emphasized
target: root.anchors
property: "bottomMargin"
to: -content.implicitHeight - 5
// easing.bezierCurve: Appearance.anim.curves.emphasized
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}

View file

@ -10,23 +10,24 @@ Item {
property alias osdPanel: content.osdPanel
property alias sessionPanel: content.sessionPanel
visible: height > 0
visible: anchors.topMargin > -implicitHeight - 5
anchors.topMargin: -5
implicitWidth: Math.max(sidebarPanel.width, content.implicitWidth)
implicitHeight: content.implicitHeight
states: State {
name: "hidden"
when: root.visibilities.sidebar && Config.sidebar.enabled
// when: root.visibilities.sidebar && Config.sidebar.enabled
PropertyChanges {
root.implicitHeight: 0
root.anchors.topMargin: -implicitHeight - 5
}
}
transitions: Transition {
Anim {
target: root
property: "implicitHeight"
target: root.anchors
property: "topMargin"
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}

View file

@ -34,8 +34,9 @@ Item {
brightness = root.monitor?.brightness ?? 0;
}
visible: width > 0
implicitWidth: 0
visible: anchors.rightMargin > -implicitWidth
anchors.rightMargin: -implicitWidth
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
states: State {
@ -43,31 +44,33 @@ Item {
when: root.shouldBeActive
PropertyChanges {
root.implicitWidth: content.implicitWidth
root.anchors.rightMargin: 0
}
}
transitions: [
Transition {
from: ""
to: "visible"
// from: ""
// to: "visible"
Anim {
target: root
property: "implicitWidth"
target: root.anchors
property: "rightMargin"
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
},
Transition {
from: "visible"
to: ""
Anim {
target: root
property: "implicitWidth"
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
// Transition {
// from: "visible"
// to: ""
// Anim {
// target: root
// property: "implicitWidth"
// easing.bezierCurve: Appearance.anim.curves.emphasized
// }
// }
]
Connections {

View file

@ -11,8 +11,9 @@ Item {
required property var panels
readonly property real nonAnimWidth: content.implicitWidth
visible: width > 0
implicitWidth: 0
visible: anchors.rightMargin > -implicitWidth - 1
anchors.rightMargin: -implicitWidth - 1
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
states: State {
@ -20,31 +21,33 @@ Item {
when: root.visibilities.session && Config.session.enabled
PropertyChanges {
root.implicitWidth: root.nonAnimWidth
root.anchors.rightMargin: 0
}
}
transitions: [
Transition {
from: ""
to: "visible"
// from: ""
// to: "visible"
Anim {
target: root
property: "implicitWidth"
target: root.anchors
property: "rightMargin"
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
},
Transition {
from: "visible"
to: ""
Anim {
target: root
property: "implicitWidth"
easing.bezierCurve: root.panels.osd.width > 0 ? Appearance.anim.curves.expressiveDefaultSpatial : Appearance.anim.curves.emphasized
}
}
// Transition {
// from: "visible"
// to: ""
// Anim {
// target: root
// property: "implicitWidth"
// easing.bezierCurve: root.panels.osd.width > 0 ? Appearance.anim.curves.expressiveDefaultSpatial : Appearance.anim.curves.emphasized
// }
// }
]
Loader {

View file

@ -11,40 +11,43 @@ Item {
required property var panels
readonly property Props props: Props {}
visible: width > 0
implicitWidth: 0
visible: anchors.rightMargin > -implicitWidth - 5
anchors.rightMargin: -implicitWidth - 5
implicitWidth: Config.sidebar.sizes.width
states: State {
name: "visible"
when: root.visibilities.sidebar && Config.sidebar.enabled
PropertyChanges {
root.implicitWidth: Config.sidebar.sizes.width
root.anchors.rightMargin: 0
}
}
transitions: [
Transition {
from: ""
to: "visible"
// from: ""
// to: "visible"
Anim {
target: root
property: "implicitWidth"
target: root.anchors
property: "rightMargin"
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
},
Transition {
from: "visible"
to: ""
Anim {
target: root
property: "implicitWidth"
easing.bezierCurve: root.panels.osd.width > 0 || root.panels.session.width > 0 ? Appearance.anim.curves.expressiveDefaultSpatial : Appearance.anim.curves.emphasized
}
}
// Transition {
// from: "visible"
// to: ""
// Anim {
// target: root
// property: "implicitWidth"
// easing.bezierCurve: root.panels.osd.width > 0 || root.panels.session.width > 0 ? Appearance.anim.curves.expressiveDefaultSpatial : Appearance.anim.curves.emphasized
// }
// }
]
Loader {

View file

@ -22,8 +22,9 @@ Item {
}
readonly property bool shouldBeActive: visibilities.sidebar || (visibilities.utilities && Config.utilities.enabled && !(visibilities.session && Config.session.enabled))
visible: height > 0
implicitHeight: 0
visible: anchors.bottomMargin > -implicitHeight - 5
anchors.bottomMargin: -implicitHeight - 5
implicitHeight: content.implicitHeight
implicitWidth: sidebar.visible ? sidebar.width : Config.utilities.sizes.width
onStateChanged: {
@ -38,32 +39,33 @@ Item {
when: root.shouldBeActive
PropertyChanges {
root.implicitHeight: content.implicitHeight + Appearance.padding.large * 2
root.anchors.bottomMargin: 0
}
}
transitions: [
Transition {
from: ""
to: "visible"
// from: ""
// to: "visible"
Anim {
target: root
property: "implicitHeight"
target: root.anchors
property: "bottomMargin"
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
},
Transition {
from: "visible"
to: ""
Anim {
target: root
property: "implicitHeight"
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
// Transition {
// from: "visible"
// to: ""
// Anim {
// target: root
// property: "implicitHeight"
// easing.bezierCurve: Appearance.anim.curves.emphasized
// }
// }
]
Timer {