@dxos/ui-theme 0.8.4-main.c85a9c8dae → 0.8.4-main.d05539e30a

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 (164) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/index.mjs +423 -499
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/node-esm/index.mjs +423 -499
  7. package/dist/lib/node-esm/index.mjs.map +4 -4
  8. package/dist/lib/node-esm/meta.json +1 -1
  9. package/dist/plugin/node-cjs/{theme.css → main.css} +204 -125
  10. package/dist/plugin/node-cjs/main.css.map +7 -0
  11. package/dist/plugin/node-cjs/meta.json +1 -1
  12. package/dist/plugin/node-cjs/plugins/ThemePlugin.cjs +8 -15
  13. package/dist/plugin/node-cjs/plugins/ThemePlugin.cjs.map +3 -3
  14. package/dist/plugin/node-esm/{theme.css → main.css} +204 -125
  15. package/dist/plugin/node-esm/main.css.map +7 -0
  16. package/dist/plugin/node-esm/meta.json +1 -1
  17. package/dist/plugin/node-esm/plugins/ThemePlugin.mjs +8 -15
  18. package/dist/plugin/node-esm/plugins/ThemePlugin.mjs.map +3 -3
  19. package/dist/types/src/Theme.stories.d.ts.map +1 -1
  20. package/dist/types/src/defs.d.ts +2 -2
  21. package/dist/types/src/defs.d.ts.map +1 -1
  22. package/dist/types/src/fragments/density.d.ts +1 -4
  23. package/dist/types/src/fragments/density.d.ts.map +1 -1
  24. package/dist/types/src/fragments/hover.d.ts +0 -1
  25. package/dist/types/src/fragments/hover.d.ts.map +1 -1
  26. package/dist/types/src/fragments/index.d.ts +0 -5
  27. package/dist/types/src/fragments/index.d.ts.map +1 -1
  28. package/dist/types/src/fragments/text.d.ts +0 -5
  29. package/dist/types/src/fragments/text.d.ts.map +1 -1
  30. package/dist/types/src/index.d.ts +1 -1
  31. package/dist/types/src/index.d.ts.map +1 -1
  32. package/dist/types/src/plugins/ThemePlugin.d.ts +1 -1
  33. package/dist/types/src/plugins/ThemePlugin.d.ts.map +1 -1
  34. package/dist/types/src/theme/components/avatar.d.ts.map +1 -1
  35. package/dist/types/src/theme/components/button.d.ts +2 -2
  36. package/dist/types/src/theme/components/button.d.ts.map +1 -1
  37. package/dist/types/src/theme/components/card.d.ts +3 -2
  38. package/dist/types/src/theme/components/card.d.ts.map +1 -1
  39. package/dist/types/src/theme/components/dialog.d.ts.map +1 -1
  40. package/dist/types/src/theme/components/focus.d.ts +6 -0
  41. package/dist/types/src/theme/components/focus.d.ts.map +1 -0
  42. package/dist/types/src/theme/components/icon-button.d.ts +1 -0
  43. package/dist/types/src/theme/components/icon-button.d.ts.map +1 -1
  44. package/dist/types/src/theme/components/icon.d.ts +3 -0
  45. package/dist/types/src/theme/components/icon.d.ts.map +1 -1
  46. package/dist/types/src/theme/components/index.d.ts +1 -0
  47. package/dist/types/src/theme/components/index.d.ts.map +1 -1
  48. package/dist/types/src/theme/components/input.d.ts +8 -8
  49. package/dist/types/src/theme/components/input.d.ts.map +1 -1
  50. package/dist/types/src/theme/components/link.d.ts.map +1 -1
  51. package/dist/types/src/theme/components/list.d.ts.map +1 -1
  52. package/dist/types/src/theme/components/main.d.ts.map +1 -1
  53. package/dist/types/src/theme/components/message.d.ts.map +1 -1
  54. package/dist/types/src/theme/components/popover.d.ts.map +1 -1
  55. package/dist/types/src/theme/components/scroll-area.d.ts +12 -2
  56. package/dist/types/src/theme/components/scroll-area.d.ts.map +1 -1
  57. package/dist/types/src/theme/components/select.d.ts.map +1 -1
  58. package/dist/types/src/theme/components/status.d.ts +1 -1
  59. package/dist/types/src/theme/components/status.d.ts.map +1 -1
  60. package/dist/types/src/theme/components/toast.d.ts.map +1 -1
  61. package/dist/types/src/theme/components/toolbar.d.ts +0 -1
  62. package/dist/types/src/theme/components/toolbar.d.ts.map +1 -1
  63. package/dist/types/src/theme/components/tooltip.d.ts.map +1 -1
  64. package/dist/types/src/theme/components/treegrid.d.ts.map +1 -1
  65. package/dist/types/src/theme/index.d.ts +1 -0
  66. package/dist/types/src/theme/index.d.ts.map +1 -1
  67. package/dist/types/src/theme/primitives/column.d.ts +25 -3
  68. package/dist/types/src/theme/primitives/column.d.ts.map +1 -1
  69. package/dist/types/src/theme/primitives/panel.d.ts +9 -5
  70. package/dist/types/src/theme/primitives/panel.d.ts.map +1 -1
  71. package/dist/types/src/theme/theme.d.ts.map +1 -1
  72. package/dist/types/src/util/elevation.d.ts.map +1 -0
  73. package/dist/types/src/util/hash-styles.d.ts +1 -1
  74. package/dist/types/src/util/hash-styles.d.ts.map +1 -1
  75. package/dist/types/src/util/index.d.ts +3 -0
  76. package/dist/types/src/util/index.d.ts.map +1 -1
  77. package/dist/types/src/util/mx.d.ts +52 -4
  78. package/dist/types/src/util/mx.d.ts.map +1 -1
  79. package/dist/types/src/util/size.d.ts +27 -0
  80. package/dist/types/src/util/size.d.ts.map +1 -0
  81. package/dist/types/src/util/valence.d.ts +4 -0
  82. package/dist/types/src/util/valence.d.ts.map +1 -0
  83. package/dist/types/tsconfig.tsbuildinfo +1 -1
  84. package/package.json +15 -18
  85. package/src/Theme.stories.tsx +5 -5
  86. package/src/css/DESIGN_SYSTEM.md +159 -0
  87. package/src/css/base/base.css +2 -2
  88. package/src/css/components/button.css +4 -3
  89. package/src/css/components/checkbox.css +1 -1
  90. package/src/css/components/{focus-ring.css → focus.css} +27 -13
  91. package/src/css/components/icon.css +9 -0
  92. package/src/css/components/link.css +3 -0
  93. package/src/css/components/panel.css +45 -45
  94. package/src/css/components/selected.css +76 -0
  95. package/src/css/components/selected.md +101 -0
  96. package/src/css/components/surface.css +4 -4
  97. package/src/css/components/tag.css +25 -23
  98. package/src/css/integrations/codemirror.css +5 -3
  99. package/src/css/integrations/tldraw.css +1 -0
  100. package/src/css/layout/main.css +0 -7
  101. package/src/css/layout/size.css +19 -27
  102. package/src/css/theme/animation.css +31 -0
  103. package/src/css/theme/palette.css +8 -0
  104. package/src/css/theme/semantic.css +48 -36
  105. package/src/css/theme/spacing.css +37 -20
  106. package/src/css/theme/styles.css +22 -22
  107. package/src/css/utilities.css +114 -3
  108. package/src/defs.ts +2 -2
  109. package/src/fragments/AUDIT.md +55 -0
  110. package/src/fragments/density.ts +8 -5
  111. package/src/fragments/hover.ts +0 -2
  112. package/src/fragments/index.ts +1 -6
  113. package/src/fragments/text.ts +1 -6
  114. package/src/index.ts +1 -1
  115. package/src/{theme.css → main.css} +48 -10
  116. package/src/plugins/ThemePlugin.ts +12 -24
  117. package/src/plugins/main.css +45 -0
  118. package/src/theme/components/avatar.ts +3 -4
  119. package/src/theme/components/button.ts +3 -3
  120. package/src/theme/components/card.ts +19 -11
  121. package/src/theme/components/dialog.ts +4 -3
  122. package/src/theme/components/focus.ts +33 -0
  123. package/src/theme/components/icon-button.ts +6 -5
  124. package/src/theme/components/icon.ts +13 -4
  125. package/src/theme/components/index.ts +1 -0
  126. package/src/theme/components/input.ts +18 -33
  127. package/src/theme/components/link.ts +1 -2
  128. package/src/theme/components/list.ts +4 -4
  129. package/src/theme/components/menu.ts +4 -4
  130. package/src/theme/components/message.ts +6 -7
  131. package/src/theme/components/popover.ts +4 -5
  132. package/src/theme/components/scroll-area.ts +58 -46
  133. package/src/theme/components/select.ts +3 -4
  134. package/src/theme/components/status.ts +5 -5
  135. package/src/theme/components/toast.ts +2 -3
  136. package/src/theme/components/toolbar.ts +1 -7
  137. package/src/theme/components/tooltip.ts +2 -3
  138. package/src/theme/components/treegrid.ts +1 -1
  139. package/src/theme/index.ts +1 -0
  140. package/src/theme/primitives/column.ts +49 -8
  141. package/src/theme/primitives/panel.ts +19 -23
  142. package/src/theme/theme.ts +2 -0
  143. package/src/typings.d.ts +3 -0
  144. package/src/util/hash-styles.ts +19 -19
  145. package/src/util/index.ts +3 -0
  146. package/src/util/mx.ts +119 -8
  147. package/src/util/size.ts +103 -0
  148. package/dist/plugin/node-cjs/theme.css.map +0 -7
  149. package/dist/plugin/node-esm/theme.css.map +0 -7
  150. package/dist/types/src/fragments/elevation.d.ts.map +0 -1
  151. package/dist/types/src/fragments/focus.d.ts +0 -4
  152. package/dist/types/src/fragments/focus.d.ts.map +0 -1
  153. package/dist/types/src/fragments/selected.d.ts +0 -4
  154. package/dist/types/src/fragments/selected.d.ts.map +0 -1
  155. package/dist/types/src/fragments/size.d.ts +0 -7
  156. package/dist/types/src/fragments/size.d.ts.map +0 -1
  157. package/dist/types/src/fragments/valence.d.ts +0 -4
  158. package/dist/types/src/fragments/valence.d.ts.map +0 -1
  159. package/src/fragments/focus.ts +0 -11
  160. package/src/fragments/selected.ts +0 -12
  161. package/src/fragments/size.ts +0 -117
  162. /package/dist/types/src/{fragments → util}/elevation.d.ts +0 -0
  163. /package/src/{fragments → util}/elevation.ts +0 -0
  164. /package/src/{fragments → util}/valence.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/ui-theme",
