@beyondwork/docx-react-component 1.0.36 → 1.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +103 -13
  2. package/package.json +1 -1
  3. package/src/api/package-version.ts +13 -0
  4. package/src/api/public-types.ts +83 -0
  5. package/src/core/commands/index.ts +18 -1
  6. package/src/core/selection/mapping.ts +6 -0
  7. package/src/io/docx-session.ts +24 -9
  8. package/src/io/export/build-app-properties-xml.ts +88 -0
  9. package/src/io/export/serialize-comments.ts +6 -1
  10. package/src/io/export/serialize-footnotes.ts +10 -9
  11. package/src/io/export/serialize-headers-footers.ts +11 -10
  12. package/src/io/export/serialize-main-document.ts +337 -50
  13. package/src/io/export/serialize-numbering.ts +115 -24
  14. package/src/io/export/serialize-tables.ts +13 -11
  15. package/src/io/export/table-properties-xml.ts +35 -16
  16. package/src/io/export/twip.ts +66 -0
  17. package/src/io/normalize/normalize-text.ts +5 -0
  18. package/src/io/ooxml/parse-footnotes.ts +2 -1
  19. package/src/io/ooxml/parse-headers-footers.ts +2 -1
  20. package/src/io/ooxml/parse-main-document.ts +21 -1
  21. package/src/legal/bookmarks.ts +78 -0
  22. package/src/model/canonical-document.ts +11 -0
  23. package/src/review/store/scope-tag-diff.ts +130 -0
  24. package/src/runtime/document-navigation.ts +1 -305
  25. package/src/runtime/document-runtime.ts +173 -11
  26. package/src/runtime/layout/docx-font-loader.ts +143 -0
  27. package/src/runtime/layout/index.ts +188 -0
  28. package/src/runtime/layout/inert-layout-facet.ts +45 -0
  29. package/src/runtime/layout/layout-engine-instance.ts +618 -0
  30. package/src/runtime/layout/layout-invalidation.ts +257 -0
  31. package/src/runtime/layout/layout-measurement-provider.ts +175 -0
  32. package/src/runtime/layout/measurement-backend-canvas.ts +307 -0
  33. package/src/runtime/layout/measurement-backend-empirical.ts +208 -0
  34. package/src/runtime/layout/page-fragment-mapper.ts +179 -0
  35. package/src/runtime/layout/page-graph.ts +433 -0
  36. package/src/runtime/layout/page-layout-snapshot-adapter.ts +70 -0
  37. package/src/runtime/layout/page-story-resolver.ts +195 -0
  38. package/src/runtime/layout/paginated-layout-engine.ts +788 -0
  39. package/src/runtime/layout/public-facet.ts +705 -0
  40. package/src/runtime/layout/resolved-formatting-document.ts +317 -0
  41. package/src/runtime/layout/resolved-formatting-state.ts +430 -0
  42. package/src/runtime/scope-tag-registry.ts +95 -0
  43. package/src/runtime/surface-projection.ts +1 -0
  44. package/src/runtime/text-ack-range.ts +49 -0
  45. package/src/ui/WordReviewEditor.tsx +15 -0
  46. package/src/ui/editor-runtime-boundary.ts +10 -1
  47. package/src/ui/editor-surface-controller.tsx +3 -0
  48. package/src/ui/headless/chrome-registry.ts +235 -0
  49. package/src/ui/headless/scoped-chrome-policy.ts +164 -0
  50. package/src/ui/headless/selection-tool-context.ts +2 -0
  51. package/src/ui/headless/selection-tool-resolver.ts +36 -17
  52. package/src/ui-tailwind/editor-surface/fast-text-edit-lane.ts +333 -0
  53. package/src/ui-tailwind/editor-surface/local-edit-session-state.ts +89 -0
  54. package/src/ui-tailwind/editor-surface/perf-probe.ts +21 -1
  55. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +8 -1
  56. package/src/ui-tailwind/editor-surface/pm-decorations.ts +73 -13
  57. package/src/ui-tailwind/editor-surface/predicted-position-map.ts +78 -0
  58. package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +63 -0
  59. package/src/ui-tailwind/editor-surface/predicted-tx-gate.ts +39 -0
  60. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +173 -6
  61. package/src/ui-tailwind/theme/editor-theme.css +40 -14
  62. package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +2 -2
  63. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +235 -166
  64. package/src/ui-tailwind/tw-review-workspace.tsx +27 -1
@@ -56,9 +56,14 @@ import type {
56
56
  ZoomLevel,
57
57
  } from "../../api/public-types";
58
58
  import type { SessionCapabilities } from "../../runtime/session-capabilities";
59
+ import {
60
+ getToolbarChromePlacement,
61
+ isToolbarChromeItemVisible,
62
+ resolveScopedChromePolicy,
63
+ type ScopedChromePolicy,
64
+ } from "../../ui/headless/scoped-chrome-policy";
59
65
  import { preserveEditorSelectionMouseDown } from "../../ui/headless/preserve-editor-selection";
60
66
  import { TwHealthPanel } from "../review/tw-health-panel";
61
- import { resolveToolbarLayoutModel } from "./toolbar-layout";
62
67
  import { TwToolbarIconButton } from "./tw-toolbar-icon-button";
63
68
 
