fix: the Shape Format group lines up and its menu opens above the toolbar
The shape trigger stood 34px tall next to the 28px colour pickers, so its caption sat a line below theirs; every captioned picker now shares one 32px box and the border-width field centres on it. The shape menu was absolute inside the band, which clips its overflow and stacks below the floating box toolbar, so it is placed from the button's rect in the top layer, as the colour picker already does. Its caret is the same chevron as theirs.
This commit is contained in:
1 parent
cdecbee234
commit
71fc8ef942
3 files changed
+30
-12
No files matched your search
@@ -14,6 +14,19 @@
|
||||
const KINDS = Object.keys(SHAPES) as ShapeKind[];
|
||||
let open = $state(false);
|
||||
let host = $state<HTMLElement | null>(null);
|
||||
let btn = $state<HTMLElement | null>(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)}
|
||||
<span class="chevron" aria-hidden="true">▾</span>
|
||||
<svg class="chevron" width="8" height="8" viewBox="0 0 8 8" fill="none" aria-hidden="true">
|
||||
<path d="M1 2.5l3 3 3-3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{#if open}
|
||||
<div class="shape-menu" role="menu">
|
||||
<div class="shape-menu" role="menu" popover="manual" use:topLayer style="top: {pos.top}px; left: {pos.left}px">
|
||||
{#each KINDS as k}
|
||||
<button
|
||||
class="shape-tile"
|
||||
@@ -93,15 +109,16 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
.shape-btn:hover { background: var(--w-hover, rgba(0, 0, 0, 0.08)); }
|
||||
.shape-btn svg { width: 22px; height: 22px; }
|
||||
.shape-btn.compact svg { width: 18px; height: 18px; }
|
||||
.chevron { font-size: 9px; line-height: 1; }
|
||||
/* Kept below the ribbon's own 28px rule for a captioned picker, so the tile grows
|
||||
there and stays compact in the floating toolbar. */
|
||||
:where(.shape-btn) svg:first-of-type { width: 22px; height: 22px; }
|
||||
:where(.shape-btn.compact) svg:first-of-type { width: 18px; height: 18px; }
|
||||
.chevron { width: 8px; height: 8px; flex: none; }
|
||||
|
||||
.shape-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
left: 0;
|
||||
z-index: 60;
|
||||
position: fixed;
|
||||
inset: auto;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 2px;
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
.field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
gap: 6px;
|
||||
color: var(--w-text-dim);
|
||||
}
|
||||
|
||||
@@ -469,7 +469,7 @@
|
||||
padding: 2px 6px 3px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
--toolbar-btn-size: 28px;
|
||||
--toolbar-btn-size: 32px;
|
||||
}
|
||||
|
||||
/* Mirrors .rb-big's box, down to the slot it holds open for a caret, so a picker
|
||||
@@ -479,7 +479,7 @@
|
||||
baseline and carry the descender gap with it. */
|
||||
.rb-captioned > * { display: flex; }
|
||||
|
||||
.rb-captioned :is(.table-trigger, .char-trigger, .dt-trigger, .tsp-trigger, .bp-trigger, .lang-picker) {
|
||||
.rb-captioned :is(.table-trigger, .char-trigger, .dt-trigger, .tsp-trigger, .bp-trigger, .lang-picker, .shape-btn) {
|
||||
height: 32px;
|
||||
min-height: 32px;
|
||||
padding: 0;
|
||||
|
||||
Reference in new issue
Block a user