@scattered-light/loomiere 0.0.0-stage → 0.1.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 (73) hide show
  1. package/README.md +60 -2
  2. package/bin/loomiere.mjs +112 -0
  3. package/build/build-tokens.mjs +485 -0
  4. package/exporters/README.md +45 -0
  5. package/exporters/ag-grid-settings.mjs +177 -0
  6. package/exporters/ag-grid.mjs +112 -0
  7. package/exporters/chakra.mjs +630 -0
  8. package/exporters/component-styles.mjs +207 -0
  9. package/exporters/dtcg.mjs +31 -0
  10. package/exporters/figma.mjs +100 -0
  11. package/exporters/index.mjs +38 -0
  12. package/exporters/mui.mjs +666 -0
  13. package/exporters/tailwind.mjs +35 -0
  14. package/exporters/theme.mjs +93 -0
  15. package/generator/brand.mjs +328 -0
  16. package/generator/brand.schema.json +657 -0
  17. package/generator/color.mjs +130 -0
  18. package/generator/data-colors.mjs +104 -0
  19. package/generator/format-brand.mjs +60 -0
  20. package/generator/generate.mjs +43 -0
  21. package/generator/pairs.mjs +236 -0
  22. package/generator/roles.mjs +258 -0
  23. package/generator/vision.mjs +167 -0
  24. package/lib/config.mjs +71 -0
  25. package/lib/contrast.mjs +134 -0
  26. package/lib/lab.mjs +108 -0
  27. package/lib/studio.mjs +127 -0
  28. package/lib/tool-server.mjs +96 -0
  29. package/package.json +51 -4
  30. package/templates/brand.json +104 -0
  31. package/tokens/README.md +219 -0
  32. package/tokens/component/avatar.json +10 -0
  33. package/tokens/component/button.json +12 -0
  34. package/tokens/component/drawer.json +26 -0
  35. package/tokens/component/navigation-menu.json +13 -0
  36. package/tokens/component/popover.json +13 -0
  37. package/tokens/component/preview-card.json +13 -0
  38. package/tokens/component/slider.json +13 -0
  39. package/tokens/component/switch.json +41 -0
  40. package/tokens/component/toast.json +21 -0
  41. package/tokens/component/toggle.json +9 -0
  42. package/tokens/component/toolbar.json +9 -0
  43. package/tokens/component/tooltip.json +9 -0
  44. package/tokens/foundation/layering.json +57 -0
  45. package/tokens/foundation/layout.json +75 -0
  46. package/tokens/foundation/motion.json +41 -0
  47. package/tokens/foundation/type.json +92 -0
  48. package/tokens/semantic/accessibility.json +39 -0
  49. package/tokens/semantic/bar.json +45 -0
  50. package/tokens/semantic/check.json +57 -0
  51. package/tokens/semantic/color.json +270 -0
  52. package/tokens/semantic/content.json +124 -0
  53. package/tokens/semantic/disclosure.json +49 -0
  54. package/tokens/semantic/elevation.json +72 -0
  55. package/tokens/semantic/field.json +77 -0
  56. package/tokens/semantic/focus.json +36 -0
  57. package/tokens/semantic/gauge.json +45 -0
  58. package/tokens/semantic/icon-button.json +33 -0
  59. package/tokens/semantic/icon.json +30 -0
  60. package/tokens/semantic/item.json +65 -0
  61. package/tokens/semantic/modal.json +86 -0
  62. package/tokens/semantic/motion.json +20 -0
  63. package/tokens/semantic/notice.json +37 -0
  64. package/tokens/semantic/popup.json +89 -0
  65. package/tokens/semantic/scheme.json +11 -0
  66. package/tokens/semantic/shape.json +54 -0
  67. package/tokens/semantic/spacing.json +110 -0
  68. package/tokens/semantic/table.json +73 -0
  69. package/tokens/semantic/typography.json +312 -0
  70. package/tools/brand-builder/builder.js +1119 -0
  71. package/tools/brand-builder/index.html +329 -0
  72. package/tools/pair-lab/index.html +119 -0
  73. package/tools/pair-lab/lab.js +249 -0
