fix: one button height across the ribbon, and the Paragraph dialog's grid
The shared pickers frame their trigger for the classic toolbar's island; in a ribbon row of borderless buttons that reads as a different control, and at 27-28px it broke the row's line. Every trigger is 30px there now. Redrew the change-case and highlighter glyphs, which were malformed and off-centre. The dialog sized each row on its own, so a long label wrapped and "pt" vs "cm" shifted the field beside it - fixed unit width, no wrap, one 2x3 grid.
This commit is contained in:
1 parent
04eeba3432
commit
c60cb4e0de
4 files changed
+64
-29
No files matched your search
@@ -24,7 +24,9 @@
|
||||
|
||||
const ALIGNS = ['left', 'center', 'right', 'justify'] as const;
|
||||
|
||||
let align = $derived(tick >= 0 && editor ? (ALIGNS.find((a) => editor!.isActive({ textAlign: a })) ?? '') : '');
|
||||
// An unset paragraph renders left, so that's what the box shows; a selection
|
||||
// mixing two alignments still reads '' and leaves it blank.
|
||||
let align = $derived(read('textAlign', 'left'));
|
||||
let indent = $derived(read('indent', 0));
|
||||
let indentRight = $derived(read('indentRight', 0));
|
||||
let indentFirst = $derived(read('indentFirst', 0));
|
||||
@@ -78,28 +80,28 @@
|
||||
</div>
|
||||
|
||||
{#if pane === 'indents'}
|
||||
<label class="row">
|
||||
<span>{t().align.section}</span>
|
||||
<select value={align} onchange={(e) => editor?.chain().focus().setTextAlign((e.currentTarget as HTMLSelectElement).value as never).run()}>
|
||||
{#each ALIGNS as a}<option value={a}>{t().align[a]}</option>{/each}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<div class="grid">
|
||||
<label class="row"><span>{t().ribbon.indentLeft}</span><input type="text" inputmode="decimal" value={num(indent)} onchange={(e) => setNumber('indent', (e.currentTarget as HTMLInputElement).value)} /><em>cm</em></label>
|
||||
<label class="row">
|
||||
<span>{t().align.section}</span>
|
||||
<select value={align} onchange={(e) => editor?.chain().focus().setTextAlign((e.currentTarget as HTMLSelectElement).value as never).run()}>
|
||||
{#each ALIGNS as a}<option value={a}>{t().align[a]}</option>{/each}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label class="row newline"><span>{t().ribbon.indentLeft}</span><input type="text" inputmode="decimal" value={num(indent)} onchange={(e) => setNumber('indent', (e.currentTarget as HTMLInputElement).value)} /><em>cm</em></label>
|
||||
<label class="row"><span>{t().ribbon.indentRight}</span><input type="text" inputmode="decimal" value={num(indentRight)} onchange={(e) => setNumber('indentRight', (e.currentTarget as HTMLInputElement).value)} /><em>cm</em></label>
|
||||
<label class="row"><span>{t().ruler.firstLineIndent}</span><input type="text" inputmode="decimal" value={num(indentFirst)} onchange={(e) => setNumber('indentFirst', (e.currentTarget as HTMLInputElement).value)} /><em>cm</em></label>
|
||||
<span></span>
|
||||
<label class="row"><span>{t().ribbon.spaceBefore}</span><input type="text" inputmode="decimal" value={num(spaceBefore)} onchange={(e) => setNumber('spaceBefore', (e.currentTarget as HTMLInputElement).value)} /><em>pt</em></label>
|
||||
<label class="row"><span>{t().ribbon.spaceAfter}</span><input type="text" inputmode="decimal" value={num(spaceAfter)} onchange={(e) => setNumber('spaceAfter', (e.currentTarget as HTMLInputElement).value)} /><em>pt</em></label>
|
||||
</div>
|
||||
|
||||
<label class="row">
|
||||
<span>{t().toolbarExpanded.lineSpacing}</span>
|
||||
<select value={String(lineHeight)} onchange={(e) => editor?.chain().focus().setLineHeight((e.currentTarget as HTMLSelectElement).value).run()}>
|
||||
{#each ['1', '1.15', '1.5', '2'] as h}<option value={h}>{h === '1' ? t().toolbarExpanded.lineSingle : h === '2' ? t().toolbarExpanded.lineDouble : h}</option>{/each}
|
||||
</select>
|
||||
</label>
|
||||
<label class="row newline"><span>{t().ribbon.spaceBefore}</span><input type="text" inputmode="decimal" value={num(spaceBefore)} onchange={(e) => setNumber('spaceBefore', (e.currentTarget as HTMLInputElement).value)} /><em>pt</em></label>
|
||||
<label class="row"><span>{t().ribbon.spaceAfter}</span><input type="text" inputmode="decimal" value={num(spaceAfter)} onchange={(e) => setNumber('spaceAfter', (e.currentTarget as HTMLInputElement).value)} /><em>pt</em></label>
|
||||
|
||||
<label class="row newline">
|
||||
<span>{t().toolbarExpanded.lineSpacing}</span>
|
||||
<select value={String(lineHeight)} onchange={(e) => editor?.chain().focus().setLineHeight((e.currentTarget as HTMLSelectElement).value).run()}>
|
||||
{#each ['1', '1.15', '1.5', '2'] as h}<option value={h}>{h === '1' ? t().toolbarExpanded.lineSingle : h === '2' ? t().toolbarExpanded.lineDouble : h}</option>{/each}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flow">
|
||||
{#each FLOW as f}
|
||||
@@ -139,7 +141,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: 420px;
|
||||
width: 500px;
|
||||
padding: 18px 20px 16px;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 0.85rem;
|
||||
@@ -165,14 +167,18 @@
|
||||
|
||||
.tabs button.active { color: var(--color-text); border-bottom-color: var(--color-primary); }
|
||||
|
||||
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; }
|
||||
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 20px; }
|
||||
|
||||
/* Equal columns plus a fixed unit width put every field on the same edge; the
|
||||
label takes the rest and never wraps, so no row grows a second line. */
|
||||
.newline { grid-column: 1; }
|
||||
|
||||
.row { display: flex; align-items: center; gap: 8px; }
|
||||
.row > span { flex: 1; color: var(--color-text-muted); }
|
||||
.row em { font-style: normal; color: var(--color-text-muted); }
|
||||
.row > span { flex: 1; white-space: nowrap; color: var(--color-text-muted); }
|
||||
.row em { width: 1.5em; font-style: normal; color: var(--color-text-muted); }
|
||||
|
||||
.row input, .row select {
|
||||
width: 72px;
|
||||
width: 76px;
|
||||
height: 26px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius);
|
||||
@@ -182,7 +188,8 @@
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.row select { width: 130px; }
|
||||
/* No unit of its own, so it reaches across the field and unit columns. */
|
||||
.row select { width: calc(84px + 1.5em); }
|
||||
.row input { text-align: right; }
|
||||
|
||||
.flow { display: flex; flex-direction: column; gap: 8px; }
|
||||
|
||||
@@ -307,7 +307,7 @@
|
||||
--color-btn-hover: var(--w-hover);
|
||||
--font-sans: var(--w-font);
|
||||
--radius: 3px;
|
||||
--toolbar-btn-size: 28px;
|
||||
--toolbar-btn-size: 30px;
|
||||
|
||||
flex-shrink: 0;
|
||||
background: var(--w-chrome);
|
||||
@@ -317,6 +317,34 @@
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Those pickers frame their trigger for the classic toolbar's tinted island. A
|
||||
ribbon row is borderless icon buttons, so the frame comes off and the hover
|
||||
tint takes over — same 30px box as .rb-icon, so a row reads as one strip. */
|
||||
.ribbon :global(.color-split) {
|
||||
border-color: transparent;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.ribbon :global(.color-split:hover) {
|
||||
border-color: transparent;
|
||||
background: var(--w-hover);
|
||||
}
|
||||
|
||||
.ribbon :global(.color-main) {
|
||||
min-width: 28px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.ribbon :global(.color-chevron) {
|
||||
width: 13px;
|
||||
border-left: none;
|
||||
color: var(--w-text-dim);
|
||||
}
|
||||
|
||||
.ribbon :global(.color-chevron:hover) { background: var(--w-pressed); }
|
||||
|
||||
.ribbon :global(.bp-trigger) { height: 30px; }
|
||||
|
||||
.ribbon-tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -38,7 +38,7 @@ export const STROKED = {
|
||||
superscript: ['M2 12.5 7.5 5.5M2 5.5 7.5 12.5', 'M10.5 5.75a1.5 1.5 0 1 1 2.7.9L10.5 9.5h3'],
|
||||
subscript: ['M2 10.5 7.5 3.5M2 3.5 7.5 10.5', 'M10.5 9.75a1.5 1.5 0 1 1 2.7.9L10.5 13.5h3'],
|
||||
clearFormat: ['M5.5 3h7.5', 'M9.25 3 6.5 13', 'M2 9.5 5 12.5M5 9.5 2 12.5'],
|
||||
changeCase: ['M1.5 10.5 4 4l2.5 6.5M2.4 8.6h3.2', 'M9 12.25c1.2 0 2-.7 2-1.7V8.4c0-1-.7-1.6-1.9-1.6-.9 0-1.6.3-2 .8M11 7v5.25'],
|
||||
changeCase: ['M2.1 11.5 4.8 4.5l2.7 7M3.05 9.4h3.5', 'M11.8 11.5a2.15 2.15 0 1 0 0-4.3 2.15 2.15 0 0 0 0 4.3z', 'M13.95 7.2v4.3'],
|
||||
|
||||
bulletList: ['M6 4h8.5M6 8h8.5M6 12h8.5', 'M2.5 5.2a1.2 1.2 0 1 0 0-2.4 1.2 1.2 0 0 0 0 2.4z', 'M2.5 9.2a1.2 1.2 0 1 0 0-2.4 1.2 1.2 0 0 0 0 2.4z', 'M2.5 13.2a1.2 1.2 0 1 0 0-2.4 1.2 1.2 0 0 0 0 2.4z'],
|
||||
orderedList: ['M6 4h8.5M6 8h8.5M6 12h8.5', 'M1.6 2.6h.9v2.6M1.4 5.2h1.6', 'M1.3 7.1c.2-.4.6-.5 1-.4.5.1.7.6.4 1L1.4 9.4h1.7', 'M1.4 10.9h1.5l-.9 1.1c.6 0 1 .3 1 .8s-.4.8-1 .8c-.4 0-.8-.1-1-.4'],
|
||||
@@ -52,7 +52,7 @@ export const STROKED = {
|
||||
lineSpacing: ['M6.5 4h8M6.5 8h8M6.5 12h8', 'M3 4.5 3 11.5', 'M1.6 5.9 3 4.5l1.4 1.4', 'M1.6 10.1 3 11.5l1.4-1.4'],
|
||||
pilcrow: ['M9 2.5v11', 'M12 2.5v11', 'M9 2.5H6.75a2.75 2.75 0 0 0 0 5.5H9'],
|
||||
borders: ['M2.25 2.25h11.5v11.5H2.25z', 'M8 2.25v11.5M2.25 8h11.5'],
|
||||
highlighter: ['M5.5 9.5 10 5l3 3-4.5 4.5H5.5z', 'M9.25 3.25 12.75 6.75', 'M2.5 13.5h4'],
|
||||
highlighter: ['M6.5 12.5 3.5 9.5 9.5 3.5 12.5 6.5z', 'M8 5 11 8'],
|
||||
shading: ['M4 8.5 8.5 4l4 4-4.5 4.5a1.4 1.4 0 0 1-2 0L4 10.5a1.4 1.4 0 0 1 0-2z', 'M6.5 2 8.5 4', 'M2.5 13.5h11'],
|
||||
|
||||
rowAbove: ['M1.5 9h13v5.5h-13z', 'M1.5 11.75h13', 'M8 1.5v5M5.5 4h5'],
|
||||
|
||||
@@ -394,7 +394,7 @@
|
||||
.rb-combo {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
height: 28px;
|
||||
height: 30px;
|
||||
border: 1px solid var(--w-border-strong);
|
||||
border-radius: 3px;
|
||||
background: var(--w-surface);
|
||||
|
||||
Reference in new issue
Block a user