// A themed popup panel anchored under a bar item, in the style of GNOME's // shell menus: near-opaque, heavily rounded, blurred behind (the blur comes // from the `qs-popover` layer rule in hypr/rules.lua), closing on outside click. // // Usage: // Popover { // id: pop // anchorItem: someBarPill // Column { ... } // } // ... // pop.visible = true import Quickshell import QtQuick import qs.config PopupWindow { id: root // The bar item this popover hangs from. property Item anchorItem: null property int contentPadding: Theme.popoverPadding default property alias content: container.data anchor.item: anchorItem // Attach to the bottom-left of the anchor and grow down-right. anchor.edges: Edges.Bottom | Edges.Left anchor.gravity: Edges.Bottom | Edges.Right anchor.margins.top: 8 implicitWidth: Math.max(container.implicitWidth + contentPadding * 2, 240) implicitHeight: container.implicitHeight + contentPadding * 2 color: "transparent" visible: false // Clicking anywhere outside dismisses the popover and clears `visible`. grabFocus: true Rectangle { id: surface anchors.fill: parent radius: Theme.popoverRadius color: Theme.alpha(Theme.bgPopover, Theme.popoverAlpha) border.width: 1 border.color: Theme.alpha(Theme.fg, 0.08) // The prism edge — see widgets/PrismEdge.qml. Sits just inside the // 1px border so the two don't fight for the same row of pixels. PrismEdge { anchors.top: parent.top anchors.topMargin: 1 anchors.left: parent.left anchors.right: parent.right inset: parent.radius } // Scale + fade in. Runs once on open, never while idle. transform: Scale { id: popScale origin.x: 0 origin.y: 0 xScale: 1 yScale: 1 } Item { id: container anchors.fill: parent anchors.margins: root.contentPadding } } onVisibleChanged: { if (visible) openAnim.restart(); } NumberAnimation { id: openAnim target: popScale property: "yScale" from: 0.96 to: 1.0 duration: Theme.durNormal easing.type: Easing.OutCubic } }