summaryrefslogtreecommitdiff
path: root/components/controls/Menu.qml
diff options
context:
space:
mode:
Diffstat (limited to 'components/controls/Menu.qml')
-rw-r--r--components/controls/Menu.qml111
1 files changed, 111 insertions, 0 deletions
diff --git a/components/controls/Menu.qml b/components/controls/Menu.qml
new file mode 100644
index 0000000..7121536
--- /dev/null
+++ b/components/controls/Menu.qml
@@ -0,0 +1,111 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import "../effects"
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+Elevation {
+ id: root
+
+ property list<MenuItem> items
+ property MenuItem active: items[0] ?? null
+ property bool expanded
+
+ signal itemSelected(item: MenuItem)
+
+ radius: Appearance.rounding.small / 2
+ level: 2
+
+ implicitWidth: column.implicitWidth
+ implicitHeight: root.expanded ? column.implicitHeight : 0
+ opacity: root.expanded ? 1 : 0
+
+ StyledClippingRect {
+ anchors.fill: parent
+ radius: parent.radius
+ color: Colours.palette.m3surfaceContainer
+
+ ColumnLayout {
+ id: column
+
+ spacing: 0
+
+ Repeater {
+ model: root.items
+
+ StyledRect {
+ id: item
+
+ required property int index
+ required property MenuItem modelData
+ readonly property bool active: modelData === root.active
+
+ Layout.fillWidth: true
+ implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.normal * 2
+ implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.normal * 2
+
+ color: Qt.alpha(Colours.palette.m3secondaryContainer, active ? 1 : 0)
+
+ StateLayer {
+ color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
+ disabled: !root.expanded
+
+ function onClicked(): void {
+ root.itemSelected(item.modelData);
+ root.active = item.modelData;
+ root.expanded = false;
+ }
+ }
+
+ RowLayout {
+ id: menuOptionRow
+
+ anchors.fill: parent
+ anchors.margins: Appearance.padding.normal
+ spacing: Appearance.spacing.small
+
+ MaterialIcon {
+ Layout.alignment: Qt.AlignVCenter
+ text: item.modelData.icon
+ color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurfaceVariant
+ }
+
+ StyledText {
+ Layout.alignment: Qt.AlignVCenter
+ Layout.fillWidth: true
+ text: item.modelData.text
+ color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
+ }
+
+ Loader {
+ Layout.alignment: Qt.AlignVCenter
+ active: item.modelData.trailingIcon.length > 0
+ visible: active
+
+ sourceComponent: MaterialIcon {
+ text: item.modelData.trailingIcon
+ color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Behavior on opacity {
+ Anim {
+ duration: Appearance.anim.durations.expressiveDefaultSpatial
+ }
+ }
+
+ Behavior on implicitHeight {
+ Anim {
+ duration: Appearance.anim.durations.expressiveDefaultSpatial
+ easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
+ }
+ }
+}