3
- "version": "0.8.4-main.c85a9c8dae",
3
+ "version": "0.8.4-main.d05539e30a",
4
4
  "description": "A set of design system tokens to use with DXOS UI.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -8,7 +8,7 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/dxos/dxos"
10
10
  },
11
- "license": "MIT",
11
+ "license": "FSL-1.1-Apache-2.0",
12
12
  "author": "DXOS.org",
13
13
  "sideEffects": [
14
14
  "*.css"
@@ -27,13 +27,6 @@
27
27
  "require": "./dist/plugin/node-cjs/plugins/ThemePlugin.cjs"
28
28
  }
29
29
  },
30
- "typesVersions": {
31
- "*": {
32
- "plugin": [
33
- "dist/types/src/plugins/ThemePlugin.d.ts"
34
- ]
35
- }
36
- },
37
30
  "files": [
38
31
  "dist",
39
32
  "src"
@@ -42,29 +35,33 @@
42
35
  "@fontsource-variable/inter": "5.2.8",
43
36
  "@fontsource-variable/jetbrains-mono": "5.0.21",
44
37
  "@fontsource/poiret-one": "^5.0.20",
38
+ "@radix-ui/react-slot": "1.1.2",
45
39
  "@tailwindcss/forms": "^0.5.9",
46
40
  "@tailwindcss/postcss": "^4.2.0",
47
- "autoprefixer": "^10.4.12",
48
- "esbuild-style-plugin": "^1.6.1",
49
- "glob": "^7.2.3",
41
+ "autoprefixer": "^10.5.0",
42
+ "esbuild-style-plugin": "^1.6.3",
50
43
  "globby": "14.1.0",
51
44
  "lodash.merge": "^4.6.2",
52
- "postcss": "^8.4.41",
45
+ "postcss": "^8.5.12",
53
46
  "postcss-import": "^16.1.0",
54
47
  "postcss-nesting": "^13.0.1",
55
48
  "tailwind-merge": "^3.5.0",
56
49
  "tailwind-scrollbar": "^4.0.0",
57
50
  "tailwindcss": "^4.2.0",
58
51
  "tailwindcss-radix": "^4.0.2",
59
- "@dxos/util": "0.8.4-main.c85a9c8dae",
60
- "@dxos/node-std": "0.8.4-main.c85a9c8dae"
52
+ "@dxos/log": "0.8.4-main.d05539e30a",
53
+ "@dxos/node-std": "0.8.4-main.d05539e30a",
54
+ "@dxos/util": "0.8.4-main.d05539e30a"
61
55
  },