64
69
  export interface TwToolbarProps {
@@ -68,6 +73,7 @@ export interface TwToolbarProps {
68
73
  blockedReasons?: WorkflowBlockedCommandReason[];
69
74
  showDiagnosticsChrome?: boolean;
70
75
  interactionPolicy?: ToolbarInteractionPolicy;
76
+ scopedChromePolicy?: ScopedChromePolicy;
71
77
  preset?: WordReviewEditorChromePreset;
72
78
  compactMode?: boolean;
73
79
  workspaceMode: WorkspaceMode;
@@ -152,27 +158,55 @@ export function TwToolbar(props: TwToolbarProps) {
152
158
  const canEdit = props.interactionPolicy?.canFormatText ?? (caps ? caps.canEdit : false);
153
159
  const canInsertStructural = props.interactionPolicy?.canInsertStructural ?? canEdit;
154
160
  const canAddComment = props.interactionPolicy?.canAddComment ?? (caps ? caps.canAddComment : false);
155
- const showStyleSelectors = preset === "advanced";
156
- const showAdvancedFormatting = preset === "advanced";
157
- const showFormattingColors = preset !== "review";
158
- const showInsertMenu = preset === "simple" || preset === "advanced";
159
- const showTrackedChangesToggle = preset !== "simple";
160
161
  const showDiagnosticsChrome = props.showDiagnosticsChrome ?? true;
161
- const showHealth = showDiagnosticsChrome && Boolean(props.compatibility && props.warnings);
162
- const showListActions = preset === "simple" || preset === "advanced";
163
- const showUpdateActions = preset === "advanced";
164
- const showSidebarToggle = props.showSidebarToggle ?? false;
165
- const layoutModel = resolveToolbarLayoutModel({
166
- compactMode: isCompact,
162
+ const scopedChromePolicy = props.scopedChromePolicy ?? resolveScopedChromePolicy({
167
163
  preset,
168
- hasActiveListContext: Boolean(props.activeListContext),
164
+ compactMode: isCompact,
165
+ capabilities: caps,
166
+ interactionGuardSnapshot: props.interactionPolicy
167
+ ? ({
168
+ effectiveMode: props.interactionPolicy.mode,
169
+ blockedReasons: props.blockedReasons ?? [],
170
+ } as any)
171
+ : undefined,
172
+ activeListContext: props.activeListContext,
169
173
  });
174
+ const showStyleSelectors = isToolbarChromeItemVisible(scopedChromePolicy, "text-style-selectors");
175
+ const showInlineFormatting = isToolbarChromeItemVisible(scopedChromePolicy, "inline-formatting");
176
+ const showAdvancedFormatting = preset === "advanced" && showInlineFormatting;
177
+ const showTextColors = isToolbarChromeItemVisible(scopedChromePolicy, "text-colors");
178
+ const showParagraphAlignment = isToolbarChromeItemVisible(scopedChromePolicy, "paragraph-alignment");
179
+ const showInsertMenu = isToolbarChromeItemVisible(scopedChromePolicy, "insert-actions");
180
+ const showTrackedChangesToggle = isToolbarChromeItemVisible(scopedChromePolicy, "tracked-changes-toggle");
181
+ const showHealth =
182
+ showDiagnosticsChrome &&
183
+ isToolbarChromeItemVisible(scopedChromePolicy, "health") &&
184
+ Boolean(props.compatibility && props.warnings);
185
+ const showListActions = isToolbarChromeItemVisible(scopedChromePolicy, "list-actions");
186
+ const showUpdateActions = isToolbarChromeItemVisible(scopedChromePolicy, "update-actions");
187
+ const showSidebarToggle =
188
+ (props.showSidebarToggle ?? false) &&
189
+ isToolbarChromeItemVisible(scopedChromePolicy, "sidebar-toggle");
190
+ const showStyleSelectorsInRow = getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "inline";
191
+ const showListActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "list-actions") === "inline";
192
+ const showSpacingActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "indentation") === "inline";
193
+ const showListContinuationInRow =
194
+ getToolbarChromePlacement(scopedChromePolicy, "list-continuation") === "inline";
195
+ const showInsertActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "insert-actions") === "inline";
196
+ const showUpdateActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "update-actions") === "inline";
197
+ const showCompactOverflow =
198
+ getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "overflow" ||
199
+ getToolbarChromePlacement(scopedChromePolicy, "list-actions") === "overflow" ||
200
+ getToolbarChromePlacement(scopedChromePolicy, "indentation") === "overflow" ||
201
+ getToolbarChromePlacement(scopedChromePolicy, "list-continuation") === "overflow" ||
202
+ getToolbarChromePlacement(scopedChromePolicy, "insert-actions") === "overflow" ||
203
+ getToolbarChromePlacement(scopedChromePolicy, "update-actions") === "overflow";
170
204
  const showPostFormattingDivider =
171
- layoutModel.showListActionsInRow ||
172
- layoutModel.showSpacingActionsInRow ||
173
- (showInsertMenu && layoutModel.showInsertActionsInRow) ||
174
- (showUpdateActions && layoutModel.showUpdateActionsInRow) ||
175
- layoutModel.showCompactOverflow;
205
+ showListActionsInRow ||
206
+ showSpacingActionsInRow ||
207
+ showInsertActionsInRow ||
208
+ showUpdateActionsInRow ||
209
+ showCompactOverflow;
176
210
  const zoomLabel =
177
211
  typeof zoomLevel === "number"
178
212
  ? `${zoomLevel}%`
@@ -185,8 +219,8 @@ export function TwToolbar(props: TwToolbarProps) {
185
219
  className={[
186
220
  "shrink-0 rounded-xl border border-border/70 bg-canvas/92 px-2.5 shadow-[0_8px_20px_-18px_var(--color-shadow-strong)] backdrop-blur-sm",
187
221
  isCompact
188
- ? "flex min-h-11 flex-wrap items-center gap-1.5 py-2"
189
- : "flex h-11 items-center gap-1",
222
+ ? "flex min-h-10 flex-wrap items-center gap-1.5 py-1.5"
223
+ : "flex h-10 items-center gap-1",
190
224
  ].join(" ")}
191
225
  >
192
226
  {/* Left cluster: undo/redo + formatting */}
@@ -205,7 +239,7 @@ export function TwToolbar(props: TwToolbarProps) {
205
239
  />
206
240
  <div className="mx-1 h-4 w-px bg-border" />
207
241
 
208
- {showStyleSelectors && layoutModel.showStyleSelectorsInRow ? (
242
+ {showStyleSelectors && showStyleSelectorsInRow ? (
209
243
  <>
210
244
  <ToolbarParagraphStyleSelect
211
245
  disabled={!canEdit || paragraphStyles.length === 0 || !props.onSetParagraphStyle}
@@ -229,69 +263,79 @@ export function TwToolbar(props: TwToolbarProps) {
229
263
  </>
230
264
  ) : null}
231
265
 
232
- <TwToolbarIconButton
233
- icon={Bold}
234
- label="Bold"
235
- active={props.formattingState?.bold ?? false}
236
- disabled={!canEdit}
237
- onClick={props.onToggleBold}
238
- />
239
- <TwToolbarIconButton
240
- icon={Italic}
241
- label="Italic"
242
- active={props.formattingState?.italic ?? false}
243
- disabled={!canEdit}
244
- onClick={props.onToggleItalic}
245
- />
246
- <TwToolbarIconButton
247
- icon={Underline}
248
- label="Underline"
249
- active={props.formattingState?.underline ?? false}
250
- disabled={!canEdit}
251
- onClick={props.onToggleUnderline}
252
- />
253
- {showAdvancedFormatting ? (
254
- <ToolbarFormattingOverflow
255
- disabled={!canEdit}
256
- formattingState={props.formattingState}
257
- onToggleStrikethrough={props.onToggleStrikethrough}
258
- onToggleSuperscript={props.onToggleSuperscript}
259
- onToggleSubscript={props.onToggleSubscript}
260
- />
261
- ) : null}
262
- {showFormattingColors ? (
266
+ {showInlineFormatting ? (
263
267
  <>
264
- <ToolbarColorPopover
265
- ariaLabel="Text color"
266
- colors={TEXT_COLORS.map((value) => ({ value, label: value }))}
267
- disabled={!canEdit || !props.onSetTextColor}
268
- icon={<Baseline className="h-3.5 w-3.5" />}
269
- onSelect={(value) => {
270
- if (value) {
271
- props.onSetTextColor?.(value);
272
- }
273
- }}
274
- title="Text color"
268
+ <TwToolbarIconButton
269
+ icon={Bold}
270
+ label="Bold"
271
+ active={props.formattingState?.bold ?? false}
272
+ disabled={!canEdit}
273
+ onClick={props.onToggleBold}
275
274
  />
276
- <ToolbarColorPopover
277
- ariaLabel="Highlight color"
278
- colors={HIGHLIGHT_COLORS.map((entry) => ({ value: entry.value, label: entry.label }))}
279
- disabled={!canEdit || !props.onSetHighlightColor}
280
- icon={<Highlighter className="h-3.5 w-3.5" />}
281
- onSelect={(value) => props.onSetHighlightColor?.(value)}
282
- title="Highlight color"
275
+ <TwToolbarIconButton
276
+ icon={Italic}
277
+ label="Italic"
278
+ active={props.formattingState?.italic ?? false}
279
+ disabled={!canEdit}
280
+ onClick={props.onToggleItalic}
283
281
  />
284
- <ToolbarAlignmentPopover
285
- activeAlignment={props.formattingState?.alignment}
286
- disabled={!canEdit || !props.onSetAlignment}
287
- onSelect={(alignment) => props.onSetAlignment?.(alignment)}
282
+ <TwToolbarIconButton
283
+ icon={Underline}
284
+ label="Underline"
285
+ active={props.formattingState?.underline ?? false}
286
+ disabled={!canEdit}
287
+ onClick={props.onToggleUnderline}
288
288
  />
289
+ {showAdvancedFormatting ? (
290
+ <ToolbarFormattingOverflow
291
+ disabled={!canEdit}
292
+ formattingState={props.formattingState}
293
+ onToggleStrikethrough={props.onToggleStrikethrough}
294
+ onToggleSuperscript={props.onToggleSuperscript}
295
+ onToggleSubscript={props.onToggleSubscript}
296
+ />
297
+ ) : null}
298
+ </>
299
+ ) : null}
300
+ {showTextColors || showParagraphAlignment ? (
301
+ <>
302
+ {showTextColors ? (
303
+ <>
304
+ <ToolbarColorPopover
305
+ ariaLabel="Text color"
306
+ colors={TEXT_COLORS.map((value) => ({ value, label: value }))}
307
+ disabled={!canEdit || !props.onSetTextColor}
308
+ icon={<Baseline className="h-3.5 w-3.5" />}
309
+ onSelect={(value) => {
310
+ if (value) {
311
+ props.onSetTextColor?.(value);
312
+ }
313
+ }}
314
+ title="Text color"
315
+ />
316
+ <ToolbarColorPopover
317
+ ariaLabel="Highlight color"
318
+ colors={HIGHLIGHT_COLORS.map((entry) => ({ value: entry.value, label: entry.label }))}
319
+ disabled={!canEdit || !props.onSetHighlightColor}
320
+ icon={<Highlighter className="h-3.5 w-3.5" />}
321
+ onSelect={(value) => props.onSetHighlightColor?.(value)}
322
+ title="Highlight color"
323
+ />
324
+ </>
325
+ ) : null}
326
+ {showParagraphAlignment ? (
327
+ <ToolbarAlignmentPopover
328
+ activeAlignment={props.formattingState?.alignment}
329
+ disabled={!canEdit || !props.onSetAlignment}
330
+ onSelect={(alignment) => props.onSetAlignment?.(alignment)}
331
+ />
332
+ ) : null}
289
333
  </>
290
334
  ) : null}
291
335
 
292
336
  {showPostFormattingDivider ? <div className="mx-1 h-4 w-px bg-border" /> : null}
293
337
 
294
- {showListActions && layoutModel.showListActionsInRow ? (
338
+ {showListActions && showListActionsInRow ? (
295
339
  <>
296
340
  <TwToolbarIconButton
297
341
  icon={List}
@@ -309,7 +353,7 @@ export function TwToolbar(props: TwToolbarProps) {
309
353
  />
310
354
  </>
311
355
  ) : null}
312
- {layoutModel.showSpacingActionsInRow ? (
356
+ {showSpacingActionsInRow ? (
313
357
  <>
314
358
  <TwToolbarIconButton
315
359
  icon={Outdent}
@@ -325,7 +369,7 @@ export function TwToolbar(props: TwToolbarProps) {
325
369
  />
326
370
  </>
327
371
  ) : null}
328
- {layoutModel.showListContinuationInRow ? (
372
+ {showListContinuationInRow ? (
329
373
  <>
330
374
  <button
331
375
  type="button"
@@ -333,7 +377,7 @@ export function TwToolbar(props: TwToolbarProps) {
333
377
  disabled={!canEdit || !props.onRestartNumbering}
334
378
  onMouseDown={preserveEditorSelectionMouseDown}
335
379
  onClick={props.onRestartNumbering}
336
- className={`inline-flex h-7 items-center rounded-md px-2 text-xs font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
380
+ className={`inline-flex h-6 items-center rounded-md px-2 text-[11px] font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
337
381
  >
338
382
  Restart
339
383
  </button>
@@ -343,13 +387,13 @@ export function TwToolbar(props: TwToolbarProps) {
343
387
  disabled={!canEdit || !props.onContinueNumbering}
344
388
  onMouseDown={preserveEditorSelectionMouseDown}
345
389
  onClick={props.onContinueNumbering}
346
- className={`inline-flex h-7 items-center rounded-md px-2 text-xs font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
390
+ className={`inline-flex h-6 items-center rounded-md px-2 text-[11px] font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
347
391
  >
348
392
  Continue
349
393
  </button>
350
394
  </>
351
395
  ) : null}
352
- {showInsertMenu && layoutModel.showInsertActionsInRow ? (
396
+ {showInsertMenu && showInsertActionsInRow ? (
353
397
  <ToolbarInsertMenu
354
398
  disabled={!canInsertStructural}
355
399
  onInsertImage={props.onInsertImage}
@@ -358,7 +402,7 @@ export function TwToolbar(props: TwToolbarProps) {
358
402
  onInsertTable={props.onInsertTable}
359
403
  />
360
404
  ) : null}
361
- {showUpdateActions && layoutModel.showUpdateActionsInRow ? (
405
+ {showUpdateActions && showUpdateActionsInRow ? (
362
406
  <>
363
407
  <button
364
408
  type="button"
@@ -366,7 +410,7 @@ export function TwToolbar(props: TwToolbarProps) {
366
410
  disabled={!canEdit || !props.onUpdateFields}
367
411
  onMouseDown={preserveEditorSelectionMouseDown}
368
412
  onClick={props.onUpdateFields}
369
- className={`inline-flex h-7 items-center rounded-md px-2 text-xs font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
413
+ className={`inline-flex h-6 items-center rounded-md px-2 text-[11px] font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
370
414
  >
371
415
  Fields
372
416
  </button>
@@ -376,23 +420,25 @@ export function TwToolbar(props: TwToolbarProps) {
376
420
  disabled={!canEdit || !props.onUpdateTableOfContents}
377
421
  onMouseDown={preserveEditorSelectionMouseDown}
378
422
  onClick={props.onUpdateTableOfContents}
379
- className={`inline-flex h-7 items-center rounded-md px-2 text-xs font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
423
+ className={`inline-flex h-6 items-center rounded-md px-2 text-[11px] font-medium text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
380
424
  >
381
425
  TOC
382
426
  </button>
383
427
  </>
384
428
  ) : null}
385
- {layoutModel.showCompactOverflow ? (
429
+ {showCompactOverflow ? (
386
430
  <ToolbarCompactOverflow
387
431
  activeListContext={props.activeListContext}
388
432
  canEdit={canEdit}
389
433
  canInsertStructural={canInsertStructural}
390
434
  formattingState={props.formattingState}
391
435
  paragraphStyles={paragraphStyles}
392
- showInsertMenu={showInsertMenu}
393
- showListActions={showListActions}
394
- showStyleSelectors={showStyleSelectors}
395
- showUpdateActions={showUpdateActions}
436
+ showInsertMenu={getToolbarChromePlacement(scopedChromePolicy, "insert-actions") === "overflow"}
437
+ showListActions={getToolbarChromePlacement(scopedChromePolicy, "list-actions") === "overflow"}
438
+ showParagraphActions={getToolbarChromePlacement(scopedChromePolicy, "indentation") === "overflow"}
439
+ showListContinuation={getToolbarChromePlacement(scopedChromePolicy, "list-continuation") === "overflow"}
440
+ showStyleSelectors={getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "overflow"}
441
+ showUpdateActions={getToolbarChromePlacement(scopedChromePolicy, "update-actions") === "overflow"}
396
442
  onSetParagraphStyle={props.onSetParagraphStyle}
397
443
  onSetFontFamily={props.onSetFontFamily}
398
444
  onSetFontSize={props.onSetFontSize}
@@ -412,14 +458,15 @@ export function TwToolbar(props: TwToolbarProps) {
412
458
  ) : null}
413
459
 
414
460
  {/* Story focus breadcrumb — visible when editing a secondary story */}
415
- {props.activeStory && props.activeStory.kind !== "main" ? (
461
+ {props.activeStory && props.activeStory.kind !== "main" &&
462
+ isToolbarChromeItemVisible(scopedChromePolicy, "story-breadcrumb") ? (
416
463
  <>
417
464
  <div className="mx-1 h-4 w-px bg-border" />
418
465
  <button
419
466
  type="button"
420
467
  onClick={props.onCloseStory}
421
468
  onMouseDown={preserveEditorSelectionMouseDown}
422
- className={`inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-xs font-medium text-accent hover:bg-surface transition-colors outline-none ${focusRingClass}`}
469
+ className={`inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] font-medium text-accent hover:bg-surface transition-colors outline-none ${focusRingClass}`}
423
470
  aria-label={`Editing ${storyLabel(props.activeStory)} — click to return to main body`}
424
471
  >
425
472
  <span className="text-secondary">&larr;</span>
@@ -431,6 +478,14 @@ export function TwToolbar(props: TwToolbarProps) {
431
478
 
432
479
  {/* Right cluster: comment, track changes, markup, view, export */}
433
480
  <div className={`flex items-center gap-0.5 ${isCompact ? "ml-auto flex-wrap justify-end" : ""}`}>
481
+ {scopedChromePolicy.scopeStatusLabel ? (
482
+ <>
483
+ <span className="inline-flex h-6 items-center rounded-full bg-surface px-2 text-[10px] font-medium text-secondary ring-1 ring-border/50">
484
+ {scopedChromePolicy.scopeStatusLabel}
485
+ </span>
486
+ <div className="mx-1 h-4 w-px bg-border" />
487
+ </>
488
+ ) : null}
434
489
  {showSidebarToggle ? (
435
490
  <>
436
491
  <TwToolbarIconButton
@@ -443,13 +498,15 @@ export function TwToolbar(props: TwToolbarProps) {
443
498
  </>
444
499
  ) : null}
445
500
 
446
- <TwToolbarIconButton
447
- icon={MessageSquare}
448
- label="Add comment"
449
- disabled={!canAddComment}
450
- emphasis
451
- onClick={props.onAddComment}
452
- />
501
+ {isToolbarChromeItemVisible(scopedChromePolicy, "comment") ? (
502
+ <TwToolbarIconButton
503
+ icon={MessageSquare}
504
+ label="Add comment"
505
+ disabled={!canAddComment}
506
+ emphasis
507
+ onClick={props.onAddComment}
508
+ />
509
+ ) : null}
453
510
 
454
511
  {showTrackedChangesToggle ? (
455
512
  <>
@@ -460,9 +517,9 @@ export function TwToolbar(props: TwToolbarProps) {
460
517
  onPressedChange={props.onShowTrackedChangesChange}
461
518
  disabled={caps ? !caps.trackChangesSupported : false}
462
519
  onMouseDown={preserveEditorSelectionMouseDown}
463
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-canvas data-[state=on]:text-accent data-[state=on]:ring-1 data-[state=on]:ring-accent/30 data-[state=on]:shadow-sm outline-none disabled:opacity-40 ${focusRingClass}`}
520
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-canvas data-[state=on]:text-accent data-[state=on]:ring-1 data-[state=on]:ring-accent/30 data-[state=on]:shadow-sm outline-none disabled:opacity-40 ${focusRingClass}`}
464
521
  >
465
- {props.showTrackedChanges ? <Eye className="h-4 w-4" /> : <EyeOff className="h-4 w-4" />}
522
+ {props.showTrackedChanges ? <Eye className="h-3.5 w-3.5" /> : <EyeOff className="h-3.5 w-3.5" />}
466
523
  </Toggle.Root>
467
524
  </Tooltip.Trigger>
468
525
  <Tooltip.Portal>
@@ -480,21 +537,22 @@ export function TwToolbar(props: TwToolbarProps) {
480
537
  ) : null}
481
538
 
482
539
  {/* View mode toggle group: Canvas (clean, flowing) / Page (layout-sensitive) */}
483
- <ToggleGroup.Root
484
- type="single"
485
- value={workspaceMode}
486
- onValueChange={(v: string) => {
487
- if (v) props.onWorkspaceModeChange(v as WorkspaceMode);
488
- }}
489
- className="flex items-center gap-0.5"
490
- >
540
+ {isToolbarChromeItemVisible(scopedChromePolicy, "workspace-mode") ? (
541
+ <ToggleGroup.Root
542
+ type="single"
543
+ value={workspaceMode}
544
+ onValueChange={(v: string) => {
545
+ if (v) props.onWorkspaceModeChange(v as WorkspaceMode);
546
+ }}
547
+ className="flex items-center gap-0.5"
548
+ >
491
549
  <Tooltip.Root>
492
550
  <Tooltip.Trigger asChild>
493
551
  <ToggleGroup.Item
494
552
  value="canvas"
495
553
  aria-label="Canvas workspace"
496
554
  onMouseDown={preserveEditorSelectionMouseDown}
497
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-canvas data-[state=on]:text-accent data-[state=on]:ring-1 data-[state=on]:ring-accent/30 data-[state=on]:shadow-sm outline-none ${focusRingClass}`}
555
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-canvas data-[state=on]:text-accent data-[state=on]:ring-1 data-[state=on]:ring-accent/30 data-[state=on]:shadow-sm outline-none ${focusRingClass}`}
498
556
  >
499
557
  <Monitor className="h-3.5 w-3.5" />
500
558
  </ToggleGroup.Item>
@@ -511,7 +569,7 @@ export function TwToolbar(props: TwToolbarProps) {
511
569
  value="page"
512
570
  aria-label="Page workspace"
513
571
  onMouseDown={preserveEditorSelectionMouseDown}
514
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-canvas data-[state=on]:text-accent data-[state=on]:ring-1 data-[state=on]:ring-accent/30 data-[state=on]:shadow-sm outline-none ${focusRingClass}`}
572
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-canvas data-[state=on]:text-accent data-[state=on]:ring-1 data-[state=on]:ring-accent/30 data-[state=on]:shadow-sm outline-none ${focusRingClass}`}
515
573
  >
516
574
  <FileText className="h-3.5 w-3.5" />
517
575
  </ToggleGroup.Item>
@@ -522,10 +580,11 @@ export function TwToolbar(props: TwToolbarProps) {
522
580
  </Tooltip.Content>
523
581
  </Tooltip.Portal>
524
582
  </Tooltip.Root>
525
- </ToggleGroup.Root>
583
+ </ToggleGroup.Root>
584
+ ) : null}
526
585
 
527
586
  {/* Zoom controls — available in all workspace modes */}
528
- {props.onZoomChange ? (
587
+ {isToolbarChromeItemVisible(scopedChromePolicy, "zoom") && props.onZoomChange ? (
529
588
  <>
530
589
  <div className="mx-1 h-4 w-px bg-border" />
531
590
  <div className="flex items-center gap-0.5">
@@ -534,7 +593,7 @@ export function TwToolbar(props: TwToolbarProps) {
534
593
  <button
535
594
  type="button"
536
595
  aria-label="Zoom out"
537
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
596
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
538
597
  disabled={typeof zoomLevel === "number" && zoomLevel <= 50}
539
598
  onMouseDown={preserveEditorSelectionMouseDown}
540
599
  onClick={() => {
@@ -560,7 +619,7 @@ export function TwToolbar(props: TwToolbarProps) {
560
619
  type="button"
561
620
  aria-label={`Zoom: ${zoomLabel}`}
562
621
  onMouseDown={preserveEditorSelectionMouseDown}
563
- className={`inline-flex h-7 items-center justify-center rounded-md px-1.5 text-[11px] font-medium text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
622
+ className={`inline-flex h-6 items-center justify-center rounded-md px-1.5 text-[10px] font-medium text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
564
623
  >
565
624
  {zoomLabel}
566
625
  </button>
@@ -604,7 +663,7 @@ export function TwToolbar(props: TwToolbarProps) {
604
663
  <button
605
664
  type="button"
606
665
  aria-label="Zoom in"
607
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
666
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
608
667
  disabled={typeof zoomLevel === "number" && zoomLevel >= 200}
609
668
  onMouseDown={preserveEditorSelectionMouseDown}
610
669
  onClick={() => {
@@ -635,9 +694,9 @@ export function TwToolbar(props: TwToolbarProps) {
635
694
  type="button"
636
695
  aria-label="Document health"
637
696
  onMouseDown={preserveEditorSelectionMouseDown}
638
- className={`relative inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface hover:text-primary outline-none ${focusRingClass}`}
697
+ className={`relative inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface hover:text-primary outline-none ${focusRingClass}`}
639
698
  >
640
- <AlertCircle className="h-4 w-4" />
699
+ <AlertCircle className="h-3.5 w-3.5" />
641
700
  {(caps?.healthIssueCount ?? 0) > 0 ? (
642
701
  <span className="absolute -top-0.5 -right-0.5 flex h-3 min-w-[12px] items-center justify-center rounded-full bg-tertiary text-[8px] font-medium text-white">
643
702
  {caps?.healthIssueCount}
@@ -672,13 +731,15 @@ export function TwToolbar(props: TwToolbarProps) {
672
731
  </>
673
732
  ) : null}
674
733
 
675
- <TwToolbarIconButton
676
- icon={Download}
677
- label={caps?.exportBlocked ? "Export blocked" : "Download document"}
678
- disabled={caps ? !caps.canExport : true}
679
- emphasis
680
- onClick={props.onExport}
681
- />
734
+ {isToolbarChromeItemVisible(scopedChromePolicy, "export") ? (
735
+ <TwToolbarIconButton
736
+ icon={Download}
737
+ label={caps?.exportBlocked ? "Export blocked" : "Download document"}
738
+ disabled={caps ? !caps.canExport : true}
739
+ emphasis
740
+ onClick={props.onExport}
741
+ />
742
+ ) : null}
682
743
  </div>
683
744
  </header>
684
745
  );
@@ -706,7 +767,7 @@ function ToolbarParagraphStyleSelect(props: {
706
767
  aria-disabled={props.disabled || undefined}
707
768
  data-disabled={props.disabled ? "" : undefined}
708
769
  onMouseDown={preserveEditorSelectionMouseDown}
709
- className={`inline-flex h-7 min-w-[8.5rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2.5 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
770
+ className={`inline-flex h-6 min-w-[7.5rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-[11px] font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
710
771
  >
711
772
  <Select.Value placeholder="Style" />
712
773
  <Select.Icon>
@@ -723,7 +784,7 @@ function ToolbarParagraphStyleSelect(props: {
723
784
  <Select.Viewport className="p-1">
724
785
  {props.styles.map((style) => (
725
786
  <Select.Item
726
- className={`flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-canvas data-[state=checked]:text-accent data-[state=checked]:ring-1 data-[state=checked]:ring-accent/20 ${focusRingClass}`}
787
+ className={`flex cursor-pointer items-center rounded-md px-2 py-1 text-[11px] text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-canvas data-[state=checked]:text-accent data-[state=checked]:ring-1 data-[state=checked]:ring-accent/20 ${focusRingClass}`}
727
788
  key={style.styleId}
728
789
  value={style.styleId}
729
790
  >
@@ -755,7 +816,7 @@ function ToolbarFontFamilySelect(props: {
755
816
  aria-disabled={props.disabled || undefined}
756
817
  data-disabled={props.disabled ? "" : undefined}
757
818
  onMouseDown={preserveEditorSelectionMouseDown}
758
- className={`inline-flex h-7 min-w-[7rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
819
+ className={`inline-flex h-6 min-w-[6.5rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-[11px] font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
759
820
  >
760
821
  <Select.Value placeholder="Font" />
761
822
  <Select.Icon>
@@ -772,7 +833,7 @@ function ToolbarFontFamilySelect(props: {
772
833
  <Select.Viewport className="p-1">
773
834
  {FONT_FAMILIES.map((font) => (
774
835
  <Select.Item
775
- className={`flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-canvas data-[state=checked]:text-accent data-[state=checked]:ring-1 data-[state=checked]:ring-accent/20 ${focusRingClass}`}
836
+ className={`flex cursor-pointer items-center rounded-md px-2 py-1 text-[11px] text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-canvas data-[state=checked]:text-accent data-[state=checked]:ring-1 data-[state=checked]:ring-accent/20 ${focusRingClass}`}
776
837
  key={font}
777
838
  value={font}
778
839
  >
@@ -805,7 +866,7 @@ function ToolbarFontSizeSelect(props: {
805
866
  aria-disabled={props.disabled || undefined}
806
867
  data-disabled={props.disabled ? "" : undefined}
807
868
  onMouseDown={preserveEditorSelectionMouseDown}
808
- className={`inline-flex h-7 min-w-[4rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
869
+ className={`inline-flex h-6 min-w-[3.5rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-[11px] font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
809
870
  >
810
871
  <Select.Value placeholder="Size" />
811
872
  <Select.Icon>
@@ -822,7 +883,7 @@ function ToolbarFontSizeSelect(props: {
822
883
  <Select.Viewport className="p-1">
823
884
  {FONT_SIZES.map((size) => (
824
885
  <Select.Item
825
- className={`flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-canvas data-[state=checked]:text-accent data-[state=checked]:ring-1 data-[state=checked]:ring-accent/20 ${focusRingClass}`}
886
+ className={`flex cursor-pointer items-center rounded-md px-2 py-1 text-[11px] text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-canvas data-[state=checked]:text-accent data-[state=checked]:ring-1 data-[state=checked]:ring-accent/20 ${focusRingClass}`}
826
887
  key={size}
827
888
  value={String(size)}
828
889
  >
@@ -844,6 +905,8 @@ function ToolbarCompactOverflow(props: {
844
905
  paragraphStyles: StyleCatalogSnapshot["paragraphs"];
845
906
  showInsertMenu: boolean;
846
907
  showListActions: boolean;
908
+ showParagraphActions: boolean;
909
+ showListContinuation: boolean;
847
910
  showStyleSelectors: boolean;
848
911
  showUpdateActions: boolean;
849
912
  onSetParagraphStyle?: (styleId: string) => void;
@@ -891,7 +954,7 @@ function ToolbarCompactOverflow(props: {
891
954
  aria-expanded={open}
892
955
  onMouseDown={preserveEditorSelectionMouseDown}
893
956
  onClick={() => setOpen((value) => !value)}
894
- className={`inline-flex h-7 items-center gap-1 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
957
+ className={`inline-flex h-6 items-center gap-1 rounded-md border border-border bg-canvas px-2 text-[11px] font-medium text-primary transition-colors hover:bg-surface outline-none ${focusRingClass}`}
895
958
  >
896
959
  More
897
960
  <ChevronDown className="h-3.5 w-3.5 text-tertiary" />
@@ -971,31 +1034,36 @@ function ToolbarCompactOverflow(props: {
971
1034
  </div>
972
1035
  ) : null}
973
1036
 
974
- <div className="space-y-1">
975
- <div className="px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary">
976
- Paragraph
977
- </div>
978
- <ToolbarMenuButton
979
- ariaLabel="Outdent"
980
- disabled={!props.canEdit || !props.onOutdent}
981
- icon={<Outdent className="h-3.5 w-3.5" />}
982
- label="Outdent"
983
- onClick={() => {
984
- props.onOutdent?.();
985
- setOpen(false);
986
- }}
987
- />
988
- <ToolbarMenuButton
989
- ariaLabel="Indent"
990
- disabled={!props.canEdit || !props.onIndent}
991
- icon={<Indent className="h-3.5 w-3.5" />}
992
- label="Indent"
993
- onClick={() => {
994
- props.onIndent?.();
995
- setOpen(false);
996
- }}
997
- />
998
- {props.activeListContext ? (
1037
+ {props.showParagraphActions || (props.showListContinuation && props.activeListContext) ? (
1038
+ <div className="space-y-1">
1039
+ <div className="px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary">
1040
+ Paragraph
1041
+ </div>
1042
+ {props.showParagraphActions ? (
1043
+ <>
1044
+ <ToolbarMenuButton
1045
+ ariaLabel="Outdent"
1046
+ disabled={!props.canEdit || !props.onOutdent}
1047
+ icon={<Outdent className="h-3.5 w-3.5" />}
1048
+ label="Outdent"
1049
+ onClick={() => {
1050
+ props.onOutdent?.();
1051
+ setOpen(false);
1052
+ }}
1053
+ />
1054
+ <ToolbarMenuButton
1055
+ ariaLabel="Indent"
1056
+ disabled={!props.canEdit || !props.onIndent}
1057
+ icon={<Indent className="h-3.5 w-3.5" />}
1058
+ label="Indent"
1059
+ onClick={() => {
1060
+ props.onIndent?.();
1061
+ setOpen(false);
1062
+ }}
1063
+ />
1064
+ </>
1065
+ ) : null}
1066
+ {props.showListContinuation && props.activeListContext ? (
999
1067
  <>
1000
1068
  <ToolbarMenuButton
1001
1069
  ariaLabel="Restart numbering"
@@ -1018,8 +1086,9 @@ function ToolbarCompactOverflow(props: {
1018
1086
  }}
1019
1087
  />
1020
1088
  </>
1021
- ) : null}
1022
- </div>
1089
+ ) : null}
1090
+ </div>
1091
+ ) : null}
1023
1092
 
1024
1093
  {props.showInsertMenu ? (
1025
1094
  <div className="space-y-1">
@@ -1047,7 +1116,7 @@ function ToolbarCompactOverflow(props: {
1047
1116
  }}
1048
1117
  />
1049
1118
  <label
1050
- className={`flex h-8 cursor-pointer items-center gap-2 rounded-md px-2 text-left text-xs font-medium text-primary transition-colors hover:bg-surface ${
1119
+ className={`flex h-7 cursor-pointer items-center gap-2 rounded-md px-2 text-left text-[11px] font-medium text-primary transition-colors hover:bg-surface ${
1051
1120
  !props.canInsertStructural || !props.onInsertImage ? "pointer-events-none opacity-40" : ""
1052
1121
  }`}
1053
1122
  >
@@ -1131,7 +1200,7 @@ function ToolbarFormattingOverflow(props: {
1131
1200
  disabled={props.disabled}
1132
1201
  onMouseDown={preserveEditorSelectionMouseDown}
1133
1202
  onClick={() => setOpen((value) => !value)}
1134
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1203
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1135
1204
  >
1136
1205
  <MoreHorizontal className="h-3.5 w-3.5" />
1137
1206
  </button>
@@ -1206,7 +1275,7 @@ function ToolbarColorPopover(props: {
1206
1275
  disabled={props.disabled}
1207
1276
  onMouseDown={preserveEditorSelectionMouseDown}
1208
1277
  onClick={() => setOpen((value) => !value)}
1209
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1278
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1210
1279
  >
1211
1280
  {props.icon}
1212
1281
  </button>
@@ -1234,7 +1303,7 @@ function ToolbarColorPopover(props: {
1234
1303
  props.onSelect(color.value);
1235
1304
  setOpen(false);
1236
1305
  }}
1237
- className={`inline-flex h-8 items-center justify-center rounded-md border border-border text-[10px] font-medium text-primary transition-transform hover:scale-[1.04] disabled:cursor-not-allowed disabled:opacity-40 ${
1306
+ className={`inline-flex h-7 items-center justify-center rounded-md border border-border text-[10px] font-medium text-primary transition-transform hover:scale-[1.04] disabled:cursor-not-allowed disabled:opacity-40 ${
1238
1307
  color.value ? "" : "bg-surface"
1239
1308
  } ${focusRingClass}`}
1240
1309
  style={color.value ? { backgroundColor: color.value } : undefined}
@@ -1273,7 +1342,7 @@ function ToolbarAlignmentPopover(props: {
1273
1342
  disabled={props.disabled}
1274
1343
  onMouseDown={preserveEditorSelectionMouseDown}
1275
1344
  onClick={() => setOpen((value) => !value)}
1276
- className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1345
+ className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1277
1346
  >
1278
1347
  {(alignments.find((entry) => entry.value === props.activeAlignment) ?? alignments[0])?.icon}
1279
1348
  </button>
@@ -1346,7 +1415,7 @@ function ToolbarInsertMenu(props: {
1346
1415
  disabled={props.disabled}
1347
1416
  onMouseDown={preserveEditorSelectionMouseDown}
1348
1417
  onClick={() => setOpen((value) => !value)}
1349
- className={`inline-flex h-7 items-center gap-1 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1418
+ className={`inline-flex h-6 items-center gap-1 rounded-md border border-border bg-canvas px-2 text-[11px] font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1350
1419
  >
1351
1420
  Insert
1352
1421
  <ChevronDown className="h-3.5 w-3.5 text-tertiary" />
@@ -1382,7 +1451,7 @@ function ToolbarInsertMenu(props: {
1382
1451
  }}
1383
1452
  />
1384
1453
  <label
1385
- className={`flex h-8 cursor-pointer items-center gap-2 rounded-md px-2 text-xs font-medium text-primary transition-colors hover:bg-surface ${
1454
+ className={`flex h-7 cursor-pointer items-center gap-2 rounded-md px-2 text-[11px] font-medium text-primary transition-colors hover:bg-surface ${
1386
1455
  props.disabled || !props.onInsertImage ? "pointer-events-none opacity-40" : ""
1387
1456
  }`}
1388
1457
  >
@@ -1431,7 +1500,7 @@ function ToolbarPopoverActionButton(props: {
1431
1500
  disabled={props.disabled}
1432
1501
  onMouseDown={preserveEditorSelectionMouseDown}
1433
1502
  onClick={props.onClick}
1434
- className={`inline-flex h-8 items-center justify-center rounded-md border border-border transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${
1503
+ className={`inline-flex h-7 items-center justify-center rounded-md border border-border transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${
1435
1504
  props.active ? "bg-canvas text-accent ring-1 ring-accent/30 shadow-sm" : "bg-canvas text-secondary hover:bg-surface"
1436
1505
  } ${focusRingClass}`}
1437
1506
  >
@@ -1454,7 +1523,7 @@ function ToolbarMenuButton(props: {
1454
1523
  disabled={props.disabled}
1455
1524
  onMouseDown={preserveEditorSelectionMouseDown}
1456
1525
  onClick={props.onClick}
1457
- className={`flex h-8 w-full items-center gap-2 rounded-md px-2 text-left text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1526
+ className={`flex h-7 w-full items-center gap-2 rounded-md px-2 text-left text-[11px] font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass}`}
1458
1527
  >
1459
1528
  <span className="text-secondary">{props.icon}</span>
1460
1529
  <span>{props.label}</span>