pragma ComponentBehavior: Bound import qs.config import qs.custom import qs.services import Quickshell import Quickshell.Widgets import Quickshell.Hyprland import QtQuick import QtQuick.Controls StackView { id: root required property Item popouts required property QsMenuHandle trayItem implicitWidth: currentItem.implicitWidth implicitHeight: currentItem.implicitHeight initialItem: SubMenu { handle: root.trayItem } pushEnter: NoAnim {} pushExit: NoAnim {} popEnter: NoAnim {} popExit: NoAnim {} component NoAnim: Transition { NumberAnimation { duration: 0 } } component SubMenu: Column { id: menu required property QsMenuHandle handle property bool isSubMenu property bool shown spacing: 7 opacity: shown ? 1 : 0 scale: shown ? 1 : 0.8 Component.onCompleted: shown = true StackView.onActivating: shown = true StackView.onDeactivating: shown = false StackView.onRemoved: destroy() Behavior on opacity { Anim {} } Behavior on scale { Anim {} } QsMenuOpener { id: menuOpener menu: menu.handle } Repeater { model: menuOpener.children CustomRect { id: item required property QsMenuEntry modelData implicitWidth: 200 implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight radius: 100 color: modelData.isSeparator ? Config.colors.inactive : "transparent" Loader { id: children anchors.left: parent.left anchors.right: parent.right active: !item.modelData.isSeparator asynchronous: true sourceComponent: Item { implicitHeight: label.implicitHeight StateLayer { anchors.fill: parent anchors.margins: -2 anchors.leftMargin: -7 anchors.rightMargin: -7 radius: item.radius disabled: !item.modelData.enabled function onClicked(): void { const entry = item.modelData; if (entry.hasChildren) root.push(subMenuComp.createObject(null, { handle: entry, isSubMenu: true })); else { item.modelData.triggered(); root.popouts.hasCurrent = false; } } } Loader { id: icon anchors.left: parent.left active: item.modelData.icon !== "" asynchronous: true sourceComponent: IconImage { implicitSize: label.implicitHeight source: item.modelData.icon } } CustomText { id: label anchors.left: icon.right anchors.leftMargin: icon.active ? 10 : 0 text: labelMetrics.elidedText color: item.modelData.enabled ? Config.colors.primary : Config.colors.tertiary } TextMetrics { id: labelMetrics text: item.modelData.text font.pointSize: label.font.pointSize font.family: label.font.family elide: Text.ElideRight elideWidth: 200 - (icon.active ? icon.implicitWidth + label.anchors.leftMargin : 0) - (expand.active ? expand.implicitWidth + 12 : 0) } Loader { id: expand anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right active: item.modelData.hasChildren asynchronous: true sourceComponent: MaterialIcon { text: "chevron_right" color: item.modelData.enabled ? Config.colors.primary : Config.colors.tertiary } } } } } } Loader { active: menu.isSubMenu asynchronous: true sourceComponent: Item { implicitWidth: back.implicitWidth implicitHeight: back.implicitHeight + Appearance.spacing.small / 2 Item { anchors.bottom: parent.bottom implicitWidth: back.implicitWidth implicitHeight: back.implicitHeight CustomRect { anchors.fill: parent anchors.margins: -7 anchors.leftMargin: -7 anchors.rightMargin: -14 radius: 1000 color: Config.colors.container StateLayer { anchors.fill: parent radius: parent.radius color: Config.colors.primary function onClicked(): void { root.pop(); } } } Row { id: back anchors.verticalCenter: parent.verticalCenter MaterialIcon { anchors.verticalCenter: parent.verticalCenter text: "chevron_left" color: Config.colors.primary } CustomText { anchors.verticalCenter: parent.verticalCenter text: qsTr("Back") color: Config.colors.primary } } } } } } Component { id: subMenuComp SubMenu {} } }