62
56
  "devDependencies": {
63
57
  "@types/lodash.merge": "^4.6.6",
64
58
  "@types/postcss-import": "^14.0.3",
65
- "esbuild": "0.25.11",
66
- "vite": "^7.1.11",
67
- "@dxos/ui-types": "0.8.4-main.c85a9c8dae"
59
+ "esbuild": "0.28.0",
60
+ "vite": "^8.0.13",
61
+ "@dxos/ui-types": "0.8.4-main.d05539e30a"
62
+ },
63
+ "peerDependencies": {
64
+ "react": "~19.2.3"
68
65
  },
69
66
  "publishConfig": {
70
67
  "access": "public"
@@ -37,8 +37,8 @@ const ColorSwatch = ({ hue }: { hue: string }) => {
37
37
  >
38
38
  <div
39
39
  style={{
40
- color: `var(--color-${hue}-text)`,
41
40
  backgroundColor: `var(--color-base-surface)`,
41
+ color: `var(--color-${hue}-text)`,
42
42
  }}
43
43
  className='p-2 text-sm'
44
44
  >
@@ -46,8 +46,8 @@ const ColorSwatch = ({ hue }: { hue: string }) => {
46
46
  </div>
47
47
  <div
48
48
  style={{
49
- color: `var(--color-${hue}-text)`,
50
49
  backgroundColor: `var(--color-${hue}-fill)`,
50
+ color: `var(--color-${hue}-text)`,
51
51
  }}
52
52
  className='px-1 text-sm flex items-center'
53
53
  >
@@ -57,8 +57,8 @@ const ColorSwatch = ({ hue }: { hue: string }) => {
57
57
  </div>
58
58
  <div
59
59
  style={{
60
- color: `var(--color-${hue}-surface-text)`,
61
60
  backgroundColor: `var(--color-${hue}-surface)`,
61
+ color: `var(--color-${hue}-foreground)`,
62
62
  }}
63
63
  className='p-2 text-sm'
64
64
  >
@@ -163,9 +163,9 @@ export const Surfaces = {
163
163
  { className: 'bg-card-surface', label: 'card' },
164
164
  { className: 'bg-modal-surface', label: 'modal' },
165
165
  { className: 'bg-input-surface', label: 'input' },
166
- { className: 'bg-active-surface', label: 'active' },
166
+ { className: 'bg-current-surface', label: 'current' },
167
167
  { className: 'bg-hover-surface', label: 'hover' },
168
- { className: 'bg-inverse-surface text-inverse-surface-text', label: 'inverse' },
168
+ { className: 'bg-inverse-surface text-inverse-foreground', label: 'inverse' },
169
169
  ].map(({ className, label }) => (
170
170
  <div key={className} className={mx('shrink-0 p-2 aspect-square w-48 rounded-md', className)}>
171
171
  {label}
@@ -0,0 +1,159 @@
1
+ # Design System: Color Tokens
2
+
3
+ This document describes how color tokens are organized in `ui-theme`, the naming rules they follow, and the rationalization of overlapping state tokens (`current` / `active` / `highlight` / `selected` / `hover`) and text-on-surface tokens (`surface-text` → `foreground`).
4
+
5
+ ## Token tiers
6
+
7
+ Three layers, each consuming the one below:
8
+
9
+ | Tier | File | Purpose | Example |
10
+ | ----------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
11
+ | 1. Scale | [`theme/palette.css`](./theme/palette.css) | Raw color values. Extends Tailwind's neutral/blue scales with intermediate stops and aliases the `primary-*` ramp to `blue-*`. | `--color-neutral-150`, `--color-primary-500` |
12
+ | 2. Hue role | [`theme/styles.css`](./theme/styles.css) | Per-hue role tokens generated mechanically for every Tailwind hue plus `neutral`. Five roles each: `fill`, `surface`, `foreground`, `text`, `border`. Light/dark resolved via `light-dark()`. | `--color-red-surface`, `--color-neutral-border` |
13
+ | 3. Semantic | [`theme/semantic.css`](./theme/semantic.css) | Named UI surfaces and states. May reference hue-role tokens (e.g. `error-surface` → `rose-surface`) or compose directly from the scale. | `--color-card-surface`, `--color-current-surface`, `--color-error-text` |
14
+
15
+ A consumer should reach for the highest tier that fits. Use `bg-card-surface`, not `bg-neutral-75`. Use `text-error-text`, not `text-rose-700`.
16
+
17
+ ## Naming convention
18
+
19
+ Token names follow `--color-{name}-{part}[-{state}]`:
20
+
21
+ - **`name`** identifies the role or surface (`card`, `current`, `accent`, `error`, `red`).
22
+ - **`part`** is one of a fixed vocabulary:
23
+ - `surface` — the background fill of a thing.
24
+ - `foreground` — the text/icon color that sits on the surface (paired with `surface`).
25
+ - `border` — border color on the surface.
26
+ - `fill` — solid attention-grabbing fill (badges, dots, indicators); more saturated than `surface`.
27
+ - `text` — text color used standalone, on the base canvas (no enclosing surface).
28
+ - **`state`** is optional, appended last: `hover`, `active` (pressed). State always follows the part it modifies.
29
+
30
+ ### Pattern rules
31
+
32
+ - Suffix order is fixed: `{name}-{part}-{state}`. The part comes first, then the state.
33
+ - Pair rule: every `{name}-surface` that hosts text has a matching `{name}-foreground`. Don't invent new ink-suffix names — keep the vocabulary closed.
34
+ - A state token implies a base — `current-surface-hover` only makes sense if `current-surface` exists.
35
+ - The `-text` part (standalone) is reserved for text on the base canvas, with no enclosing surface (e.g. `accent-text` for a hyperlink in body copy). Text on any named surface uses `{name}-foreground`.
36
+
37
+ ## Surfaces
38
+
39
+ Layered fills, ordered from recessive to prominent:
40
+
41
+ ```
42
+ base-surface n-50 / n-950 the page canvas
43
+ deck-surface n-50 / n-950 deck panes
44
+ toolbar-surface n-75 / n-925 toolbars
45
+ card-surface n-75 / n-925 cards
46
+ group-surface n-100 / n-900 grouped containers
47
+ modal-surface n-100 / n-900 modals / dialogs
48
+ sidebar-surface n-100 / n-900 sidebars
49
+ header-surface n-100 / n-900 headers
50
+ input-surface n-200 / n-800 form controls
51
+ ```
52
+
53
+ Each surface that hosts text declares a matching `*-foreground` (defaulting to `n-950 / n-50`).
54
+
55
+ ## State tokens (rationalized)
56
+
57
+ The system has three orthogonal states. Pick by what the ARIA / markup is saying.
58
+
59
+ | State | Token | When | Value |
60
+ | -------------------------- | ------------------------ | ---------------------------------------------------------------- | ----------------- |
61
+ | Active item, one-of-N | `current-surface` | `aria-current=true` (nav cursor, current row, current path) | `n-100` / `n-900` |
62
+ | Hovering on current item | `current-surface-hover` | pointer-over on a `current` element | `n-200` / `n-800` |
63
+ | Text on a current surface | `current-foreground` | text/icon color paired with `current-surface` | `n-950` / `n-50` |
64
+ | Selected / checked | `selected-surface` | `aria-selected=true` (multi-select, listbox option, checked row) | `n-150` / `n-850` |
65
+ | Hovering on selected | `selected-surface-hover` | pointer-over on a `selected` element | `n-250` / `n-750` |
66
+ | Text on a selected surface | `selected-foreground` | text/icon color paired with `selected-surface` | `n-950` / `n-50` |
67
+ | Transient pointer-over | `hover-surface` | `:hover`, Radix `data-highlighted` (keyboard cursor in menus) | `n-250` / `n-750` |
68
+ | Text on a transient hover | `hover-foreground` | text/icon color paired with `hover-surface` | `n-950` / `n-50` |
69
+
70
+ **Why these three.** `current` describes one-of-N navigation/selection state ("you are here"); `selected` describes a checked item in a set (multi-select-able); `hover` is transient pointer feedback. Driving the distinction off ARIA keeps markup and tokens in sync.
71
+
72
+ ### Visual hierarchy
73
+
74
+ ```
75
+ card-surface n-75 / n-925 resting
76
+ current-surface n-100 / n-900 "I am the active one"
77
+ current-surface-hover n-200 / n-800 hovering the active one
78
+ hover-surface n-250 / n-750 transient pointer-over anywhere else
79
+ ```
80
+
81
+ ## Consolidation: tokens that go away
82
+
83
+ These are merged into the rationalized state vocabulary:
84
+
85
+ | Removed | Replaced by | Notes |
86
+ | ------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
87
+ | `active-surface` | `current-surface` | Same concept ("the active one"). Same value already. |
88
+ | `active-text` | `current-foreground` | Renamed and reclassified — it was always foreground (text on the surface), not `text`. |
89
+ | `highlight-surface` | `current-surface` | `selected.css` used it for `aria-current=true`. |
90
+ | `highlight-surface-hover` | `current-surface-hover` | |
91
+ | `highlight-surface-text` | `current-foreground` | Rename to the new `-foreground` suffix. |
92
+ | `*-surface-text` (all) | `*-foreground` | Repository-wide rename for every hue, semantic, and named-surface token (e.g. `base-surface-text` → `base-foreground`, `red-surface-text` → `red-foreground`, `error-surface-text` → `error-foreground`). |
93
+
94
+ ### Visual change to expect
95
+
96
+ The 9 `bg-active-surface` call sites become one shade subtler (from `n-200/800` to `n-100/900`). This aligns them with the existing `selected.css` treatment of `aria-current=true` and produces the coherent layering shown above.
97
+
98
+ ### Out-of-scope drift to fix separately
99
+
100
+ Two sites use `bg-hover-surface` as a _resting_ fill (not a hover state):
101
+
102
+ - [packages/plugins/plugin-navtree/src/experimental/Tree.tsx:196](../../../../plugins/plugin-navtree/src/experimental/Tree.tsx)
103
+ - [packages/plugins/plugin-script/src/components/TestPanel/TestPanel.tsx:171](../../../../plugins/plugin-script/src/components/TestPanel/TestPanel.tsx)
104
+
105
+ These should probably move to `card-surface` or `current-surface` depending on intent. Tracked as a follow-up; not part of this rationalization.
106
+
107
+ ## Accent (primary)
108
+
109
+ `accent-*` is the project's primary brand color (blue). The token name is `accent`, not `primary`, to avoid colliding with the raw scale `--color-primary-*` (which is aliased to `blue-*` for Tailwind utility convenience).
110
+
111
+ | Token | Purpose |
112
+ | ---------------------- | --------------------------------------------------- |
113
+ | `accent-surface` | Fill for primary buttons / call-to-action surfaces. |
114
+ | `accent-surface-hover` | Hover state. |
115
+ | `accent-foreground` | Text/icon color on accent surfaces. |
116
+ | `accent-text` | Standalone accent-colored text (links, emphasis). |
117
+ | `accent-text-hover` | Hover state for accent text. |
118
+
119
+ This is the canonical illustration of the `foreground` vs `text` distinction: `accent-foreground` is the ink on an accent button; `accent-text` is the accent-colored body link.
120
+
121
+ Note: `accent-focus-indicator` is removed — focus rings are now global tokens (see [Focus rings](#focus-rings)).
122
+
123
+ ## Focus rings
124
+
125
+ Focus indicators are a global UI affordance, not a per-surface property. Every focusable element should pick from the same small set of ring colors so focus stays visually consistent and accessible.
126
+
127
+ | Token | Value | Used by |
128
+ | ------------------- | ----------------- | -------------------------------------------------------- |
129
+ | `focus-ring` | `blue-600` | Default focus ring (buttons, inputs, grid cells, links). |
130
+ | `focus-ring-subtle` | `n-400` / `n-600` | Subdued ring for low-emphasis focusable elements. |
131
+
132
+ Tokens removed in this rationalization:
133
+
134
+ | Removed | Replaced by | Notes |
135
+ | ------------------------- | ------------------- | -------------------------------------------------------------- |
136
+ | `accent-focus-indicator` | `focus-ring` | Was `blue-600`. Same value. |
137
+ | `grid-focus-indicator` | `focus-ring` | Was `primary-600` (= `blue-600`). Identical to accent variant. |
138
+ | `neutral-focus-indicator` | `focus-ring-subtle` | Was `n-400` / `n-600`. Same value. |
139
+
140
+ ## Semantic aliases
141
+
142
+ Status colors point at hue-role tokens:
143
+
144
+ | Token | Aliases |
145
+ | ----------- | ----------- |
146
+ | `info-*` | `cyan-*` |
147
+ | `success-*` | `emerald-*` |
148
+ | `warning-*` | `amber-*` |
149
+ | `error-*` | `rose-*` |
150
+
151
+ Each provides `fill`, `surface`, `foreground`, `text`, `border`.
152
+
153
+ ## Adding a new token
154
+
155
+ 1. Does an existing semantic token already cover it? If yes, use it.
156
+ 2. Does it represent a new named surface, state, or status? Add it to `semantic.css` referencing scale or hue-role tokens — never raw hex.
157
+ 3. Follow the suffix order: `{name}-{part}[-{state}]`.
158
+ 4. If the new token will be used through a Tailwind utility that the source-scan can't see (e.g. CSS file, dynamic class), add it to `@source inline(...)` in [`main.css`](./main.css).
159
+ 5. If it ships state variants (`-hover`, `-active`), declare them adjacent to the base in the same block.
@@ -35,9 +35,9 @@
35
35
  html .dark,
36
36
  .sb-show-main {
37
37
  background-color: var(--color-base-surface);
38
- color: var(--color-base-surface-text);
38
+ color: var(--color-base-foreground);
39
39
  --surface-bg: var(--color-base-surface);
40
- --surface-text: var(--color-base-surface-text);
40
+ --foreground: var(--color-base-foreground);
41
41
  --description-text: var(--color-description);
42
42
  }
43
43
  }
@@ -10,7 +10,8 @@
10
10
 
11
11
  /* Base styles */
12
12
  .dx-button {
13
- @apply font-medium shrink-0 inline-flex select-none items-center justify-center overflow-hidden transition-colors duration-100 ease-linear bg-input-surface min-h-[2.5rem] px-3;
13
+ @apply shrink-0 inline-flex select-none items-center justify-center overflow-hidden min-h-[2rem] px-3;
14
+ @apply font-medium transition-colors duration-100 ease-linear bg-input-surface;
14
15
  &[aria-pressed='true'],
15
16
  &[aria-checked='true'] {
16
17
  @apply text-accent-text bg-attention-surface;
@@ -52,7 +53,7 @@
52
53
 
53
54
  /* Variants */
54
55
  &[data-variant='primary'] {
55
- @apply text-accent-surface-text bg-accent-surface;
56
+ @apply text-accent-foreground bg-accent-surface;
56
57
  &:hover,
57
58
  &[aria-pressed='true'],
58
59
  &[aria-checked='true'] &[data-state='open'] {
@@ -60,7 +61,7 @@
60
61
  }
61
62
  }
62
63
  &[data-variant='destructive'] {
63
- @apply text-accent-surface-text bg-rose-fill;
64
+ @apply text-accent-foreground bg-rose-fill;
64
65
  &:hover,
65
66
  &[aria-pressed='true'],
66
67
  &[aria-checked='true'] &[data-state='open'] {
@@ -27,7 +27,7 @@
27
27
  }
28
28
 
29
29
  .dx-checkbox {
30
- @apply w-4 h-4 overflow-hidden shadow-inner transition-colors bg-un-accent accent-un-accent text-accent-surface-text shrink-0 inline-grid place-items-center rounded-xs;
30
+ @apply w-4 h-4 overflow-hidden shadow-inner transition-colors bg-un-accent accent-un-accent text-accent-foreground shrink-0 inline-grid place-items-center rounded-xs;
31
31
  }
32
32
 
33
33
  /* TODO(ZaymonFC): Focus is handled by .dx-focus-ring, but should ideally be applied as part of this component.*/
@@ -12,10 +12,10 @@
12
12
  }
13
13
 
14
14
  &:focus-visible {
15
- @apply ring-focus-line ring-offset-focus-offset z-[1] ring-[var(--color-neutral-focus-indicator)];
15
+ @apply ring-focus-line ring-offset-focus-offset z-[1] ring-[var(--color-focus-ring-subtle)];
16
16
 
17
17
  &[data-variant='primary'] {
18
- @apply ring-[var(--color-accent-focus-indicator)];
18
+ @apply ring-[var(--color-focus-ring)];
19
19
  }
20
20
 
21
21
  &:hover {
@@ -29,6 +29,13 @@
29
29
  }
30
30
  }
31
31
 
32
+ .dx-focus-ring-none {
33
+ &:focus,
34
+ &:focus-visible {
35
+ @apply outline-hidden! ring-0!;
36
+ }
37
+ }
38
+
32
39
  .dx-focus-ring-always,
33
40
  .dx-focus-ring-inset-always {
34
41
  &:not([disabled]),
@@ -38,10 +45,10 @@
38
45
  }
39
46
 
40
47
  &:focus {
41
- @apply ring-focus-line ring-offset-focus-offset z-[1] ring-[var(--color-neutral-focus-indicator)];
48
+ @apply ring-focus-line ring-offset-focus-offset z-[1] ring-[var(--color-focus-ring-subtle)];
42
49
 
43
50
  &[data-variant='primary'] {
44
- @apply ring-[var(--color-accent-focus-indicator)];
51
+ @apply ring-[var(--color-focus-ring)];
45
52
  }
46
53
 
47
54
  &:hover {
@@ -72,10 +79,10 @@
72
79
  .dx-focus-ring-group:focus-visible .dx-focus-ring-group-indicator,
73
80
  .dx-focus-ring-group-x:focus-visible .dx-focus-ring-group-x-indicator,
74
81
  .dx-focus-ring-group-y:focus-visible .dx-focus-ring-group-y-indicator {
75
- @apply ring-focus-line ring-offset-focus-offset ring-[var(--color-neutral-focus-indicator)];
82
+ @apply ring-focus-line ring-offset-focus-offset ring-[var(--color-focus-ring-subtle)];
76
83
 
77
84
  &[data-variant='primary'] {
78
- @apply ring-[var(--color-accent-focus-indicator)];
85
+ @apply ring-[var(--color-focus-ring)];
79
86
  }
80
87
 
81
88
  &:hover {
@@ -90,10 +97,10 @@
90
97
  .dx-focus-ring-group-always:focus .dx-focus-ring-group-indicator,
91
98
  .dx-focus-ring-group-x-always:focus .dx-focus-ring-group-x-indicator,
92
99
  .dx-focus-ring-group-y-always:focus .dx-focus-ring-group-y-indicator {
93
- @apply ring-focus-line ring-offset-focus-offset ring-[var(--color-neutral-focus-indicator)];
100
+ @apply ring-focus-line ring-offset-focus-offset ring-[var(--color-focus-ring-subtle)];
94
101
 
95
102
  &[data-variant='primary'] {
96
- @apply ring-[var(--color-accent-focus-indicator)];
103
+ @apply ring-[var(--color-focus-ring)];
97
104
  }
98
105
 
99
106
  &:hover {
@@ -138,11 +145,11 @@
138
145
 
139
146
  &:focus-visible {
140
147
  &::after {
141
- @apply ring-focus-line ring-offset-focus-offset ring-inset z-[1] ring-[var(--color-neutral-focus-indicator)];
148
+ @apply ring-focus-line ring-offset-focus-offset ring-inset z-[1] ring-[var(--color-focus-ring-subtle)];
142
149
  }
143
150
 
144
151
  &[data-variant='primary']::after {
145
- @apply ring-[var(--color-accent-focus-indicator)];
152
+ @apply ring-[var(--color-focus-ring)];
146
153
  }
147
154
 
148
155
  &:hover {
@@ -171,16 +178,15 @@
171
178
 
172
179
  &:focus {
173
180
  &::after {
174
- @apply ring-focus-line ring-offset-focus-offset ring-inset z-[1] ring-[var(--color-neutral-focus-indicator)];
181
+ @apply ring-focus-line ring-offset-focus-offset ring-inset z-[1] ring-[var(--color-focus-ring-subtle)];
175
182
  }
176
183
 
177
184
  &[data-variant='primary']::after {
178
- @apply ring-[var(--color-accent-focus-indicator)];
185
+ @apply ring-[var(--color-focus-ring)];
179
186
  }
180
187
 
181
188
  &:hover {
182
189
  @apply outline-hidden;
183
-
184
190
  .dark & {
185
191
  @apply outline-hidden;
186
192
  }
@@ -226,4 +232,12 @@
226
232
  }
227
233
  }
228
234
  }
235
+
236
+ .dx-focus-subdued {
237
+ @apply focus:outline-hidden focus-visible:outline-hidden focus:ring-0 ring-0 focus:border-0 border-0;
238
+ }
239
+
240
+ .dx-focus-static {
241
+ @apply ring-2 ring-offset-0 ring-primary-300 ring-offset-white dark:ring-primary-400 dark:ring-offset-black;
242
+ }
229
243
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Icons
3
+ */
4
+
5
+ @layer dx-components {
6
+ .dx-icon-inline {
7
+ @apply inline-block align-[-0.125em];
8
+ }
9
+ }
@@ -6,4 +6,7 @@
6
6
  .dx-link {
7
7
  @apply text-accent-text hover:text-accent-text-hover;
8
8
  }
9
+ .dx-link-hover {
10
+ @apply hover:text-accent-text-hover;
11
+ }
9
12
  }
@@ -1,117 +1,117 @@
1
1
  /**
2
- * Panel — applies bg-{hue}-surface / text-{hue}-surface-text / border-{hue}-border tokens via data-hue attribute or BEM modifier.
2
+ * Panel — applies bg-{hue}-surface / text-{hue}-foreground / border-{hue}-border tokens via data-hue attribute or BEM modifier.
3
3
  * Example: <div className='dx-panel' data-hue='blue'>...</div>
4
4
  * Example: <div className='dx-panel dx-panel--blue'>...</div>
5
5
  */
6
6
 
7
7
  @layer dx-components {
8
- .dx-panel[data-hue='neutral'],
8
+ [data-hue='neutral'] .dx-panel,
9
9
  .dx-panel--neutral {
10
- @apply bg-neutral-surface text-neutral-surface-text border-neutral-border;
10
+ @apply bg-neutral-surface text-neutral-foreground border-neutral-border;
11
11
  }
12
12
 
13
- .dx-panel[data-hue='red'],
13
+ [data-hue='red'] .dx-panel,
14
14
  .dx-panel--red {
15
- @apply bg-red-surface text-red-surface-text border-red-border;
15
+ @apply bg-red-surface text-red-foreground border-red-border;
16
16
  }
17
17
 
18
- .dx-panel[data-hue='orange'],
18
+ [data-hue='orange'] .dx-panel,
19
19
  .dx-panel--orange {
20
- @apply bg-orange-surface text-orange-surface-text border-orange-border;
20
+ @apply bg-orange-surface text-orange-foreground border-orange-border;
21
21
  }
22
22
 
23
- .dx-panel[data-hue='amber'],
23
+ [data-hue='amber'] .dx-panel,
24
24
  .dx-panel--amber {
25
- @apply bg-amber-surface text-amber-surface-text border-amber-border;
25
+ @apply bg-amber-surface text-amber-foreground border-amber-border;
26
26
  }
27
27
 
28
- .dx-panel[data-hue='yellow'],
28
+ [data-hue='yellow'] .dx-panel,
29
29
  .dx-panel--yellow {
30
- @apply bg-yellow-surface text-yellow-surface-text border-yellow-border;
30
+ @apply bg-yellow-surface text-yellow-foreground border-yellow-border;
31
31
  }
32
32
 
33
- .dx-panel[data-hue='lime'],
33
+ [data-hue='lime'] .dx-panel,
34
34
  .dx-panel--lime {
35
- @apply bg-lime-surface text-lime-surface-text border-lime-border;
35
+ @apply bg-lime-surface text-lime-foreground border-lime-border;
36
36
  }
37
37
 
38
- .dx-panel[data-hue='green'],
38
+ [data-hue='green'] .dx-panel,
39
39
  .dx-panel--green {
40
- @apply bg-green-surface text-green-surface-text border-green-border;
40
+ @apply bg-green-surface text-green-foreground border-green-border;
41
41
  }
42
42
 
43
- .dx-panel[data-hue='emerald'],
43
+ [data-hue='emerald'] .dx-panel,
44
44
  .dx-panel--emerald {
45
- @apply bg-emerald-surface text-emerald-surface-text border-emerald-border;
45
+ @apply bg-emerald-surface text-emerald-foreground border-emerald-border;
46
46
  }
47
47
 
48
- .dx-panel[data-hue='teal'],
48
+ [data-hue='teal'] .dx-panel,
49
49
  .dx-panel--teal {
50
- @apply bg-teal-surface text-teal-surface-text border-teal-border;
50
+ @apply bg-teal-surface text-teal-foreground border-teal-border;
51
51
  }
52
52
 
53
- .dx-panel[data-hue='cyan'],
53
+ [data-hue='cyan'] .dx-panel,
54
54
  .dx-panel--cyan {
55
- @apply bg-cyan-surface text-cyan-surface-text border-cyan-border;
55
+ @apply bg-cyan-surface text-cyan-foreground border-cyan-border;
56
56
  }
57
57
 
58
- .dx-panel[data-hue='sky'],
58
+ [data-hue='sky'] .dx-panel,
59
59
  .dx-panel--sky {
60
- @apply bg-sky-surface text-sky-surface-text border-sky-border;
60
+ @apply bg-sky-surface text-sky-foreground border-sky-border;
61
61
  }
62
62
 
63
- .dx-panel[data-hue='blue'],
63
+ [data-hue='blue'] .dx-panel,
64
64
  .dx-panel--blue {
65
- @apply bg-blue-surface text-blue-surface-text border-blue-border;
65
+ @apply bg-blue-surface text-blue-foreground border-blue-border;
66
66
  }
67
67
 
68
- .dx-panel[data-hue='indigo'],
68
+ [data-hue='indigo'] .dx-panel,
69
69
  .dx-panel--indigo {
70
- @apply bg-indigo-surface text-indigo-surface-text border-indigo-border;
70
+ @apply bg-indigo-surface text-indigo-foreground border-indigo-border;
71
71
  }
72
72
 
73
- .dx-panel[data-hue='violet'],
73
+ [data-hue='violet'] .dx-panel,
74
74
  .dx-panel--violet {
75
- @apply bg-violet-surface text-violet-surface-text border-violet-border;
75
+ @apply bg-violet-surface text-violet-foreground border-violet-border;
76
76
  }
77
77
 
78
- .dx-panel[data-hue='purple'],
78
+ [data-hue='purple'] .dx-panel,
79
79
  .dx-panel--purple {
80
- @apply bg-purple-surface text-purple-surface-text border-purple-border;
80
+ @apply bg-purple-surface text-purple-foreground border-purple-border;
81
81
  }
82
82
 
83
- .dx-panel[data-hue='fuchsia'],
83
+ [data-hue='fuchsia'] .dx-panel,
84
84
  .dx-panel--fuchsia {
85
- @apply bg-fuchsia-surface text-fuchsia-surface-text border-fuchsia-border;
85
+ @apply bg-fuchsia-surface text-fuchsia-foreground border-fuchsia-border;
86
86
  }
87
87
 
88
- .dx-panel[data-hue='pink'],
88
+ [data-hue='pink'] .dx-panel,
89
89
  .dx-panel--pink {
90
- @apply bg-pink-surface text-pink-surface-text border-pink-border;
90
+ @apply bg-pink-surface text-pink-foreground border-pink-border;
91
91
  }
92
92
 
93
- .dx-panel[data-hue='rose'],
93
+ [data-hue='rose'] .dx-panel,
94
94
  .dx-panel--rose {
95
- @apply bg-rose-surface text-rose-surface-text border-rose-border;
95
+ @apply bg-rose-surface text-rose-foreground border-rose-border;
96
96
  }
97
97
 
98
- .dx-panel[data-hue='info'],
98
+ [data-hue='info'] .dx-panel,
99
99
  .dx-panel--info {
100
- @apply bg-info-surface text-info-surface-text border-info-border;
100
+ @apply bg-info-surface text-info-foreground border-info-border;
101
101
  }
102
102
 
103
- .dx-panel[data-hue='success'],
103
+ [data-hue='success'] .dx-panel,
104
104
  .dx-panel--success {
105
- @apply bg-success-surface text-success-surface-text border-success-border;
105
+ @apply bg-success-surface text-success-foreground border-success-border;
106
106
  }
107
107
 
108
- .dx-panel[data-hue='warning'],
108
+ [data-hue='warning'] .dx-panel,
109
109
  .dx-panel--warning {
110
- @apply bg-warning-surface text-warning-surface-text border-warning-border;
110
+ @apply bg-warning-surface text-warning-foreground border-warning-border;
111
111
  }
112
112
 
113
- .dx-panel[data-hue='error'],
113
+ [data-hue='error'] .dx-panel,
114
114
  .dx-panel--error {
115
- @apply bg-error-surface text-error-surface-text border-error-border;
115
+ @apply bg-error-surface text-error-foreground border-error-border;
116
116
  }
117
117
  }