summaryrefslogtreecommitdiff
path: root/examples/gtk3/js/popover/Popover.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'examples/gtk3/js/popover/Popover.tsx')
-rw-r--r--examples/gtk3/js/popover/Popover.tsx90
1 files changed, 90 insertions, 0 deletions
diff --git a/examples/gtk3/js/popover/Popover.tsx b/examples/gtk3/js/popover/Popover.tsx
new file mode 100644
index 0000000..38ea01e
--- /dev/null
+++ b/examples/gtk3/js/popover/Popover.tsx
@@ -0,0 +1,90 @@
+import { Astal, Gdk, Gtk, Widget } from "astal/gtk3"
+
+const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor
+
+type PopoverProps = Pick<
+ Widget.WindowProps,
+ | "name"
+ | "namespace"
+ | "className"
+ | "visible"
+ | "child"
+ | "marginBottom"
+ | "marginTop"
+ | "marginLeft"
+ | "marginRight"
+ | "halign"
+ | "valign"
+> & {
+ onClose?(self: Widget.Window): void
+}
+
+/**
+ * Full screen window widget where you can space the child widget
+ * using margins and alignment properties.
+ *
+ * NOTE: Child widgets will assume they can span across the full window width
+ * this means that setting `wrap` or `ellipsize` on labels for example will not work
+ * without explicitly setting its `max_width_chars` property.
+ * For a workaround see Popover2.tsx
+ */
+export default function Popover({
+ child,
+ marginBottom,
+ marginTop,
+ marginLeft,
+ marginRight,
+ halign = Gtk.Align.CENTER,
+ valign = Gtk.Align.CENTER,
+ onClose,
+ ...props
+}: PopoverProps) {
+ return (
+ <window
+ {...props}
+ css="background-color: transparent"
+ keymode={Astal.Keymode.EXCLUSIVE}
+ anchor={TOP | BOTTOM | LEFT | RIGHT}
+ exclusivity={Astal.Exclusivity.IGNORE}
+ onNotifyVisible={(self) => {
+ if (!self.visible) onClose?.(self)
+ }}
+ // close when click occurs otside of child
+ onButtonPressEvent={(self, event) => {
+ const [, _x, _y] = event.get_coords()
+ const { x, y, width, height } = self
+ .get_child()!
+ .get_allocation()
+
+ const xOut = _x < x || _x > x + width
+ const yOut = _y < y || _y > y + height
+
+ // clicked outside
+ if (xOut || yOut) {
+ self.visible = false
+ }
+ }}
+ // close when hitting Escape
+ onKeyPressEvent={(self, event: Gdk.Event) => {
+ if (event.get_keyval()[1] === Gdk.KEY_Escape) {
+ self.visible = false
+ }
+ }}
+ >
+ <box
+ // make sure click event does not bubble up
+ onButtonPressEvent={() => true}
+ // child can be positioned with `halign` `valign` and margins
+ expand
+ halign={halign}
+ valign={valign}
+ marginBottom={marginBottom}
+ marginTop={marginTop}
+ marginStart={marginLeft}
+ marginEnd={marginRight}
+ >
+ {child}
+ </box>
+ </window>
+ )
+}