From 90a1a03fc6d2285775c4c6f8b46a252002d160db Mon Sep 17 00:00:00 2001 From: Steffen Becker Date: Wed, 2 Sep 2026 12:39:57 +0000 Subject: [PATCH] fix: a big ribbon button's label wraps onto two lines Capped at 78px, so "Display for review" costs the group a column of width instead of one of the widest buttons in the band. The caret moves up beside the icon to free that second line, which lets the split button drop its stacked layout and read as a row again. --- docs/architecture/ribbon.md | 2 +- src/lib/components/ribbon/RibbonButton.svelte | 43 +++++-------------- .../components/ribbon/tabs/TableTabs.svelte | 5 +-- 3 files changed, 13 insertions(+), 37 deletions(-) diff --git a/docs/architecture/ribbon.md b/docs/architecture/ribbon.md index a43e772..32b29c4 100644 --- a/docs/architecture/ribbon.md +++ b/docs/architecture/ribbon.md @@ -100,7 +100,7 @@ at every height. A flex row cannot reserve width in part of its height, so it mo | --- | --- | | `Ribbon.svelte` | Shell, tab state, the File menu, which contextual tabs are shown | | `RibbonGroup.svelte` | A group: its controls, its visible label, Word's ↘ dialog launcher | -| `RibbonButton.svelte` | `big` / `small` / `icon`, plus the split button. Hover paints the **icon box**, not the whole button | +| `RibbonButton.svelte` | `big` / `small` / `icon`, plus the split button. Hover paints the **icon box**, not the whole button. A big label wraps onto two lines at a 78px cap and its caret rides beside the icon, so a three-word label costs width instead of a third row | | `RibbonMenu.svelte` | The dropdown panel; its look is global CSS, since its rows come from a caller's snippet | | `Icon.svelte`, `icons.ts` | Path data on a 16-unit canvas. `pinnedStroke(size)` holds the painted stroke at ~1.5px on large glyphs and ~1.1px on small ones, so 14px and 28px icons read as one family | | `menu.svelte.ts` | The one open-menu id, `anchored`, `pinPanels`, `clickOutside` | diff --git a/src/lib/components/ribbon/RibbonButton.svelte b/src/lib/components/ribbon/RibbonButton.svelte index 1fb5ed5..c2e01bb 100644 --- a/src/lib/components/ribbon/RibbonButton.svelte +++ b/src/lib/components/ribbon/RibbonButton.svelte @@ -36,29 +36,23 @@ const ICON_SIZE = { big: 28, small: 14, icon: 20 } as const; -{#snippet face(withLabel = true)} +{#snippet face()} {#if content}{@render content()} {:else if icon}{/if} - {#if caret && !onCaret && variant === 'icon'} + {#if caret && !onCaret && variant !== 'small'} {/if} - {#if withLabel && label && variant !== 'icon'}{label}{/if} + {#if label && variant !== 'icon'}{label}{/if} {#if caret && !onCaret && variant === 'small'}{/if} - - {#if variant === 'big' && !onCaret} - {#if caret}{/if} - {/if} {/snippet} {#if caret && onCaret} - {@const stacked = variant === 'big'} - + @@ -163,12 +156,12 @@ color: inherit; } - /* Rides closer to the label than the 4px column gap: the two read as one line. */ - .rb-stack-caret { - display: flex; - height: 8px; - margin-top: -3px; - color: var(--w-text-dim); + /* The cap is what makes the wrap happen: unwrapped, a three-word label is twice + the width of the icon above it. Two lines fit the band, a third is clipped. */ + .rb-big .rb-label { + max-width: 78px; + white-space: normal; + text-align: center; } /* Split button: the two halves read as one control, so the hover outline sits on @@ -194,20 +187,6 @@ cursor: pointer; } - /* A big split button stacks, as in Word: the icon runs the command, the label - and the caret under it open the menu. Icon, label and caret each get their - own line — abreast, the caret widens the button by its own width. */ - .rb-split-col { flex-direction: column; } - .rb-split-col .rb-big { padding: 2px 6px 0; } - - .rb-split-col .rb-caret { - flex-direction: column; - width: auto; - padding: 0 6px 1px; - border-radius: 0 0 3px 3px; - color: var(--w-text); - } - .rb-caret:hover:not(:disabled) { background: var(--w-pressed); } .rb-caret:disabled { opacity: 0.4; cursor: default; } .rb-caret.active { background: var(--w-active); } diff --git a/src/lib/components/ribbon/tabs/TableTabs.svelte b/src/lib/components/ribbon/tabs/TableTabs.svelte index e727fae..de346dc 100644 --- a/src/lib/components/ribbon/tabs/TableTabs.svelte +++ b/src/lib/components/ribbon/tabs/TableTabs.svelte @@ -338,8 +338,7 @@ .rb-menu-wrap { position: relative; } /* Wrapped onto two lines, as in Word — on one they are half the group's width. - `min-content` is what keeps the button off the label's unwrapped width, and - the caret slot goes because the two lines already reach the group's foot. */ + `min-content` breaks at every space, tighter than the button's own cap. */ .inserts { display: flex; align-items: stretch; @@ -355,8 +354,6 @@ line-height: 13px; } - .inserts :global(.rb-stack-caret) { display: none; } - /* A big button wrapped in the trigger the popover hangs from; `anchored` drops the popover below the whole band, like every other ribbon menu. */ .split-trigger {