hefty: bar: popup choreography

This commit is contained in:
end-4
2026-03-02 21:55:18 +01:00
parent aa4c18b86a
commit 28936dd226
5 changed files with 132 additions and 11 deletions
@@ -0,0 +1,19 @@
pragma ComponentBehavior: Bound
import QtQuick
import ".."
Item {
id: root
property real progress: 0
default property Item child
implicitWidth: child.implicitWidth
implicitHeight: child.implicitHeight
children: [child]
property var animation: Appearance.animation.elementMoveSmall.numberAnimation.createObject(this)
Behavior on progress {
animation: root.animation
}
}
@@ -0,0 +1,41 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
GridLayout {
id: root
property bool vertical: true
columns: vertical ? 1 : -1
property real totalDuration: 250
property real interval: totalDuration / count
default property list<AbstractChoreographable> choreographableChildren
readonly property int count: choreographableChildren.length
children: choreographableChildren
property bool shown: true
onShownChanged: {
// When hiding, hide all at once
if (!shown) {
for (var i = 0; i < count; i++) {
choreographableChildren[i].progress = 0;
}
}
// When showing, choreograph
root.choreographIndex = 0;
}
property int choreographIndex: count
Timer {
id: choreographTimer
interval: root.interval
property bool step: root.shown && root.choreographIndex < root.count
running: step
repeat: step
onTriggered: {
const index = root.choreographIndex;
root.choreographableChildren[index].progress = 1;
root.choreographIndex++;
}
}
}
@@ -0,0 +1,26 @@
pragma ComponentBehavior: Bound
import QtQuick
AbstractChoreographable {
id: root
progress: 0
property bool vertical: true
property bool reverseDirection: false
property real distance: 15
readonly property real directionMultiplier: reverseDirection ? -1 : 1
Component.onCompleted: syncProgress()
onProgressChanged: syncProgress()
function syncProgress() {
const progressDistance = distance * (1 - progress) * directionMultiplier;
root.child.opacity = progress
if (vertical) {
root.child.y = progressDistance
} else {
root.child.x = progressDistance
}
}
}
@@ -1,16 +1,11 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.modules.common as C
import qs.modules.common.functions as F
import qs.services as S
import qs.modules.common.widgets as W
import qs.modules.common.widgets.shapes as Shapes
import "../../../common/widgets/shapes/material-shapes.js" as MaterialShapes
import "../../../common/widgets/shapes/shapes/corner-rounding.js" as CornerRounding
import "../../../common/widgets/shapes/geometry/offset.js" as Offset
// TODO: generalize this shi for vertical
Shapes.ShapeCanvas {
@@ -21,11 +16,17 @@ Shapes.ShapeCanvas {
required property bool showPopup
required property real backgroundWidth
required property real backgroundHeight
property real popupWidth: 400
property real popupHeight: 500
property real popupContentWidth: 400
property real popupContentHeight: 500
property real popupPadding: 10
property real popupWidth: popupContentWidth + popupPadding * 2
property real popupHeight: popupContentHeight + popupPadding * 2
required property real startRadius
required property real endRadius
property real baseMargin: (parent.height - containerShape.height) / 2 // TODO vertical
readonly property real popupContentOffsetBase: -baseMargin + popupPadding
readonly property real popupContentOffsetY: spacing + popupContentOffsetBase + (atBottom ? -(popupHeight + backgroundHeight + spacing * 2) : 0)
readonly property real popupContentOffsetX: popupXOffset + popupContentOffsetBase
property alias containerShape: containerShape
property alias popupShape: popupShape
@@ -35,13 +36,13 @@ Shapes.ShapeCanvas {
function updateXInGlobal() {
xInGlobal = mapToGlobal(0, 0).x + xOffset;
}
Component.onCompleted: updateXInGlobal();
onXChanged: updateXInGlobal();
Component.onCompleted: updateXInGlobal()
onXChanged: updateXInGlobal()
readonly property real minPopupXOffset: -xInGlobal + baseMargin
readonly property real maxPopupXOffset: {
const maxPopupX = QsWindow.window.screen.width - popupWidth - baseMargin;
const maxOffset = maxPopupX - xInGlobal;
return maxOffset
return maxOffset;
}
readonly property real popupXOffset: Math.min(Math.max(-(popupWidth - containerShape.width) / 2, minPopupXOffset), maxPopupXOffset)
@@ -108,6 +109,6 @@ Shapes.ShapeCanvas {
component Anim: SpringAnimation {
spring: 3.5
damping: 0.35
damping: 0.3
}
}
@@ -41,6 +41,8 @@ HBarWidgetContainer {
backgroundWidth: root.backgroundWidth
backgroundHeight: root.backgroundHeight
popupContentWidth: popupContent.implicitWidth
popupContentHeight: popupContent.implicitHeight
startRadius: root.getBackgroundRadius(root.startSide)
endRadius: root.getBackgroundRadius(root.endSide)
}
@@ -57,6 +59,7 @@ HBarWidgetContainer {
contentImplicitWidth: vertical ? verticalContent.implicitWidth : horizontalContent.implicitWidth
contentImplicitHeight: vertical ? verticalContent.implicitHeight : horizontalContent.implicitHeight
// When horizontal
W.FadeLoader {
id: horizontalContent
anchors.fill: parent
@@ -97,9 +100,40 @@ HBarWidgetContainer {
}
}
// When vertical
W.FadeLoader {
id: verticalContent
anchors.fill: parent
}
// Popup content
W.ChoreographerGrid {
id: popupContent
anchors {
top: horizontalContent.bottom
topMargin: bgShape.popupContentOffsetY
left: horizontalContent.left
leftMargin: bgShape.popupContentOffsetX
}
shown: root.showPopup
W.FlyFadeEnterChoreographable {
W.StyledText {
text: "Kalender"
font.pixelSize: 25
}
}
W.FlyFadeEnterChoreographable {
W.StyledText {
text: "Lorem ipsum okakumalum tung\ntung tung tung"
}
}
W.FlyFadeEnterChoreographable {
W.StyledText {
text: "BAJLANDO\nUUOOOUUUOOOUUOOUOU"
}
}
}
}
}