@ponchia/ui 0.12.0 → 0.14.0

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 (71) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +4 -4
  3. package/behaviors/command.d.ts +34 -13
  4. package/behaviors/command.d.ts.map +1 -1
  5. package/behaviors/command.js +195 -129
  6. package/classes/classes.json +17 -2
  7. package/classes/index.d.ts +12 -0
  8. package/classes/index.js +14 -2
  9. package/classes/vscode.css-custom-data.json +64 -0
  10. package/css/base.css +2 -2
  11. package/css/blocknote.css +61 -0
  12. package/css/clamp.css +2 -2
  13. package/css/content.css +160 -1
  14. package/css/disclosure.css +10 -10
  15. package/css/feedback.css +95 -3
  16. package/css/fonts-inter.css +35 -0
  17. package/css/fonts-jetbrains-mono.css +49 -0
  18. package/css/forms.css +8 -8
  19. package/css/primitives.css +5 -6
  20. package/css/row.css +2 -2
  21. package/css/site.css +0 -31
  22. package/css/term.css +2 -2
  23. package/css/textref.css +2 -2
  24. package/css/toc.css +2 -2
  25. package/css/tokens.css +43 -0
  26. package/css/tool.css +29 -0
  27. package/css/workbench.css +2 -2
  28. package/dist/bronto.css +1 -1
  29. package/dist/css/base.css +1 -1
  30. package/dist/css/blocknote.css +1 -0
  31. package/dist/css/clamp.css +1 -1
  32. package/dist/css/content.css +1 -1
  33. package/dist/css/disclosure.css +1 -1
  34. package/dist/css/feedback.css +1 -1
  35. package/dist/css/fonts-inter.css +1 -0
  36. package/dist/css/fonts-jetbrains-mono.css +1 -0
  37. package/dist/css/forms.css +1 -1
  38. package/dist/css/report-kit.css +1 -1
  39. package/dist/css/row.css +1 -1
  40. package/dist/css/site.css +1 -1
  41. package/dist/css/term.css +1 -1
  42. package/dist/css/textref.css +1 -1
  43. package/dist/css/toc.css +1 -1
  44. package/dist/css/tokens.css +1 -1
  45. package/dist/css/tool.css +1 -0
  46. package/dist/css/workbench.css +1 -1
  47. package/docs/command.md +47 -7
  48. package/docs/compositions.md +2 -2
  49. package/docs/interop/blocknote.md +60 -0
  50. package/docs/package-contract.md +11 -2
  51. package/docs/reference.md +27 -1
  52. package/docs/reporting.md +8 -8
  53. package/docs/stability.md +5 -2
  54. package/docs/theming.md +56 -2
  55. package/docs/usage.md +55 -0
  56. package/fonts/OFL-Inter.txt +92 -0
  57. package/fonts/OFL-JetBrainsMono.txt +93 -0
  58. package/fonts/inter-variable-italic.woff2 +0 -0
  59. package/fonts/inter-variable.woff2 +0 -0
  60. package/fonts/jetbrains-mono-400-italic.woff2 +0 -0
  61. package/fonts/jetbrains-mono-400.woff2 +0 -0
  62. package/fonts/jetbrains-mono-700-italic.woff2 +0 -0
  63. package/fonts/jetbrains-mono-700.woff2 +0 -0
  64. package/llms.txt +1 -1
  65. package/package.json +18 -10
  66. package/tokens/figma.variables.json +240 -0
  67. package/tokens/index.d.ts +2 -2
  68. package/tokens/index.js +30 -2
  69. package/tokens/index.json +32 -0
  70. package/tokens/resolved.json +17 -1
  71. package/tokens/tokens.dtcg.json +190 -0
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$comment": "@ponchia/ui class vocabulary as language-neutral data — validate emitted markup without executing the ESM cls map or parsing the .d.ts. Generated from classes/index.js — do not edit by hand; run `npm run classes:json:build`. Drift-checked in CI. `groups[].base` is null for a parts-only namespace (no standalone base class — do NOT emit it). A modifier whose name contains `__` (e.g. `ui-spark__bar--pos`) attaches to THAT part, not the base host. `states` is the author-applied `is-*` hooks (runtime/behavior-managed hooks are excluded); `behaviorAttributes` are the `data-bronto-*` wiring hooks the optional behaviors delegate on; `requiredAria` is the role/aria a generator must emit per component. `states` + `customProperties` are documented in docs/reference.md and ship outside `cls` by design.",
3
3
  "counts": {
4
- "classes": 695,
5
- "groups": 187
4
+ "classes": 700,
5
+ "groups": 188
6
6
  },
