pragma ComponentBehavior: Bound import qs.components import qs.components.controls import qs.services import qs.config import Quickshell import QtQuick import QtQuick.Layouts StyledRect { id: root required property Notifs.Notif modelData required property Props props required property bool expanded Layout.fillWidth: true implicitHeight: expanded ? summary.implicitHeight + expandedContent.implicitHeight + expandedContent.anchors.topMargin + Appearance.padding.normal * 2 : summary.implicitHeight radius: Appearance.rounding.small color: { const c = root.modelData.urgency === "critical" ? Colours.palette.m3secondaryContainer : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2); return expanded ? c : Qt.alpha(c, 0); } states: State { name: "expanded" when: root.expanded PropertyChanges { summary.anchors.margins: Appearance.padding.normal dummySummary.anchors.margins: Appearance.padding.normal compactBody.anchors.margins: Appearance.padding.normal timeStr.anchors.margins: Appearance.padding.normal expandedContent.anchors.margins: Appearance.padding.normal summary.width: root.width - Appearance.padding.normal * 2 - timeStr.implicitWidth - Appearance.spacing.small } } transitions: Transition { Anim { properties: "margins,width" } } ParallelAnimation { running: true Anim { target: root property: "opacity" from: 0 to: 1 } Anim { target: root property: "scale" from: 0.7 to: 1 } // Anim { // target: root.Layout // property: "preferredHeight" // from: 0 // to: root.implicitHeight // } } RetainableLock { object: root.modelData.notification locked: true } StyledText { id: summary anchors.top: parent.top anchors.left: parent.left width: parent.width text: root.modelData.summary color: root.modelData.urgency === "critical" ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface elide: Text.ElideRight } StyledText { id: dummySummary anchors.top: parent.top anchors.left: parent.left visible: false text: root.modelData.summary } WrappedLoader { id: compactBody shouldBeActive: !root.expanded anchors.top: parent.top anchors.left: dummySummary.right anchors.right: parent.right anchors.leftMargin: Appearance.spacing.small sourceComponent: StyledText { text: root.modelData.body.replace(/\n/g, " ") color: root.modelData.urgency === "critical" ? Colours.palette.m3secondary : Colours.palette.m3outline elide: Text.ElideRight } } WrappedLoader { id: timeStr shouldBeActive: root.expanded anchors.top: parent.top anchors.right: parent.right sourceComponent: StyledText { animate: true text: root.modelData.timeStr color: Colours.palette.m3outline font.pointSize: Appearance.font.size.small } } WrappedLoader { id: expandedContent shouldBeActive: root.expanded anchors.top: summary.bottom anchors.left: parent.left anchors.right: parent.right anchors.topMargin: Appearance.spacing.small / 2 sourceComponent: ColumnLayout { spacing: Math.floor(Appearance.spacing.small / 2) StyledText { Layout.fillWidth: true text: root.modelData.body || qsTr("No body here! :/") color: root.modelData.urgency === "critical" ? Colours.palette.m3secondary : Colours.palette.m3outline wrapMode: Text.WordWrap } } } Behavior on implicitHeight { Anim { duration: Appearance.anim.durations.expressiveDefaultSpatial easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial } } component WrappedLoader: Loader { required property bool shouldBeActive opacity: shouldBeActive ? 1 : 0 active: opacity > 0 Behavior on opacity { Anim {} } } }