@@ -0,0 +1,92 @@
1
+ {
2
+ "font-weight": {
3
+ "$type": "fontWeight",
4
+ "$description": "Numeric weights. Brands pick which ones their typefaces actually ship.",
5
+ "hairline": {
6
+ "$value": 100
7
+ },
8
+ "thin": {
9
+ "$value": 200
10
+ },
11
+ "light": {
12
+ "$value": 300
13
+ },
14
+ "normal": {
15
+ "$value": 400
16
+ },
17
+ "medium": {
18
+ "$value": 500
19
+ },
20
+ "semibold": {
21
+ "$value": 600
22
+ },
23
+ "bold": {
24
+ "$value": 700
25
+ },
26
+ "extrabold": {
27
+ "$value": 800
28
+ },
29
+ "black": {
30
+ "$value": 900
31
+ }
32
+ },
33
+ "letter-spacing": {
34
+ "$type": "dimension",
35
+ "$description": "Tracking in em so it scales with the font size.",
36
+ "tighter": {
37
+ "$value": "-0.05em",
38
+ "$description": "Very large display text."
39
+ },
40
+ "tight": {
41
+ "$value": "-0.025em",
42
+ "$description": "Headlines."
43
+ },
44
+ "normal": {
45
+ "$value": "0",
46
+ "$description": "Body text."
47
+ },
48
+ "wide": {
49
+ "$value": "0.025em",
50
+ "$description": "Small text that needs air."
51
+ },
52
+ "wider": {
53
+ "$value": "0.05em",
54
+ "$description": "Small caps and labels."
55
+ },
56
+ "widest": {
57
+ "$value": "0.1em",
58
+ "$description": "Uppercase group labels."
59
+ }
60
+ },
61
+ "font-family": {
62
+ "sans": {
63
+ "$type": "fontFamily",
64
+ "$value": [
65
+ "-apple-system",
66
+ "BlinkMacSystemFont",
67
+ "Segoe UI",
68
+ "Roboto",
69
+ "Oxygen",
70
+ "Ubuntu",
71
+ "Cantarell",
72
+ "Fira Sans",
73
+ "Droid Sans",
74
+ "Helvetica Neue",
75
+ "sans-serif"
76
+ ],
77
+ "$description": "Platform UI font. Fallback when a brand typeface is unavailable."
78
+ },
79
+ "serif": {
80
+ "$type": "fontFamily",
81
+ "$value": [
82
+ "ui-serif",
83
+ "Georgia",
84
+ "Cambria",
85
+ "Times New Roman",
86
+ "Times",
87
+ "serif"
88
+ ],
89
+ "$description": "Platform serif stack."
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "a11y": {
3
+ "focus-outline-offset": {
4
+ "$value": "2px",
5
+ "$description": "Gap between a control and its focus ring so the ring never blends into the control border."
6
+ },
7
+ "focus-outline-width": {
8
+ "$value": "2px",
9
+ "$description": "Focus ring thickness. 2px is the WCAG 2.2 minimum that stays visible on every surface."
10
+ },
11
+ "focus-ring-radius": {
12
+ "$value": "{radius.focus}",
13
+ "$description": "Rounds the focus ring to match the small control radius."
14
+ },
15
+ "link-focus-outline-offset": {
16
+ "$value": "0.25em",
17
+ "$description": "Links sit inside text, so the offset scales with the font (em) instead of a fixed px."
18
+ },
19
+ "link-focus-ring-radius": {
20
+ "$value": "0.125em",
21
+ "$description": "A slight em-based rounding so inline focus rings hug the text."
22
+ },
23
+ "min-touch-target": {
24
+ "$value": "44px",
25
+ "$description": "Smallest tap area for any control (WCAG 2.5.5 and Apple HIG both use 44px)."
26
+ }
27
+ },
28
+ "focus": {
29
+ "ring": {
30
+ "$value": "{interactive.default}",
31
+ "$type": "color",
32
+ "$description": "Focus ring color. Uses the interactive accent so focus reads as \"this is the thing you can act on\"."
33
+ },
34
+ "ring-width": {
35
+ "$value": "{a11y.focus-outline-width}",
36
+ "$description": "Alias for the focus outline width, kept for components that style rings with box-shadow."
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "bar": {
3
+ "$description": "A strip that holds a row of controls: toolbars and toggle groups. One surface and rhythm so every row of controls reads as the same kind of thing.",
4
+ "background": {
5
+ "$value": "{surface.tray}",
6
+ "$description": "Strip fill."
7
+ },
8
+ "border-color": {
9
+ "$value": "{border.default}",
10
+ "$description": "Strip edge."
11
+ },
12
+ "border-width": {
13
+ "$value": "{stroke.default}",
14
+ "$description": "Strip edge thickness."
15
+ },
16
+ "radius": {
17
+ "$value": "{radius.surface}",
18
+ "$description": "Strip corners. Controls inside a toggle group take radius.item, so the inner corners follow the outer ones."
19
+ },
20
+ "padding": {
21
+ "$value": "{space.1}",
22
+ "$description": "Space between the strip's edge and its controls, small so the controls nearly fill it."
23
+ },
24
+ "gap": {
25
+ "$value": "{space.1}",
26
+ "$description": "Space between controls in one group."
27
+ },
28
+ "group-gap": {
29
+ "$value": "{space.2}",
30
+ "$description": "Space between groups in a toolbar, wider than inside a group."
31
+ },
32
+ "separator-color": {
33
+ "$value": "{border.default}",
34
+ "$description": "Divider between groups."
35
+ },
36
+ "separator-length": {
37
+ "$value": "{space.6}",
38
+ "$description": "Divider height, shorter than the controls so the groups still read as one strip."
39
+ },
40
+ "separator-spacing": {
41
+ "$value": "{space.1}",
42
+ "$description": "Extra space either side of a divider."
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "check": {
3
+ "$description": "The small box or circle you tick: checkboxes and radios, and the edge of a switch track. They share one look so a form of mixed choices reads as one set.",
4
+ "background": {
5
+ "$value": "{field.background}",
6
+ "$description": "Empty box, the same fill as a field so it reads as something to fill in."
7
+ },
8
+ "border-color": {
9
+ "$value": "{border.control}",
10
+ "$description": "Empty box edge. Passes 3:1 so the box can be found before it's ticked."
11
+ },
12
+ "border-color-hover": {
13
+ "$value": "{border.control-hover}",
14
+ "$description": "Edge under the pointer."
15
+ },
16
+ "border-width": {
17
+ "$value": "{stroke.default}",
18
+ "$description": "Edge thickness."
19
+ },
20
+ "background-checked": {
21
+ "$value": "{interactive.default}",
22
+ "$description": "Ticked box fill, the brand's interactive color."
23
+ },
24
+ "border-color-checked": {
25
+ "$value": "{border.accent}",
26
+ "$description": "Ticked box edge."
27
+ },
28
+ "mark-color": {
29
+ "$value": "{text.on-primary}",
30
+ "$description": "Check mark, dash or dot on a ticked fill."
31
+ },
32
+ "mark-color-outline": {
33
+ "$value": "{interactive.default}",
34
+ "$description": "Check mark in the outline style, where the box stays empty and only the mark is colored."
35
+ },
36
+ "mark-color-disabled": {
37
+ "$value": "{text.disabled}",
38
+ "$description": "Check mark of a disabled outline box."
39
+ },
40
+ "radius": {
41
+ "$value": "{radius.box}",
42
+ "$description": "Checkbox corners. Radios are always round."
43
+ },
44
+ "dot-scale": {
45
+ "$value": "0.4",
46
+ "$description": "A radio's dot as a share of the circle, so it scales with the size."
47
+ },
48
+ "opacity-disabled": {
49
+ "$value": "0.5",
50
+ "$description": "A disabled box fades as a whole; its label turns to disabled text."
51
+ },
52
+ "transition": {
53
+ "$value": "{transition.input}",
54
+ "$description": "Changes at the same speed as a field."
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,270 @@
1
+ {
2
+ "border": {
3
+ "accent": {
4
+ "$value": "{scope.accent.border}",
5
+ "$type": "color",
6
+ "$description": "Borders that signal selection or the active item."
7
+ },
8
+ "default": {
9
+ "$value": "{scope.chrome.divider}",
10
+ "$type": "color",
11
+ "$description": "Everyday dividers and control outlines. Darkens under prefers-contrast: more."
12
+ },
13
+ "strong": {
14
+ "$value": "{scope.chrome.border-strong}",
15
+ "$type": "color",
16
+ "$description": "Borders that identify a control, such as inputs and unchecked checkboxes. 3:1 against the canvas, as WCAG asks for control boundaries."
17
+ },
18
+ "subtle": {
19
+ "$value": "{scope.chrome.border-subtle}",
20
+ "$type": "color",
21
+ "$description": "Hairlines inside a surface (table rows, list separators) that should barely register."
22
+ },
23
+ "control": {
24
+ "$value": "{scope.chrome.border}",
25
+ "$type": "color",
26
+ "$description": "Edge of a small control (checkbox, radio, switch) that must be found before it is filled."
27
+ },
28
+ "control-hover": {
29
+ "$value": "{scope.chrome.border-hover}",
30
+ "$type": "color",
31
+ "$description": "Control edge under the pointer: one clear step darker than border.control."
32
+ }
33
+ },
34
+ "interactive": {
35
+ "active": {
36
+ "$value": "{scope.accent.solid-active}",
37
+ "$type": "color",
38
+ "$description": "Pressed state of the main accent. Darker than hover so the press is felt."
39
+ },
40
+ "default": {
41
+ "$value": "{scope.accent.solid}",
42
+ "$type": "color",
43
+ "$description": "Primary accent for buttons, links and selected states. Step 600 is 6.1:1 on paper; step 400 is 5.6:1 on the dark canvas."
44
+ },
45
+ "disabled": {
46
+ "$value": "{scope.chrome.soft-active}",
47
+ "$type": "color",
48
+ "$description": "Fill for disabled accent controls. Low contrast on purpose, but never invisible."
49
+ },
50
+ "hover": {
51
+ "$value": "{scope.accent.solid-hover}",
52
+ "$type": "color",
53
+ "$description": "Hover state of the main accent. One step away from default in the direction of more contrast."
54
+ },
55
+ "tint": {
56
+ "$value": "{scope.accent.soft}",
57
+ "$type": "color",
58
+ "$description": "Faint accent wash behind a ghost or outline control on hover, or a selected row."
59
+ },
60
+ "tint-hover": {
61
+ "$value": "{scope.accent.soft-hover}",
62
+ "$type": "color",
63
+ "$description": "Accent wash for a highlighted menu item or a pressed toggle."
64
+ },
65
+ "tint-active": {
66
+ "$value": "{scope.accent.soft-active}",
67
+ "$type": "color",
68
+ "$description": "Accent wash for a selected or pressed item: one step past tint-hover."
69
+ },
70
+ "tint-strong": {
71
+ "$value": "{scope.accent.soft-strong}",
72
+ "$type": "color",
73
+ "$description": "Strongest accent wash, for hovering an item that is already pressed."
74
+ }
75
+ },
76
+ "overlay": {
77
+ "base": {
78
+ "$value": "{color.black}",
79
+ "$type": "color",
80
+ "$description": "Base color for scrims behind modals. Components apply their own opacity."
81
+ }
82
+ },
83
+ "status": {
84
+ "error": {
85
+ "$value": "{scope.error.signal}",
86
+ "$type": "color",
87
+ "$description": "Errors and destructive actions."
88
+ },
89
+ "error-dark": {
90
+ "$value": "{scope.error.fg}",
91
+ "$type": "color",
92
+ "$description": "Error color for text or icons that need more contrast than the base color."
93
+ },
94
+ "error-light": {
95
+ "$value": "{scope.error.soft}",
96
+ "$type": "color",
97
+ "$description": "Error tint for backgrounds behind error messages."
98
+ },
99
+ "info": {
100
+ "$value": "{scope.info.signal}",
101
+ "$type": "color",
102
+ "$description": "Neutral notices and help."
103
+ },
104
+ "info-dark": {
105
+ "$value": "{scope.info.fg}",
106
+ "$type": "color",
107
+ "$description": "Info color for text or icons that need more contrast."
108
+ },
109
+ "info-light": {
110
+ "$value": "{scope.info.soft}",
111
+ "$type": "color",
112
+ "$description": "Info tint for notice backgrounds."
113
+ },
114
+ "success": {
115
+ "$value": "{scope.success.signal}",
116
+ "$type": "color",
117
+ "$description": "Confirmations and completed states."
118
+ },
119
+ "success-dark": {
120
+ "$value": "{scope.success.fg}",
121
+ "$type": "color",
122
+ "$description": "Success color for text or icons that need more contrast."
123
+ },
124
+ "success-light": {
125
+ "$value": "{scope.success.soft}",
126
+ "$type": "color",
127
+ "$description": "Success tint for confirmation backgrounds."
128
+ },
129
+ "warning": {
130
+ "$value": "{scope.warning.signal}",
131
+ "$type": "color",
132
+ "$description": "Warnings, and the required-field marker."
133
+ },
134
+ "warning-dark": {
135
+ "$value": "{scope.warning.fg}",
136
+ "$type": "color",
137
+ "$description": "Warning color for text or icons that need more contrast."
138
+ },
139
+ "warning-light": {
140
+ "$value": "{scope.warning.soft}",
141
+ "$type": "color",
142
+ "$description": "Warning tint for caution backgrounds."
143
+ }
144
+ },
145
+ "surface": {
146
+ "base": {
147
+ "$value": "{surface.canvas}",
148
+ "$description": "Alias of canvas for components that ask for \"the background\"."
149
+ },
150
+ "canvas": {
151
+ "$value": "{scope.chrome.canvas}",
152
+ "$type": "color",
153
+ "$description": "The page itself. Paper in light mode, the darkest neutral in dark mode."
154
+ },
155
+ "overlay": {
156
+ "$value": "{scope.chrome.overlay}",
157
+ "$type": "color",
158
+ "$description": "Popups, menus and code blocks that sit above raised surfaces."
159
+ },
160
+ "raised": {
161
+ "$value": "{scope.chrome.raised}",
162
+ "$type": "color",
163
+ "$description": "Cards and panels one level above the canvas."
164
+ },
165
+ "modal": {
166
+ "$value": "{scope.chrome.modal}",
167
+ "$type": "color",
168
+ "$description": "Dialogs and drawers. Paper in light mode; in dark mode one step lighter than the page, so a modal lifts off the dimmed page under it."
169
+ },
170
+ "tray": {
171
+ "$value": "{scope.chrome.tray}",
172
+ "$type": "color",
173
+ "$description": "The strip behind a row of controls (toolbars, toggle groups). A step off the page in both themes, so the controls sitting on it stand out, while secondary and accent text on it still pass AA."
174
+ },
175
+ "inverse": {
176
+ "$value": "{scope.chrome.inverse}",
177
+ "$type": "color",
178
+ "$description": "Dark-on-light flip for small floating things such as tooltips. Inside a brand pair it becomes the pair's text color."
179
+ }
180
+ },
181
+ "text": {
182
+ "accent": {
183
+ "$value": "{scope.accent.fg}",
184
+ "$type": "color",
185
+ "$description": "Accent text such as active tabs. One step darker than the interactive color so it stays AA as text."
186
+ },
187
+ "disabled": {
188
+ "$value": "{scope.chrome.soft-strong}",
189
+ "$type": "color",
190
+ "$description": "Text in disabled controls. Deliberately below AA, which WCAG allows for disabled UI."
191
+ },
192
+ "on-accent": {
193
+ "$value": "{text.on-primary}",
194
+ "$description": "Alias for text placed on any accent fill."
195
+ },
196
+ "on-primary": {
197
+ "$value": "{scope.accent.on-solid}",
198
+ "$type": "color",
199
+ "$description": "Text on the accent fill: that step's own on-color, so it reads on any accent the brand picks."
200
+ },
201
+ "primary": {
202
+ "$value": "{scope.chrome.fg}",
203
+ "$type": "color",
204
+ "$description": "Body text and headings. The highest-contrast neutral."
205
+ },
206
+ "secondary": {
207
+ "$value": "{scope.chrome.fg-secondary}",
208
+ "$type": "color",
209
+ "$description": "Supporting text such as descriptions and helper copy. Over 7:1 on every surface, and darker still under prefers-contrast: more."
210
+ },
211
+ "tertiary": {
212
+ "$value": "{scope.chrome.fg-tertiary}",
213
+ "$type": "color",
214
+ "$description": "Placeholders, captions and metadata. The lightest text that still passes AA (4.5:1) on every surface."
215
+ },
216
+ "on-tint": {
217
+ "$value": "{scope.accent.on-soft}",
218
+ "$type": "color",
219
+ "$description": "Text on an accent wash (interactive.tint*). Stays in the accent family."
220
+ },
221
+ "on-tint-strong": {
222
+ "$value": "{scope.accent.ink}",
223
+ "$type": "color",
224
+ "$description": "Text on the selected accent wash, a step darker than on-tint."
225
+ },
226
+ "on-inverse": {
227
+ "$value": "{scope.chrome.on-solid}",
228
+ "$type": "color",
229
+ "$description": "Text on fill.inverse."
230
+ },
231
+ "on-inverse-surface": {
232
+ "$value": "{scope.chrome.on-inverse}",
233
+ "$type": "color",
234
+ "$description": "Text on surface.inverse (tooltips): the on-color of the inverse step, so it passes AA in both themes."
235
+ }
236
+ },
237
+ "fill": {
238
+ "$description": "Neutral fills for shapes that aren't surfaces: tracks, chips, hovered rows. Ordered by weight.",
239
+ "subtle": {
240
+ "$value": "{scope.chrome.soft}",
241
+ "$type": "color",
242
+ "$description": "Lightest fill: hovered rows, chips, empty tracks."
243
+ },
244
+ "default": {
245
+ "$value": "{scope.chrome.soft-hover}",
246
+ "$type": "color",
247
+ "$description": "Standard fill: slider and switch tracks, pressed rows."
248
+ },
249
+ "strong": {
250
+ "$value": "{scope.chrome.soft-active}",
251
+ "$type": "color",
252
+ "$description": "Heaviest fill: scroll thumbs, slider marks, hovered tracks."
253
+ },
254
+ "inverse": {
255
+ "$value": "{scope.chrome.solid}",
256
+ "$type": "color",
257
+ "$description": "A small solid chip in the chrome color that flips with the theme: dark on light pages, light on dark ones. Keyboard keys use it."
258
+ },
259
+ "stronger": {
260
+ "$value": "{scope.chrome.soft-strong}",
261
+ "$type": "color",
262
+ "$description": "One step past fill.strong, for the hover state of a strong fill such as a scrollbar thumb."
263
+ },
264
+ "track": {
265
+ "$value": "{scope.chrome.track}",
266
+ "$type": "color",
267
+ "$description": "The empty part of a meter or progress bar. Light like fill.subtle in light mode; near the page in dark mode, so any palette's fill reads 3:1 against it."
268
+ }
269
+ }
270
+ }
@@ -0,0 +1,124 @@
1
+ {
2
+ "content": {
3
+ "blockquote-border": {
4
+ "$value": "{border.accent}",
5
+ "$type": "color",
6
+ "$description": "Accent bar beside quotes so they read as quoted at a glance."
7
+ },
8
+ "blockquote-cite": {
9
+ "$value": "{text.tertiary}",
10
+ "$type": "color",
11
+ "$description": "Attribution under a quote, quieter than the quote itself."
12
+ },
13
+ "code-background": {
14
+ "$value": "{surface.overlay}",
15
+ "$type": "color",
16
+ "$description": "Inline code chip, tinted like an overlay so it separates from prose."
17
+ },
18
+ "code-border": {
19
+ "$value": "{border.default}",
20
+ "$type": "color",
21
+ "$description": "Outline for inline code chips."
22
+ },
23
+ "code-text": {
24
+ "$value": "{text.on-tint}",
25
+ "$type": "color",
26
+ "$description": "Inline code text in the accent's on-tint color so it stands apart from body text."
27
+ },
28
+ "field-border": {
29
+ "$value": "{border.default}",
30
+ "$type": "color",
31
+ "$description": "Borders for form fields rendered inside prose."
32
+ },
33
+ "hr-border": {
34
+ "$value": "{border.default}",
35
+ "$type": "color",
36
+ "$description": "Horizontal rules between prose sections."
37
+ },
38
+ "kbd-background": {
39
+ "$value": "{fill.inverse}",
40
+ "$type": "color",
41
+ "$description": "Keyboard keys render inverted (dark keys on light pages, light keys on dark ones) to look like keycaps."
42
+ },
43
+ "kbd-text": {
44
+ "$value": "{text.on-inverse}",
45
+ "$description": "Text on keycaps."
46
+ },
47
+ "link-color": {
48
+ "$value": "{interactive.default}",
49
+ "$type": "color",
50
+ "$description": "Links in running text. Same as the interactive accent so links and buttons agree."
51
+ },
52
+ "link-hover-color": {
53
+ "$value": "{interactive.hover}",
54
+ "$type": "color",
55
+ "$description": "Link hover, one step toward more contrast."
56
+ },
57
+ "link-underline-color": {
58
+ "$value": "color-mix(in oklab, {content.link-color} 45%, transparent)",
59
+ "$type": "color",
60
+ "$description": "The link color at 45% opacity, so underlines stay calmer than the text in long paragraphs and follow the link in every theme."
61
+ },
62
+ "link-underline-hover-color": {
63
+ "$value": "{content.link-hover-color}",
64
+ "$type": "color",
65
+ "$description": "Underline darkens on hover to confirm the target."
66
+ },
67
+ "list-marker-color": {
68
+ "$value": "{interactive.default}",
69
+ "$type": "color",
70
+ "$description": "Bullets and numbers in the accent so lists scan quickly."
71
+ },
72
+ "mark-background": {
73
+ "$value": "{interactive.tint-hover}",
74
+ "$type": "color",
75
+ "$description": "Highlighted text (<mark>), an accent tint."
76
+ },
77
+ "page-background": {
78
+ "$value": "{surface.canvas}",
79
+ "$description": "Background for long-form content pages."
80
+ },
81
+ "pre-background": {
82
+ "$value": "{surface.canvas}",
83
+ "$description": "Code block background."
84
+ },
85
+ "pre-border": {
86
+ "$value": "{border.default}",
87
+ "$type": "color",
88
+ "$description": "Code block outline."
89
+ },
90
+ "pre-text": {
91
+ "$value": "{content.prose-color}",
92
+ "$description": "Code block text, the same as prose."
93
+ },
94
+ "prose-color": {
95
+ "$value": "{text.primary}",
96
+ "$type": "color",
97
+ "$description": "Long-form body text. The same as body text, so prose and UI read as one voice."
98
+ },
99
+ "scrollbar-thumb": {
100
+ "$value": "{fill.strong}",
101
+ "$type": "color",
102
+ "$description": "Scrollbar thumb at rest."
103
+ },
104
+ "scrollbar-thumb-hover": {
105
+ "$value": "{fill.stronger}",
106
+ "$type": "color",
107
+ "$description": "Scrollbar thumb on hover, slightly stronger."
108
+ },
109
+ "scrollbar-track": {
110
+ "$value": "transparent",
111
+ "$description": "Scrollbar track stays transparent so it does not add a stripe to every panel."
112
+ },
113
+ "selection-background": {
114
+ "$value": "{interactive.tint-hover}",
115
+ "$type": "color",
116
+ "$description": "Text selection highlight, an accent tint."
117
+ },
118
+ "selection-text": {
119
+ "$value": "{text.primary}",
120
+ "$type": "color",
121
+ "$description": "Selected text stays body text so it reads the same on the tint."
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "disclosure": {
3
+ "$description": "Controls that show and hide a panel: Accordion, Collapsible and Tabs. They share hover and press fills, the chevron, the divider and the motion, so every show-and-hide reads the same way.",
4
+ "trigger-background-hover": {
5
+ "$value": "{fill.subtle}",
6
+ "$description": "A trigger under the pointer, the same light fill as a hovered row."
7
+ },
8
+ "trigger-background-active": {
9
+ "$value": "{fill.default}",
10
+ "$description": "A trigger being pressed, one step stronger than hover."
11
+ },
12
+ "icon-color": {
13
+ "$value": "{text.secondary}",
14
+ "$description": "The chevron that turns as a panel opens."
15
+ },
16
+ "content-color": {
17
+ "$value": "{text.secondary}",
18
+ "$description": "Text inside an opened accordion or collapsible panel, quieter than the trigger that names it."
19
+ },
20
+ "divider-color": {
21
+ "$value": "{border.default}",
22
+ "$description": "Line between accordion items and under a tab list."
23
+ },
24
+ "indicator-color": {
25
+ "$value": "{border.accent}",
26
+ "$description": "The line under the selected tab."
27
+ },
28
+ "indicator-width": {
29
+ "$value": "{stroke.emphasis}",
30
+ "$description": "Selected tab line thickness."
31
+ },
32
+ "selected-color": {
33
+ "$value": "{text.accent}",
34
+ "$description": "Selected tab text."
35
+ },
36
+ "opacity-disabled": {
37
+ "$value": "0.5",
38
+ "$description": "A disabled trigger fades as well as graying out."
39
+ },
40
+ "animation-duration": {
41
+ "$value": "{duration.normal}",
42
+ "$description": "How long a panel takes to open or close, and the chevron to turn."
43
+ },
44
+ "animation-easing": {
45
+ "$value": "{easing.in-out}",
46
+ "$description": "Panels grow and shrink in place, so they ease both ways."
47
+ }
48
+ }
49
+ }