7
7
  "groups": {
8
8
  "ui-accordion": {
@@ -23,6 +23,7 @@
23
23
  "base": "ui-alert",
24
24
  "modifiers": [
25
25
  "ui-alert--accent",
26
+ "ui-alert--band",
26
27
  "ui-alert--danger",
27
28
  "ui-alert--info",
28
29
  "ui-alert--success",
@@ -195,6 +196,14 @@
195
196
  ],
196
197
  "parts": []
197
198
  },
199
+ "ui-body-state": {
200
+ "base": "ui-body-state",
201
+ "modifiers": [
202
+ "ui-body-state--error",
203
+ "ui-body-state--stale"
204
+ ],
205
+ "parts": []
206
+ },
198
207
  "ui-bracket-note": {
199
208
  "base": "ui-bracket-note",
200
209
  "modifiers": [
@@ -993,6 +1002,7 @@
993
1002
  "ui-prose": {
994
1003
  "base": "ui-prose",
995
1004
  "modifiers": [
1005
+ "ui-prose--blocks",
996
1006
  "ui-prose--compact"
997
1007
  ],
998
1008
  "parts": []
@@ -1603,6 +1613,7 @@
1603
1613
  "ui-activity",
1604
1614
  "ui-alert",
1605
1615
  "ui-alert--accent",
1616
+ "ui-alert--band",
1606
1617
  "ui-alert--danger",
1607
1618
  "ui-alert--info",
1608
1619
  "ui-alert--success",
@@ -1684,6 +1695,9 @@
1684
1695
  "ui-badge--muted",
1685
1696
  "ui-badge--success",
1686
1697
  "ui-badge--warning",
1698
+ "ui-body-state",
1699
+ "ui-body-state--error",
1700
+ "ui-body-state--stale",
1687
1701
  "ui-bracket-note",
1688
1702
  "ui-bracket-note--accent",
1689
1703
  "ui-bracket-note--danger",
@@ -2040,6 +2054,7 @@
2040
2054
  "ui-property__label",
2041
2055
  "ui-property__value",
2042
2056
  "ui-prose",
2057
+ "ui-prose--blocks",
2043
2058
  "ui-prose--compact",
2044
2059
  "ui-provenance",
2045
2060
  "ui-provenance__item",
@@ -133,6 +133,10 @@ export declare const cls: {
133
133
  readonly alertWarning: 'ui-alert--warning';
134
134
  readonly alertDanger: 'ui-alert--danger';
135
135
  readonly alertInfo: 'ui-alert--info';
136
+ readonly alertBand: 'ui-alert--band';
137
+ readonly bodyState: 'ui-body-state';
138
+ readonly bodyStateError: 'ui-body-state--error';
139
+ readonly bodyStateStale: 'ui-body-state--stale';
136
140
  readonly toastStack: 'ui-toast-stack';
137
141
  readonly toastStackAssertive: 'ui-toast-stack--assertive';
138
142
  readonly toast: 'ui-toast';
@@ -241,6 +245,7 @@ export declare const cls: {
241
245
  readonly eyebrowSm: 'ui-eyebrow--sm';
242
246
  readonly prose: 'ui-prose';
243
247
  readonly proseCompact: 'ui-prose--compact';
248
+ readonly proseBlocks: 'ui-prose--blocks';
244
249
  readonly quote: 'ui-quote';
245
250
  readonly quoteCite: 'ui-quote__cite';
246
251
  readonly container: 'ui-container';
@@ -722,6 +727,10 @@ export interface ButtonOpts {
722
727
  export interface EmptyStateOpts {
723
728
  invite?: boolean;
724
729
  }
730
+ export interface BodyStateOpts {
731
+ /** Omit for empty and loading (mark a loading region aria-busy). */
732
+ state?: 'error' | 'stale';
733
+ }
725
734
  export interface ToolstripOpts {
726
735
  variant?: 'floating' | 'compact' | 'pane';
727
736
  anchor?: 'block-start' | 'block-end';
@@ -795,6 +804,7 @@ export interface StaggerOpts {
795
804
  export type Tone = 'accent' | 'success' | 'warning' | 'danger' | 'info';
796
805
  export interface AlertOpts {
797
806
  tone?: Tone;
807
+ band?: boolean;
798
808
  }
799
809
  export interface ToastOpts {
800
810
  tone?: Tone;
@@ -822,6 +832,7 @@ export interface AvatarOpts {
822
832
  }
823
833
  export interface ProseOpts {
824
834
  compact?: boolean;
835
+ blocks?: boolean;
825
836
  }
826
837
  export interface ContainerOpts {
827
838
  narrow?: boolean;
@@ -1013,6 +1024,7 @@ export interface Ui {
1013
1024
  job(opts?: JobOpts): string;
1014
1025
  originLabel(opts?: OriginLabelOpts): string;
1015
1026
  emptyState(opts?: EmptyStateOpts): string;
1027
+ bodyState(opts?: BodyStateOpts): string;
1016
1028
  toolstrip(opts?: ToolstripOpts): string;
1017
1029
  selectionbar(opts?: SelectionbarOpts): string;
1018
1030
  }
package/classes/index.js CHANGED
@@ -141,6 +141,10 @@ export const cls = Object.freeze({
141
141
  alertWarning: 'ui-alert--warning',
142
142
  alertDanger: 'ui-alert--danger',
143
143
  alertInfo: 'ui-alert--info',
144
+ alertBand: 'ui-alert--band',
145
+ bodyState: 'ui-body-state',
146
+ bodyStateError: 'ui-body-state--error',
147
+ bodyStateStale: 'ui-body-state--stale',
144
148
  toastStack: 'ui-toast-stack',
145
149
  toastStackAssertive: 'ui-toast-stack--assertive',
146
150
  toast: 'ui-toast',
@@ -255,6 +259,7 @@ export const cls = Object.freeze({
255
259
  eyebrowSm: 'ui-eyebrow--sm',
256
260
  prose: 'ui-prose',
257
261
  proseCompact: 'ui-prose--compact',
262
+ proseBlocks: 'ui-prose--blocks',
258
263
  quote: 'ui-quote',
259
264
  quoteCite: 'ui-quote__cite',
260
265
  // site shell
@@ -874,6 +879,11 @@ const dotTone = (tone) =>
874
879
  tone,
875
880
  );
876
881
 
882
+ // A body state's tone. Empty and loading are the plain state (no option); a
883
+ // loading region says so with aria-busy, not a class.
884
+ const bodyStateTone = (state) =>
885
+ valueClass({ error: cls.bodyStateError, stale: cls.bodyStateStale }, state);
886
+
877
887
  const alertTone = (tone) =>
878
888
  toneClass(
879
889
  'alert',
@@ -1025,7 +1035,7 @@ export const ui = {
1025
1035
  hint: ({ error } = {}) => j(cls.hint, error && cls.hintError),
1026
1036
  cluster: ({ between } = {}) => j(cls.cluster, between && cls.clusterBetween),
1027
1037
  stagger: ({ auto } = {}) => j(cls.stagger, auto && cls.staggerAuto),
1028
- alert: ({ tone } = {}) => j(cls.alert, alertTone(tone)),
1038
+ alert: ({ tone, band } = {}) => j(cls.alert, alertTone(tone), band && cls.alertBand),
1029
1039
  toast: ({ tone } = {}) => j(cls.toast, toastTone(tone)),
1030
1040
  progress: ({ indeterminate } = {}) => j(cls.progress, indeterminate && cls.progressIndeterminate),
1031
1041
  meter: ({ tone } = {}) => j(cls.meter, meterTone(tone)),
@@ -1036,7 +1046,8 @@ export const ui = {
1036
1046
  tab: ({ active } = {}) => j(cls.tab, active && 'is-active'),
1037
1047
  avatar: ({ size } = {}) =>
1038
1048
  j(cls.avatar, size === 'sm' && cls.avatarSm, size === 'lg' && cls.avatarLg),
1039
- prose: ({ compact } = {}) => j(cls.prose, compact && cls.proseCompact),
1049
+ prose: ({ compact, blocks } = {}) =>
1050
+ j(cls.prose, compact && cls.proseCompact, blocks && cls.proseBlocks),
1040
1051
  container: ({ narrow, wide } = {}) =>
1041
1052
  j(cls.container, narrow && cls.containerNarrow, wide && cls.containerWide),
1042
1053
  tag: ({ accent } = {}) => j(cls.tag, accent && cls.tagAccent),
@@ -1150,6 +1161,7 @@ export const ui = {
1150
1161
  job: ({ state, compact } = {}) => j(cls.job, jobTone(state), compact && cls.jobCompact),
1151
1162
  originLabel: ({ ai } = {}) => j(cls.originLabel, ai && cls.originLabelAi),
1152
1163
  emptyState: ({ invite } = {}) => j(cls.emptyState, invite && cls.emptyStateInvite),
1164
+ bodyState: ({ state } = {}) => j(cls.bodyState, bodyStateTone(state)),
1153
1165
  toolstrip: ({ variant, anchor } = {}) =>
1154
1166
  j(
1155
1167
  cls.toolstrip,
@@ -201,6 +201,18 @@
201
201
  "name": "--focus-ring",
202
202
  "description": "Theme token. Light: `var(--accent)` · Dark: `var(--accent)`"
203
203
  },
204
+ {
205
+ "name": "--focus-ring-offset",
206
+ "description": "Global scale token. Value: `2px`"
207
+ },
208
+ {
209
+ "name": "--focus-ring-width",
210
+ "description": "Global scale token. Value: `2px`"
211
+ },
212
+ {
213
+ "name": "--hairline",
214
+ "description": "Global scale token. Value: `1px`"
215
+ },
204
216
  {
205
217
  "name": "--info",
206
218
  "description": "Theme token. Light: `#1f63c4` · Dark: `#6fb0e6`"
@@ -285,6 +297,22 @@
285
297
  "name": "--shadow-raised",
286
298
  "description": "Theme token. Light: `0 0 0 1px var(--line-strong)` · Dark: `0 0 0 1px var(--line-strong)`"
287
299
  },
300
+ {
301
+ "name": "--space-0-5",
302
+ "description": "Global scale token. Value: `0.125rem`"
303
+ },
304
+ {
305
+ "name": "--space-0-75",
306
+ "description": "Global scale token. Value: `0.1875rem`"
307
+ },
308
+ {
309
+ "name": "--space-1-5",
310
+ "description": "Global scale token. Value: `0.375rem`"
311
+ },
312
+ {
313
+ "name": "--space-2-5",
314
+ "description": "Global scale token. Value: `0.625rem`"
315
+ },
288
316
  {
289
317
  "name": "--space-2xl",
290
318
  "description": "Global scale token. Value: `2.5rem`"
@@ -409,6 +437,14 @@
409
437
  "name": "--tracking-wider",
410
438
  "description": "Global scale token. Value: `0.22em`"
411
439
  },
440
+ {
441
+ "name": "--ui-px",
442
+ "description": "Global scale token. Value: `1px`"
443
+ },
444
+ {
445
+ "name": "--ui-zoom",
446
+ "description": "Global scale token. Value: `1`"
447
+ },
412
448
  {
413
449
  "name": "--warning",
414
450
  "description": "Theme token. Light: `#806414` · Dark: `#d8bd72`"
@@ -421,10 +457,34 @@
421
457
  "name": "--z-base",
422
458
  "description": "Global scale token. Value: `0`"
423
459
  },
460
+ {
461
+ "name": "--z-canvas",
462
+ "description": "Global scale token. Value: `var(--z-base)`"
463
+ },
464
+ {
465
+ "name": "--z-chrome",
466
+ "description": "Global scale token. Value: `var(--z-sticky)`"
467
+ },
468
+ {
469
+ "name": "--z-menu",
470
+ "description": "Global scale token. Value: `var(--z-popover)`"
471
+ },
472
+ {
473
+ "name": "--z-modal",
474
+ "description": "Global scale token. Value: `var(--z-overlay)`"
475
+ },
476
+ {
477
+ "name": "--z-navigation",
478
+ "description": "Global scale token. Value: `80`"
479
+ },
424
480
  {
425
481
  "name": "--z-overlay",
426
482
  "description": "Global scale token. Value: `30`"
427
483
  },
484
+ {
485
+ "name": "--z-panel",
486
+ "description": "Global scale token. Value: `25`"
487
+ },
428
488
  {
429
489
  "name": "--z-popover",
430
490
  "description": "Global scale token. Value: `50`"
@@ -440,6 +500,10 @@
440
500
  {
441
501
  "name": "--z-toast",
442
502
  "description": "Global scale token. Value: `60`"
503
+ },
504
+ {
505
+ "name": "--z-tooltip",
506
+ "description": "Global scale token. Value: `70`"
443
507
  }
444
508
  ],
445
509
  "atDirectives": [
package/css/base.css CHANGED
@@ -164,8 +164,8 @@ input:focus-visible,
164
164
  select:focus-visible,
165
165
  textarea:focus-visible,
166
166
  [tabindex]:focus-visible {
167
- outline: 2px solid var(--focus-ring);
168
- outline-offset: 2px;
167
+ outline: var(--focus-ring-width) solid var(--focus-ring);
168
+ outline-offset: var(--focus-ring-offset);
169
169
  }
170
170
 
171
171
  /* Small global helpers reused across apps. */
@@ -0,0 +1,61 @@
1
+ /* ==========================================================================
2
+ blocknote — BlockNote's theme variables, mapped to bronto tokens.
3
+
4
+ INTEROP LEAF, opt-in. BlockNote (https://www.blocknotejs.org) themes its
5
+ editor, menus, side menu, toolbar and text highlights through `--bn-*`
6
+ custom properties on `.bn-root`, with its own light and dark values. Point
7
+ them at the bronto tokens and the editor follows the theme, skins, contrast
8
+ and the OLED surface like the rest of the page.
9
+
10
+ BlockNote's stylesheet is unlayered, and an unlayered rule outranks any
11
+ layered one, so import this leaf's UNLAYERED build, after BlockNote's:
12
+
13
+ @import '@blocknote/mantine/style.css';
14
+ @import '@ponchia/ui/css/unlayered/blocknote.css';
15
+
16
+ Text and background highlights are categorical identity (a colour a person
17
+ chose for a span), so they take `--cat-N-ink` and `--cat-N-tint` from
18
+ css/dataviz.css. Without that leaf they fall back to the status colours.
19
+ ========================================================================== */
20
+
21
+ .bn-root,
22
+ .bn-root[data-color-scheme] {
23
+ --bn-font-family: var(--sans);
24
+ --bn-border-radius: var(--radius-lg);
25
+ --bn-colors-editor-text: var(--text);
26
+ --bn-colors-editor-background: var(--panel);
27
+ --bn-colors-menu-text: var(--text);
28
+ --bn-colors-menu-background: var(--panel-strong);
29
+ --bn-colors-tooltip-text: var(--text);
30
+ --bn-colors-tooltip-background: var(--panel-soft);
31
+ --bn-colors-hovered-text: var(--text);
32
+ --bn-colors-hovered-background: var(--panel-soft);
33
+ --bn-colors-selected-text: var(--on-accent);
34
+ --bn-colors-selected-background: var(--accent);
35
+ --bn-colors-disabled-text: var(--text-dim);
36
+ --bn-colors-disabled-background: var(--panel-soft);
37
+ --bn-colors-shadow: var(--line);
38
+ --bn-colors-border: var(--line);
39
+ --bn-colors-side-menu: var(--text-dim);
40
+
41
+ /* Highlights: BlockNote's nine names onto the categorical hues. Gray is the
42
+ neutral ink; brown, which the palette has no hue for, is the orange ink. */
43
+ --bn-colors-highlights-gray-text: var(--text-dim);
44
+ --bn-colors-highlights-gray-background: var(--panel-soft);
45
+ --bn-colors-highlights-brown-text: var(--cat-2-ink, var(--warning));
46
+ --bn-colors-highlights-brown-background: var(--panel-soft);
47
+ --bn-colors-highlights-red-text: var(--cat-8-ink, var(--danger));
48
+ --bn-colors-highlights-red-background: var(--cat-8-tint, var(--panel-soft));
49
+ --bn-colors-highlights-orange-text: var(--cat-2-ink, var(--warning));
50
+ --bn-colors-highlights-orange-background: var(--cat-2-tint, var(--panel-soft));
51
+ --bn-colors-highlights-yellow-text: var(--cat-4-ink, var(--warning));
52
+ --bn-colors-highlights-yellow-background: var(--cat-4-tint, var(--panel-soft));
53
+ --bn-colors-highlights-green-text: var(--cat-6-ink, var(--success));
54
+ --bn-colors-highlights-green-background: var(--cat-6-tint, var(--panel-soft));
55
+ --bn-colors-highlights-blue-text: var(--cat-1-ink, var(--info));
56
+ --bn-colors-highlights-blue-background: var(--cat-1-tint, var(--panel-soft));
57
+ --bn-colors-highlights-purple-text: var(--cat-7-ink, var(--info));
58
+ --bn-colors-highlights-purple-background: var(--cat-7-tint, var(--panel-soft));
59
+ --bn-colors-highlights-pink-text: var(--cat-5-ink, var(--danger));
60
+ --bn-colors-highlights-pink-background: var(--cat-5-tint, var(--panel-soft));
61
+ }
package/css/clamp.css CHANGED
@@ -55,8 +55,8 @@
55
55
  }
56
56
 
57
57
  .ui-clamp__toggle:focus-visible + .ui-clamp__body + .ui-clamp__control {
58
- outline: 2px solid var(--focus-ring);
59
- outline-offset: 2px;
58
+ outline: var(--focus-ring-width) solid var(--focus-ring);
59
+ outline-offset: var(--focus-ring-offset);
60
60
  }
61
61
 
62
62
  .ui-clamp__less {
package/css/content.css CHANGED
@@ -5,9 +5,42 @@
5
5
  and the document is styled in the Nothing aesthetic while the markup
6
6
  stays semantic and machine-readable (no class-soup). Everything here
7
7
  is an element selector scoped under `.ui-prose`, so it never leaks
8
- into app UI.
8
+ into app UI. The one exception is `.ui-meta`, the date · author line
9
+ that sits beside long-form text, a tool's remarks included (it lived in
10
+ site.css until 0.14, so css/tool.css can keep it without the site shell).
9
11
  ========================================================================== */
10
12
 
13
+ /* --- Meta row — date · author · read-time, dot-separated --- */
14
+
15
+ .ui-meta {
16
+ align-items: center;
17
+ color: var(--text-dim);
18
+ display: flex;
19
+ flex-wrap: wrap;
20
+ font-family: var(--mono);
21
+ font-size: var(--text-2xs);
22
+ gap: 0.55rem;
23
+ letter-spacing: var(--tracking-wide);
24
+ list-style: none;
25
+ margin: 0;
26
+ padding: 0;
27
+ text-transform: uppercase;
28
+ }
29
+
30
+ .ui-meta__item {
31
+ align-items: center;
32
+ display: inline-flex;
33
+ gap: 0.55rem;
34
+ }
35
+
36
+ .ui-meta__item:not(:last-child)::after {
37
+ background: var(--line-strong);
38
+ border-radius: 50%;
39
+ block-size: 0.22rem;
40
+ content: '';
41
+ inline-size: 0.22rem;
42
+ }
43
+
11
44
  .ui-prose {
12
45
  /* A prose block must shrink as a grid/flex item; its pre blocks scroll locally. */
13
46
  min-inline-size: 0;
@@ -308,6 +341,132 @@
308
341
  margin-block-start: var(--space-lg);
309
342
  }
310
343
 
344
+ /* --- Blocks variant — the block editor's geometry ---
345
+ For a surface that is both read and edited, where the editor is a block
346
+ editor (BlockNote's model): the read view has to put every line where the
347
+ editor will draw it, or the text jumps when the surface switches mode.
348
+ Blocks carry a small padding instead of flow margins; headings a lead above
349
+ and a 1.6/1.3/1.15em scale at weight 600; lists a fixed marker column with
350
+ disc, circle and square; a task row the editor's checkbox geometry. The
351
+ measure is released: a block surface is as wide as its container. The
352
+ geometry is the editor's own px, exposed so a host can retune it. */
353
+
354
+ .ui-prose--blocks {
355
+ --prose-measure: none;
356
+ --prose-block: 3px;
357
+ --prose-heading-lead: 18px;
358
+ --prose-list-column: 24px;
359
+
360
+ color: var(--text);
361
+ line-height: 1.5;
362
+ }
363
+
364
+ .ui-prose--blocks > *,
365
+ .ui-prose--blocks > * + *,
366
+ .ui-prose--blocks > * + :is(h1, h2, h3, h4, h5, h6),
367
+ .ui-prose--blocks li,
368
+ .ui-prose--blocks li + li,
369
+ .ui-prose--blocks li > *,
370
+ .ui-prose--blocks :is(ul, ol) :is(ul, ol),
371
+ .ui-prose--blocks blockquote > *,
372
+ .ui-prose--blocks blockquote > * + * {
373
+ margin-block: 0;
374
+ }
375
+
376
+ .ui-prose--blocks > :not(ul, ol),
377
+ .ui-prose--blocks li {
378
+ padding-block: var(--prose-block);
379
+ }
380
+
381
+ /* An item's own block ends before its nested list, as the editor nests it. */
382
+ .ui-prose--blocks li:has(> :is(ul, ol)) {
383
+ padding-block-end: 0;
384
+ }
385
+
386
+ .ui-prose--blocks li > :is(ul, ol) {
387
+ padding-block-start: var(--prose-block);
388
+ }
389
+
390
+ .ui-prose--blocks :is(h1, h2, h3, h4, h5, h6) {
391
+ padding-block: var(--prose-heading-lead) var(--prose-block);
392
+ border: 0;
393
+ font-size: 1em;
394
+ font-weight: 600;
395
+ line-height: 1.25;
396
+ }
397
+
398
+ .ui-prose--blocks h1 {
399
+ font-size: 1.6em;
400
+ }
401
+
402
+ .ui-prose--blocks h2 {
403
+ font-size: 1.3em;
404
+ }
405
+
406
+ .ui-prose--blocks h3 {
407
+ font-size: 1.15em;
408
+ }
409
+
410
+ .ui-prose--blocks :is(ul, ol) {
411
+ padding-inline-start: var(--prose-list-column);
412
+ }
413
+
414
+ .ui-prose--blocks ul {
415
+ list-style: disc;
416
+ }
417
+
418
+ .ui-prose--blocks ul ul {
419
+ list-style: circle;
420
+ }
421
+
422
+ .ui-prose--blocks ul ul ul {
423
+ list-style: square;
424
+ }
425
+
426
+ .ui-prose--blocks li::marker {
427
+ color: inherit;
428
+ }
429
+
430
+ /* A task row is the editor's: the checkbox centred in a hit area at the text
431
+ column, the text padded inside the block. A loose list may put the checkbox
432
+ in the item's paragraph rather than the item. */
433
+ .ui-prose--blocks li:has(> input[type='checkbox'], > p > input[type='checkbox']) {
434
+ margin-inline-start: calc(-1 * var(--prose-list-column));
435
+ padding-block: 10px;
436
+ list-style: none;
437
+ }
438
+
439
+ .ui-prose--blocks :is(li, li > p):has(> input[type='checkbox']) {
440
+ display: flex;
441
+ align-items: flex-start;
442
+ }
443
+
444
+ .ui-prose--blocks :is(li, li > p) > input[type='checkbox'] {
445
+ flex: none;
446
+ inline-size: 20px;
447
+ block-size: 20px;
448
+ margin: 2px 6px 0;
449
+ }
450
+
451
+ @media (pointer: coarse) {
452
+ .ui-prose--blocks li:has(> input[type='checkbox'], > p > input[type='checkbox']) {
453
+ padding-block: 16px;
454
+ }
455
+
456
+ .ui-prose--blocks :is(li, li > p) > input[type='checkbox'] {
457
+ margin-inline: 12px;
458
+ }
459
+ }
460
+
461
+ /* A quote is one block: its text on the body's line, its rule at the column. */
462
+ .ui-prose--blocks blockquote {
463
+ margin-inline: 0;
464
+ }
465
+
466
+ .ui-prose--blocks blockquote > * {
467
+ line-height: inherit;
468
+ }
469
+
311
470
  /* ==========================================================================
312
471
  ui-quote — pull-quote with attribution. A long-form companion to
313
472
  .ui-prose (works inside it or standalone). Emphasis via scale + a
@@ -75,8 +75,8 @@
75
75
  distinction — colour stays the solid accent used by every other
76
76
  control's ring (the --focus-ring token wiring is decided globally,
77
77
  not per-component). */
78
- outline: 2px solid var(--focus-ring);
79
- outline-offset: -3px;
78
+ outline: var(--focus-ring-width) solid var(--focus-ring);
79
+ outline-offset: calc(-1.5 * var(--focus-ring-offset));
80
80
  }
81
81
 
82
82
  .ui-tabs__panel[hidden] {
@@ -216,8 +216,8 @@
216
216
  }
217
217
 
218
218
  .ui-segmented__option:has(input:focus-visible) {
219
- outline: 2px solid var(--focus-ring);
220
- outline-offset: -2px;
219
+ outline: var(--focus-ring-width) solid var(--focus-ring);
220
+ outline-offset: calc(-1 * var(--focus-ring-offset));
221
221
  }
222
222
 
223
223
  @media (hover: hover) {
@@ -439,8 +439,8 @@
439
439
  }
440
440
 
441
441
  .ui-carousel__viewport:focus-visible {
442
- outline: 2px solid var(--focus-ring);
443
- outline-offset: -2px;
442
+ outline: var(--focus-ring-width) solid var(--focus-ring);
443
+ outline-offset: calc(-1 * var(--focus-ring-offset));
444
444
  }
445
445
 
446
446
  .ui-carousel__slide {
@@ -519,8 +519,8 @@
519
519
 
520
520
  .ui-carousel__prev:focus-visible,
521
521
  .ui-carousel__next:focus-visible {
522
- outline: 2px solid var(--focus-ring);
523
- outline-offset: 2px;
522
+ outline: var(--focus-ring-width) solid var(--focus-ring);
523
+ outline-offset: var(--focus-ring-offset);
524
524
  }
525
525
 
526
526
  /* Position counter ("3 / 12") — initCarousel fills the text; aria-live. */
@@ -584,8 +584,8 @@
584
584
  }
585
585
 
586
586
  .ui-carousel__thumb:focus-visible {
587
- outline: 2px solid var(--focus-ring);
588
- outline-offset: 2px;
587
+ outline: var(--focus-ring-width) solid var(--focus-ring);
588
+ outline-offset: var(--focus-ring-offset);
589
589
  }
590
590
 
591
591
  @media (prefers-reduced-motion: reduce) {