fix: the ribbon's bare icon buttons carry their labels

Layout's hyphenation, page numbers, line numbers and page decoration, and
Review's accept/reject and comment pane, all passed a label that the icon
variant drops. They are small buttons now, stacked two to a column so the band
keeps its height, with the caret after the label as a row reads.
This commit is contained in:
Steffen Becker committed 2026-08-15 00:12:24 +02:00
1 parent 3e5a546bb9
commit d0d2ea2338
3 files changed
+127 -108

No files matched your search

@@ -34,21 +34,19 @@
} = $props();
const ICON_SIZE = { big: 28, small: 14, icon: 20 } as const;
// One button when the whole of it opens the menu, and the caret joins the column
// under the label.
let stackCaret = $derived(caret && !onCaret && variant === 'big');
</script>
{#snippet face(withLabel = true)}
<span class="rb-face">
{#if content}{@render content()}
{:else if icon}<Icon name={icon} size={ICON_SIZE[variant]} />{/if}
{#if caret && !onCaret && !stackCaret}
{#if caret && !onCaret && variant === 'icon'}
<Icon name="chevronDown" size={10} />
{/if}
</span>
{#if withLabel && label && variant !== 'icon'}<span class="rb-label">{label}</span>{/if}
<!-- A row reads left to right, so its caret follows the label rather than the icon. -->
{#if caret && !onCaret && variant === 'small'}<Icon name="chevronDown" size={10} />{/if}
<!-- Held open on every big button, carrying a caret or nothing: the group centres
its controls, so one taller button lifts its own icon and label off the row. -->
{#if variant === 'big' && !onCaret}
+85 -75
View File
@@ -242,88 +242,94 @@
{/if}
</div>
<RibbonButton
icon="hyphenation"
label={t().ribbon.hyphenation}
title={t().ribbon.hyphenationHint}
active={hyphenate}
onclick={() => (hyphenate = !hyphenate)}
/>
<div class="rb-menu-wrap" use:clickOutside={'pageNum'}>
<div class="rb-col">
<RibbonButton
icon="pageNumber"
label={t().ribbon.pageNumberFormat}
title={t().ribbon.pageNumberFormat}
caret
active={isMenuOpen('pageNum')}
onclick={() => toggleMenu('pageNum')}
variant="small"
icon="hyphenation"
label={t().ribbon.hyphenation}
title={t().ribbon.hyphenationHint}
active={hyphenate}
onclick={() => (hyphenate = !hyphenate)}
/>
{#if isMenuOpen('pageNum')}
<div class="ribbon-menu" use:anchored role="menu">
<div class="rb-menu-label">{t().ribbon.pageNumberFormat}</div>
{#each PAGE_NUM_FORMATS as f}
<button class:selected={pageNumbering.format === f} onclick={() => (pageNumbering = { ...pageNumbering, format: f })}>
{[1, 2, 3].map((n) => formatOrdinal(n, f)).join(', ')}
<div class="rb-menu-wrap" use:clickOutside={'pageNum'}>
<RibbonButton
variant="small"
icon="pageNumber"
label={t().ribbon.pageNumberFormat}
title={t().ribbon.pageNumberFormat}
caret
active={isMenuOpen('pageNum')}
onclick={() => toggleMenu('pageNum')}
/>
{#if isMenuOpen('pageNum')}
<div class="ribbon-menu" use:anchored role="menu">
<div class="rb-menu-label">{t().ribbon.pageNumberFormat}</div>
{#each PAGE_NUM_FORMATS as f}
<button class:selected={pageNumbering.format === f} onclick={() => (pageNumbering = { ...pageNumbering, format: f })}>
{[1, 2, 3].map((n) => formatOrdinal(n, f)).join(', ')}
</button>
{/each}
<div class="rb-menu-label">{t().ribbon.pageNumberStart}</div>
<label class="num-row">
<input
type="number"
min="1"
max="9999"
value={pageNumbering.start}
onchange={(e) => (pageNumbering = { ...pageNumbering, start: clampPageStart(Number(e.currentTarget.value)) })}
/>
</label>
</div>
{/if}
</div>
</div>
<div class="rb-col">
<div class="rb-menu-wrap" use:clickOutside={'lineNum'}>
<RibbonButton
variant="small"
icon="lineNumbers"
label={t().ribbon.lineNumbers}
title={t().lineNumbers.title}
caret
active={isMenuOpen('lineNum') || lineNumbering.on}
onclick={() => toggleMenu('lineNum')}
/>
{#if isMenuOpen('lineNum')}
<div class="ribbon-menu" use:anchored role="menu">
<button class:selected={!lineNumbering.on} onclick={() => (lineNumbering = { ...lineNumbering, on: false })}>
{t().lineNumbers.off}
</button>
{/each}
<div class="rb-menu-label">{t().ribbon.pageNumberStart}</div>
<label class="num-row">
<input
type="number"
min="1"
max="9999"
value={pageNumbering.start}
onchange={(e) => (pageNumbering = { ...pageNumbering, start: clampPageStart(Number(e.currentTarget.value)) })}
/>
</label>
<button class:selected={lineNumbering.on && lineNumbering.restart === 'continuous'}
onclick={() => (lineNumbering = { ...lineNumbering, on: true, restart: 'continuous' })}>
{t().lineNumbers.continuous}
</button>
<button class:selected={lineNumbering.on && lineNumbering.restart === 'page'}
onclick={() => (lineNumbering = { ...lineNumbering, on: true, restart: 'page' })}>
{t().lineNumbers.perPage}
</button>
<div class="rb-menu-label">{t().lineNumbers.interval}</div>
<label class="num-row">
<input type="number" min="1" max="100" value={lineNumbering.interval}
onchange={(e) => (lineNumbering = { ...lineNumbering, interval: Math.max(1, Math.min(100, Number(e.currentTarget.value) || 1)) })} />
</label>
<label class="check-row">
<input type="checkbox" checked={lineNumbering.countEmpty}
onchange={(e) => (lineNumbering = { ...lineNumbering, countEmpty: e.currentTarget.checked })} />
{t().lineNumbers.countEmpty}
</label>
</div>
{/if}
</div>
{/if}
</div>
<div class="rb-menu-wrap" use:clickOutside={'lineNum'}>
<RibbonButton
icon="lineNumbers"
label={t().ribbon.lineNumbers}
title={t().lineNumbers.title}
caret
active={isMenuOpen('lineNum') || lineNumbering.on}
onclick={() => toggleMenu('lineNum')}
variant="small"
icon="watermark"
label={t().ribbon.pageDecor}
title={t().pageDecor.title}
active={!!(pageDecor.background || pageDecor.border || pageDecor.watermark)}
onclick={() => (decorOpen = true)}
/>
{#if isMenuOpen('lineNum')}
<div class="ribbon-menu" use:anchored role="menu">
<button class:selected={!lineNumbering.on} onclick={() => (lineNumbering = { ...lineNumbering, on: false })}>
{t().lineNumbers.off}
</button>
<button class:selected={lineNumbering.on && lineNumbering.restart === 'continuous'}
onclick={() => (lineNumbering = { ...lineNumbering, on: true, restart: 'continuous' })}>
{t().lineNumbers.continuous}
</button>
<button class:selected={lineNumbering.on && lineNumbering.restart === 'page'}
onclick={() => (lineNumbering = { ...lineNumbering, on: true, restart: 'page' })}>
{t().lineNumbers.perPage}
</button>
<div class="rb-menu-label">{t().lineNumbers.interval}</div>
<label class="num-row">
<input type="number" min="1" max="100" value={lineNumbering.interval}
onchange={(e) => (lineNumbering = { ...lineNumbering, interval: Math.max(1, Math.min(100, Number(e.currentTarget.value) || 1)) })} />
</label>
<label class="check-row">
<input type="checkbox" checked={lineNumbering.countEmpty}
onchange={(e) => (lineNumbering = { ...lineNumbering, countEmpty: e.currentTarget.checked })} />
{t().lineNumbers.countEmpty}
</label>
</div>
{/if}
</div>
<RibbonButton
icon="watermark"
label={t().ribbon.pageDecor}
title={t().pageDecor.title}
active={!!(pageDecor.background || pageDecor.border || pageDecor.watermark)}
onclick={() => (decorOpen = true)}
/>
</RibbonGroup>
<PageDecorDialog bind:open={decorOpen} bind:decor={pageDecor} />
@@ -379,6 +385,10 @@
.rb-menu-wrap { position: relative; }
/* Two rows of named commands beside the big ones, as the band is one big button tall. */
.rb-col { display: flex; flex-direction: column; gap: 2px; }
.rb-col :global(.rb-small) { width: 100%; }
.col-preview { flex-shrink: 0; }
.margin-menu, .format-menu, .breaks-menu { min-width: 230px; }
+39 -28
View File
@@ -91,6 +91,7 @@
onclick={() => onNewComment?.()}
/>
<RibbonButton
variant="small"
icon="comment"
label={t().comments.title}
title={t().comments.showPane}
@@ -110,34 +111,41 @@
active={recordChanges()}
onclick={() => setRecordChanges(!recordChanges())}
/>
<RibbonButton
icon="check"
label={t().revisions.accept}
title={t().revisions.acceptHint}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().acceptRevisions().run()}
/>
<RibbonButton
icon="close"
label={t().revisions.reject}
title={t().revisions.rejectHint}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().rejectRevisions().run()}
/>
<RibbonButton
variant="small"
icon="check"
label={t().revisions.acceptAll}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().acceptRevisions(true).run()}
/>
<RibbonButton
variant="small"
icon="close"
label={t().revisions.rejectAll}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().rejectRevisions(true).run()}
/>
<!-- The one at the cursor over the whole document, so the pair reads as one column. -->
<div class="rb-col">
<RibbonButton
variant="small"
icon="check"
label={t().revisions.accept}
title={t().revisions.acceptHint}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().acceptRevisions().run()}
/>
<RibbonButton
variant="small"
icon="check"
label={t().revisions.acceptAll}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().acceptRevisions(true).run()}
/>
</div>
<div class="rb-col">
<RibbonButton
variant="small"
icon="close"
label={t().revisions.reject}
title={t().revisions.rejectHint}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().rejectRevisions().run()}
/>
<RibbonButton
variant="small"
icon="close"
label={t().revisions.rejectAll}
disabled={!hasRevisions}
onclick={() => editor?.chain().focus().rejectRevisions(true).run()}
/>
</div>
</RibbonGroup>
<div class="ribbon-sep"></div>
@@ -153,6 +161,9 @@
.rb-menu-wrap { position: relative; }
.stats-menu { min-width: 240px; }
.rb-col { display: flex; flex-direction: column; gap: 2px; }
.rb-col :global(.rb-small) { width: 100%; }
.stat {
display: flex;
justify-content: space-between;