diff --git a/src/lib/components/ShapePicker.svelte b/src/lib/components/ShapePicker.svelte index 007cfbb..e6a4a45 100644 --- a/src/lib/components/ShapePicker.svelte +++ b/src/lib/components/ShapePicker.svelte @@ -14,6 +14,19 @@ const KINDS = Object.keys(SHAPES) as ShapeKind[]; let open = $state(false); let host = $state(null); + let btn = $state(null); + // The ribbon band clips its overflow and the floating box toolbar stacks above it, + // so the menu is placed from the button's rect and shown in the top layer. + let pos = $state({ top: 0, left: 0 }); + const topLayer = (node: HTMLElement) => node.showPopover(); + + function place() { + const r = btn?.getBoundingClientRect(); + if (!r) return; + const band = host?.closest('.ribbon-body')?.getBoundingClientRect(); + const left = Math.min(r.left, window.innerWidth - 220); + pos = { top: Math.max(r.bottom, band?.bottom ?? 0) + 4, left: Math.max(8, left) }; + } const label = (k: ShapeKind) => t().textBox.shapes[k]; @@ -32,14 +45,17 @@ aria-label={t().textBox.chooseShape} aria-haspopup="true" aria-expanded={open} - onclick={() => (open = !open)} + bind:this={btn} + onclick={() => { open = !open; if (open) place(); }} > {@render tile(value)} - + {#if open} -