@dxos/ui-theme 0.8.4-staging.ac66bdf99f → 0.9.1-main.c7dcc2e112

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 (169) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/index.mjs +89 -867
  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 +89 -867
  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/main.css +279 -120
  10. package/dist/plugin/node-cjs/main.css.map +3 -3
  11. package/dist/plugin/node-cjs/meta.json +1 -1
  12. package/dist/plugin/node-cjs/plugins/ThemePlugin.cjs +82 -10
  13. package/dist/plugin/node-cjs/plugins/ThemePlugin.cjs.map +3 -3
  14. package/dist/plugin/node-esm/main.css +279 -120
  15. package/dist/plugin/node-esm/main.css.map +3 -3
  16. package/dist/plugin/node-esm/meta.json +1 -1
  17. package/dist/plugin/node-esm/plugins/ThemePlugin.mjs +84 -12
  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 +1 -1
  21. package/dist/types/src/defs.d.ts.map +1 -1
  22. package/dist/types/src/fragments/density.d.ts +2 -2
  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/index.d.ts +0 -1
  27. package/dist/types/src/index.d.ts.map +1 -1
  28. package/dist/types/src/plugins/ThemePlugin.d.ts +3 -2
  29. package/dist/types/src/plugins/ThemePlugin.d.ts.map +1 -1
  30. package/dist/types/src/util/hash-styles.d.ts +12 -2
  31. package/dist/types/src/util/hash-styles.d.ts.map +1 -1
  32. package/dist/types/src/util/mx.d.ts +0 -36
  33. package/dist/types/src/util/mx.d.ts.map +1 -1
  34. package/dist/types/src/util/size.d.ts.map +1 -1
  35. package/dist/types/src/util/valence.d.ts +8 -2
  36. package/dist/types/src/util/valence.d.ts.map +1 -1
  37. package/dist/types/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +14 -21
  39. package/src/Theme.stories.tsx +94 -27
  40. package/src/css/DESIGN_SYSTEM.md +187 -0
  41. package/src/css/base/base.css +2 -2
  42. package/src/css/components/button.css +57 -12
  43. package/src/css/components/card.css +14 -0
  44. package/src/css/components/checkbox.css +3 -3
  45. package/src/css/components/focus.css +12 -12
  46. package/src/css/components/link.css +4 -1
  47. package/src/css/components/panel.css +45 -45
  48. package/src/css/components/state.css +76 -0
  49. package/src/css/components/state.md +101 -0
  50. package/src/css/components/surface.css +86 -11
  51. package/src/css/components/tag.css +25 -24
  52. package/src/css/integrations/codemirror.css +4 -3
  53. package/src/css/integrations/tldraw.css +1 -1
  54. package/src/css/layout/main.css +6 -0
  55. package/src/css/layout/size.css +17 -4
  56. package/src/css/theme/animation.css +31 -0
  57. package/src/css/theme/palette.css +34 -0
  58. package/src/css/theme/semantic.css +190 -68
  59. package/src/css/theme/spacing.css +30 -13
  60. package/src/css/theme/styles.css +172 -119
  61. package/src/css/utilities.css +42 -0
  62. package/src/defs.ts +3 -1
  63. package/src/fragments/AUDIT.md +0 -2
  64. package/src/fragments/density.ts +34 -7
  65. package/src/fragments/hover.ts +0 -2
  66. package/src/index.ts +1 -1
  67. package/src/main.css +68 -9
  68. package/src/plugins/ThemePlugin.ts +102 -14
  69. package/src/plugins/main.css +10 -7
  70. package/src/util/hash-styles.ts +54 -42
  71. package/src/util/mx.ts +1 -126
  72. package/src/util/valence.ts +15 -5
  73. package/dist/types/src/theme/components/avatar.d.ts +0 -21
  74. package/dist/types/src/theme/components/avatar.d.ts.map +0 -1
  75. package/dist/types/src/theme/components/breadcrumb.d.ts +0 -9
  76. package/dist/types/src/theme/components/breadcrumb.d.ts.map +0 -1
  77. package/dist/types/src/theme/components/button.d.ts +0 -15
  78. package/dist/types/src/theme/components/button.d.ts.map +0 -1
  79. package/dist/types/src/theme/components/card.d.ts +0 -12
  80. package/dist/types/src/theme/components/card.d.ts.map +0 -1
  81. package/dist/types/src/theme/components/dialog.d.ts +0 -17
  82. package/dist/types/src/theme/components/dialog.d.ts.map +0 -1
  83. package/dist/types/src/theme/components/focus.d.ts +0 -6
  84. package/dist/types/src/theme/components/focus.d.ts.map +0 -1
  85. package/dist/types/src/theme/components/icon-button.d.ts +0 -8
  86. package/dist/types/src/theme/components/icon-button.d.ts.map +0 -1
  87. package/dist/types/src/theme/components/icon.d.ts +0 -10
  88. package/dist/types/src/theme/components/icon.d.ts.map +0 -1
  89. package/dist/types/src/theme/components/index.d.ts +0 -27
  90. package/dist/types/src/theme/components/index.d.ts.map +0 -1
  91. package/dist/types/src/theme/components/input.d.ts +0 -115
  92. package/dist/types/src/theme/components/input.d.ts.map +0 -1
  93. package/dist/types/src/theme/components/link.d.ts +0 -7
  94. package/dist/types/src/theme/components/link.d.ts.map +0 -1
  95. package/dist/types/src/theme/components/list.d.ts +0 -14
  96. package/dist/types/src/theme/components/list.d.ts.map +0 -1
  97. package/dist/types/src/theme/components/main.d.ts +0 -28
  98. package/dist/types/src/theme/components/main.d.ts.map +0 -1
  99. package/dist/types/src/theme/components/menu.d.ts +0 -13
  100. package/dist/types/src/theme/components/menu.d.ts.map +0 -1
  101. package/dist/types/src/theme/components/message.d.ts +0 -12
  102. package/dist/types/src/theme/components/message.d.ts.map +0 -1
  103. package/dist/types/src/theme/components/popover.d.ts +0 -11
  104. package/dist/types/src/theme/components/popover.d.ts.map +0 -1
  105. package/dist/types/src/theme/components/scroll-area.d.ts +0 -32
  106. package/dist/types/src/theme/components/scroll-area.d.ts.map +0 -1
  107. package/dist/types/src/theme/components/select.d.ts +0 -13
  108. package/dist/types/src/theme/components/select.d.ts.map +0 -1
  109. package/dist/types/src/theme/components/separator.d.ts +0 -8
  110. package/dist/types/src/theme/components/separator.d.ts.map +0 -1
  111. package/dist/types/src/theme/components/skeleton.d.ts +0 -7
  112. package/dist/types/src/theme/components/skeleton.d.ts.map +0 -1
  113. package/dist/types/src/theme/components/splitter.d.ts +0 -4
  114. package/dist/types/src/theme/components/splitter.d.ts.map +0 -1
  115. package/dist/types/src/theme/components/status.d.ts +0 -9
  116. package/dist/types/src/theme/components/status.d.ts.map +0 -1
  117. package/dist/types/src/theme/components/tag.d.ts +0 -7
  118. package/dist/types/src/theme/components/tag.d.ts.map +0 -1
  119. package/dist/types/src/theme/components/toast.d.ts +0 -12
  120. package/dist/types/src/theme/components/toast.d.ts.map +0 -1
  121. package/dist/types/src/theme/components/toolbar.d.ts +0 -11
  122. package/dist/types/src/theme/components/toolbar.d.ts.map +0 -1
  123. package/dist/types/src/theme/components/tooltip.d.ts +0 -8
  124. package/dist/types/src/theme/components/tooltip.d.ts.map +0 -1
  125. package/dist/types/src/theme/components/treegrid.d.ts +0 -10
  126. package/dist/types/src/theme/components/treegrid.d.ts.map +0 -1
  127. package/dist/types/src/theme/index.d.ts +0 -4
  128. package/dist/types/src/theme/index.d.ts.map +0 -1
  129. package/dist/types/src/theme/primitives/column.d.ts +0 -29
  130. package/dist/types/src/theme/primitives/column.d.ts.map +0 -1
  131. package/dist/types/src/theme/primitives/index.d.ts +0 -3
  132. package/dist/types/src/theme/primitives/index.d.ts.map +0 -1
  133. package/dist/types/src/theme/primitives/panel.d.ts +0 -13
  134. package/dist/types/src/theme/primitives/panel.d.ts.map +0 -1
  135. package/dist/types/src/theme/theme.d.ts +0 -5
  136. package/dist/types/src/theme/theme.d.ts.map +0 -1
  137. package/src/css/components/selected.css +0 -30
  138. package/src/theme/components/avatar.ts +0 -95
  139. package/src/theme/components/breadcrumb.ts +0 -29
  140. package/src/theme/components/button.ts +0 -48
  141. package/src/theme/components/card.ts +0 -102
  142. package/src/theme/components/dialog.ts +0 -61
  143. package/src/theme/components/focus.ts +0 -33
  144. package/src/theme/components/icon-button.ts +0 -18
  145. package/src/theme/components/icon.ts +0 -28
  146. package/src/theme/components/index.ts +0 -30
  147. package/src/theme/components/input.ts +0 -171
  148. package/src/theme/components/link.ts +0 -25
  149. package/src/theme/components/list.ts +0 -46
  150. package/src/theme/components/main.ts +0 -34
  151. package/src/theme/components/menu.ts +0 -50
  152. package/src/theme/components/message.ts +0 -40
  153. package/src/theme/components/popover.ts +0 -41
  154. package/src/theme/components/scroll-area.ts +0 -115
  155. package/src/theme/components/select.ts +0 -52
  156. package/src/theme/components/separator.ts +0 -24
  157. package/src/theme/components/skeleton.ts +0 -23
  158. package/src/theme/components/splitter.ts +0 -20
  159. package/src/theme/components/status.ts +0 -32
  160. package/src/theme/components/tag.ts +0 -23
  161. package/src/theme/components/toast.ts +0 -53
  162. package/src/theme/components/toolbar.ts +0 -35
  163. package/src/theme/components/tooltip.ts +0 -27
  164. package/src/theme/components/treegrid.ts +0 -37
  165. package/src/theme/index.ts +0 -7
  166. package/src/theme/primitives/column.ts +0 -71
  167. package/src/theme/primitives/index.ts +0 -6
  168. package/src/theme/primitives/panel.ts +0 -43
  169. package/src/theme/theme.ts +0 -87
@@ -11,8 +11,9 @@
11
11
 
12
12
  .dx-tag--anchor {
13
13
  /* NOTE: Margin offsets padding so that border is flush with text. This should only apply to anchor tags inside of Codemirror. */
14
- @apply inline cursor-pointer -mx-[4px] px-[3px] py-0.5 border border-separator rounded-xs bg-group-surface transition-colors;
15
-
14
+ @apply inline cursor-pointer px-[4px] py-0.5;
15
+ /** TODO(burdon): Configure secondary color. */
16
+ @apply bg-input-surface ring ring-neutral-border rounded-sm;
16
17
  &:hover {
17
18
  @apply bg-hover-surface;
18
19
  }
@@ -20,111 +21,111 @@
20
21
 
21
22
  .dx-tag[data-hue='neutral'],
22
23
  .dx-tag--neutral {
23
- @apply bg-neutral-surface text-neutral-surface-text;
24
+ @apply bg-neutral-surface text-neutral-fg;
24
25
  }
25
26
 
26
27
  .dx-tag[data-hue='red'],
27
28
  .dx-tag--red {
28
- @apply bg-red-surface text-red-surface-text;
29
+ @apply bg-red-surface text-red-fg;
29
30
  }
30
31
 
31
32
  .dx-tag[data-hue='orange'],
32
33
  .dx-tag--orange {
33
- @apply bg-orange-surface text-orange-surface-text;
34
+ @apply bg-orange-surface text-orange-fg;
34
35
  }
35
36
 
36
37
  .dx-tag[data-hue='amber'],
37
38
  .dx-tag--amber {
38
- @apply bg-amber-surface text-amber-surface-text;
39
+ @apply bg-amber-surface text-amber-fg;
39
40
  }
40
41
 
41
42
  .dx-tag[data-hue='yellow'],
42
43
  .dx-tag--yellow {
43
- @apply bg-yellow-surface text-yellow-surface-text;
44
+ @apply bg-yellow-surface text-yellow-fg;
44
45
  }
45
46
 
46
47
  .dx-tag[data-hue='lime'],
47
48
  .dx-tag--lime {
48
- @apply bg-lime-surface text-lime-surface-text;
49
+ @apply bg-lime-surface text-lime-fg;
49
50
  }
50
51
 
51
52
  .dx-tag[data-hue='green'],
52
53
  .dx-tag--green {
53
- @apply bg-green-surface text-green-surface-text;
54
+ @apply bg-green-surface text-green-fg;
54
55
  }
55
56
 
56
57
  .dx-tag[data-hue='emerald'],
57
58
  .dx-tag--emerald {
58
- @apply bg-emerald-surface text-emerald-surface-text;
59
+ @apply bg-emerald-surface text-emerald-fg;
59
60
  }
60
61
 
61
62
  .dx-tag[data-hue='teal'],
62
63
  .dx-tag--teal {
63
- @apply bg-teal-surface text-teal-surface-text;
64
+ @apply bg-teal-surface text-teal-fg;
64
65
  }
65
66
 
66
67
  .dx-tag[data-hue='cyan'],
67
68
  .dx-tag--cyan {
68
- @apply bg-cyan-surface text-cyan-surface-text;
69
+ @apply bg-cyan-surface text-cyan-fg;
69
70
  }
70
71
 
71
72
  .dx-tag[data-hue='sky'],
72
73
  .dx-tag--sky {
73
- @apply bg-sky-surface text-sky-surface-text;
74
+ @apply bg-sky-surface text-sky-fg;
74
75
  }
75
76
 
76
77
  .dx-tag[data-hue='blue'],
77
78
  .dx-tag--blue {
78
- @apply bg-blue-surface text-blue-surface-text;
79
+ @apply bg-blue-surface text-blue-fg;
79
80
  }
80
81
 
81
82
  .dx-tag[data-hue='indigo'],
82
83
  .dx-tag--indigo {
83
- @apply bg-indigo-surface text-indigo-surface-text;
84
+ @apply bg-indigo-surface text-indigo-fg;
84
85
  }
85
86
 
86
87
  .dx-tag[data-hue='violet'],
87
88
  .dx-tag--violet {
88
- @apply bg-violet-surface text-violet-surface-text;
89
+ @apply bg-violet-surface text-violet-fg;
89
90
  }
90
91
 
91
92
  .dx-tag[data-hue='purple'],
92
93
  .dx-tag--purple {
93
- @apply bg-purple-surface text-purple-surface-text;
94
+ @apply bg-purple-surface text-purple-fg;
94
95
  }
95
96
 
96
97
  .dx-tag[data-hue='fuchsia'],
97
98
  .dx-tag--fuchsia {
98
- @apply bg-fuchsia-surface text-fuchsia-surface-text;
99
+ @apply bg-fuchsia-surface text-fuchsia-fg;
99
100
  }
100
101
 
101
102
  .dx-tag[data-hue='pink'],
102
103
  .dx-tag--pink {
103
- @apply bg-pink-surface text-pink-surface-text;
104
+ @apply bg-pink-surface text-pink-fg;
104
105
  }
105
106
 
106
107
  .dx-tag[data-hue='rose'],
107
108
  .dx-tag--rose {
108
- @apply bg-rose-surface text-rose-surface-text;
109
+ @apply bg-rose-surface text-rose-fg;
109
110
  }
110
111
 
111
112
  .dx-tag[data-hue='info'],
112
113
  .dx-tag--info {
113
- @apply bg-cyan-surface text-cyan-surface-text;
114
+ @apply bg-cyan-surface text-cyan-fg;
114
115
  }
115
116
 
116
117
  .dx-tag[data-hue='success'],
117
118
  .dx-tag--success {
118
- @apply bg-emerald-surface text-emerald-surface-text;
119
+ @apply bg-emerald-surface text-emerald-fg;
119
120
  }
120
121
 
121
122
  .dx-tag[data-hue='warning'],
122
123
  .dx-tag--warning {
123
- @apply bg-amber-surface text-amber-surface-text;
124
+ @apply bg-amber-surface text-amber-fg;
124
125
  }
125
126
 
126
127
  .dx-tag[data-hue='error'],
127
128
  .dx-tag--error {
128
- @apply bg-rose-surface text-rose-surface-text;
129
+ @apply bg-rose-surface text-rose-fg;
129
130
  }
130
131
  }
@@ -19,11 +19,12 @@
19
19
  oklch(from var(--color-blue-400) l c h / 0.5),
20
20
  oklch(from var(--color-blue-600) l c h / 0.5)
21
21
  );
22
- --color-cm-focused-selection: light-dark(var(--color-blue-400), var(--color-blue-600));
22
+ --color-cm-focused-selection: light-dark(var(--color-blue-400), oklch(0.445 0.057 256)); /* #3f5573 */
23
23
  --color-cm-highlight: light-dark(var(--color-neutral-950), var(--color-neutral-50));
24
24
  --color-cm-highlight-surface: light-dark(var(--color-sky-200), var(--color-cyan-800));
25
- --color-cm-comment-text: light-dark(var(--color-neutral-50), var(--color-neutral-950));
26
- --color-cm-comment-surface: light-dark(var(--color-amber-800), var(--color-amber-200));
25
+ --color-cm-comment-text: light-dark(var(--color-neutral-950), var(--color-neutral-950));
26
+ --color-cm-comment-surface: light-dark(var(--color-teal-200), var(--color-teal-200));
27
+ --color-cm-comment-current-surface: light-dark(var(--color-orange-200), var(--color-orange-200));
27
28
 
28
29
  /* Markdown syntax highlighting */
29
30
  --color-cm-code: light-dark(var(--color-stone-600), var(--color-stone-400));
@@ -8,7 +8,7 @@
8
8
  }
9
9
  .tl-container.tl-theme__light,
10
10
  .tl-container.tl-theme__dark {
11
- --color-selected: var(--color-accent-surface);
11
+ --color-selected: var(--color-accent-bg);
12
12
  --color-panel: var(--color-modal-surface);
13
13
  --color-panel-contrast: var(--color-separator);
14
14
  }
@@ -81,8 +81,14 @@
81
81
  @apply backdrop-blur-lg;
82
82
  }
83
83
  background-color: var(--color-sidebar-surface);
84
+ color: var(--color-sidebar-fg);
84
85
  --surface-bg: var(--color-sidebar-surface);
85
86
 
87
+ /* Current / selected items read one stop brighter than default body text. */
88
+ & :is([aria-current]:not([aria-current='false']), [aria-selected='true']) {
89
+ color: var(--color-sidebar-current-fg);
90
+ }
91
+
86
92
  transition-property: inset-inline-start, inset-inline-end, inline-size;
87
93
  inset-block-start: max(0.5rem, env(safe-area-inset-top));
88
94
  inset-block-end: max(0.5rem, env(safe-area-inset-bottom));
@@ -3,15 +3,28 @@
3
3
  */
4
4
 
5
5
  @layer dx-components {
6
- /**
7
- * Registers the element as a size query container.
6
+ /**
7
+ * Registers the element as a size query container.
8
8
  * Children can use @container queries to apply styles based on the container's dimensions (both width and height).
9
- * Also enables children to use cqi units (e.g., max-w-[100cqi])
9
+ * Also enables children to use cqi/cqb units (e.g., max-w-[100cqi]).
10
+ * NOTE: `container-type: size` implies layout/size containment, which breaks CodeMirror's
11
+ * coordinate measurement (causes blank viewport sections during scroll until a click forces
12
+ * a re-measure). For editor content where only inline (width-based) queries are needed,
13
+ * use `.dx-inline-size-container` instead.
10
14
  */
11
15
  .dx-size-container {
12
16
  container-type: size;
13
17
  }
14
18
 
19
+ /**
20
+ * Inline-only size query container. Provides cqi units for children without the layout
21
+ * containment side-effects of `container-type: size`. Use this in CodeMirror content
22
+ * wrappers where size containment would break viewport measurement.
23
+ */
24
+ .dx-inline-size-container {
25
+ container-type: inline-size;
26
+ }
27
+
15
28
  /**
16
29
  * Document width.
17
30
  */
@@ -51,7 +64,7 @@
51
64
  }
52
65
 
53
66
  .dx-card-popover {
54
- @apply inline-card-max-width bg-card-surface;
67
+ @apply inline-card-max-width bg-popover-surface;
55
68
  max-width: min(var(--radix-popper-available-width), var(--spacing-card-max-width));
56
69
  max-height: min(var(--radix-popper-available-height), var(--spacing-card-max-height));
57
70
  }
@@ -227,3 +227,34 @@
227
227
  }
228
228
  --animate-blink: blink 1s step-start infinite;
229
229
  }
230
+
231
+ /**
232
+ * Shimmer (text)
233
+ * Sweeps a brighter band across text via mask alpha — preserves the consumer's color.
234
+ * Translates exactly one tile period (2× element width) per cycle so the loop seam is invisible.
235
+ */
236
+ @keyframes shimmer-text {
237
+ from {
238
+ mask-position-x: 100%;
239
+ -webkit-mask-position-x: 100%;
240
+ }
241
+ to {
242
+ mask-position-x: -100%;
243
+ -webkit-mask-position-x: -100%;
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Honor user reduced-motion preference for decorative animations.
249
+ * Functional transitions (fade/slide/toast/blink) are intentionally excluded —
250
+ * suppressing them would hide UI state changes.
251
+ */
252
+ @media (prefers-reduced-motion: reduce) {
253
+ .animate-halo-pulse,
254
+ .animate-spin-slow,
255
+ .animate-trail,
256
+ .animate-trail-offset,
257
+ .animate-shimmer {
258
+ animation: none;
259
+ }
260
+ }
@@ -9,13 +9,47 @@
9
9
  */
10
10
 
11
11
  @theme {
12
+ /**
13
+ * Neutral ramp.
14
+ *
15
+ * Warm-tinted gray (not pure neutral): every level shares --dx-neutral-chroma / --dx-neutral-hue,
16
+ * so those two knobs shift the warmth across the whole ramp (and everything derived from it). The
17
+ * light end is re-spread vs Tailwind's defaults — which squeeze 50–300 into ~0.11 L while the dark
18
+ * end spans ~0.23 — so light steps (~0.025 L) roughly match dark steps (~0.030 L).
19
+ *
20
+ * Two kinds of level, listed below in ascending (darkening) order:
21
+ * - Anchors — the Tailwind hundreds (50…950), defined by explicit lightness.
22
+ * - In-between steps — `color-mix` interpolations of the surrounding anchors.
23
+ */
24
+ --dx-neutral-hue: 190;
25
+ --dx-neutral-chroma: 0.001;
26
+
27
+ --color-neutral-50: oklch(0.985 var(--dx-neutral-chroma) var(--dx-neutral-hue));
12
28
  --color-neutral-75: color-mix(in oklch, var(--color-neutral-50) 50%, var(--color-neutral-100) 50%);
29
+ --color-neutral-100: oklch(0.935 var(--dx-neutral-chroma) var(--dx-neutral-hue));
30
+ --color-neutral-125: color-mix(in oklch, var(--color-neutral-100) 75%, var(--color-neutral-200) 25%);
13
31
  --color-neutral-150: color-mix(in oklch, var(--color-neutral-100) 50%, var(--color-neutral-200) 50%);
32
+ --color-neutral-175: color-mix(in oklch, var(--color-neutral-150) 50%, var(--color-neutral-200) 50%);
33
+ --color-neutral-200: oklch(0.875 var(--dx-neutral-chroma) var(--dx-neutral-hue));
14
34
  --color-neutral-250: color-mix(in oklch, var(--color-neutral-200) 50%, var(--color-neutral-300) 50%);
35
+ --color-neutral-300: oklch(0.8 var(--dx-neutral-chroma) var(--dx-neutral-hue));
36
+ --color-neutral-400: oklch(0.708 var(--dx-neutral-chroma) var(--dx-neutral-hue));
37
+ --color-neutral-500: oklch(0.556 var(--dx-neutral-chroma) var(--dx-neutral-hue));
38
+ --color-neutral-600: oklch(0.439 var(--dx-neutral-chroma) var(--dx-neutral-hue));
39
+ --color-neutral-700: oklch(0.371 var(--dx-neutral-chroma) var(--dx-neutral-hue));
15
40
  --color-neutral-750: color-mix(in oklch, var(--color-neutral-700) 50%, var(--color-neutral-800) 50%);
41
+ --color-neutral-775: color-mix(in oklch, var(--color-neutral-750) 50%, var(--color-neutral-800) 50%);
42
+ --color-neutral-800: oklch(0.269 var(--dx-neutral-chroma) var(--dx-neutral-hue));
43
+ --color-neutral-825: color-mix(in oklch, var(--color-neutral-800) 75%, var(--color-neutral-900) 25%);
16
44
  --color-neutral-850: color-mix(in oklch, var(--color-neutral-800) 50%, var(--color-neutral-900) 50%);
45
+ --color-neutral-875: color-mix(in oklch, var(--color-neutral-800) 25%, var(--color-neutral-900) 75%);
46
+ --color-neutral-900: oklch(0.205 var(--dx-neutral-chroma) var(--dx-neutral-hue));
17
47
  --color-neutral-925: color-mix(in oklch, var(--color-neutral-900) 50%, var(--color-neutral-950) 50%);
48
+ --color-neutral-950: oklch(0.145 var(--dx-neutral-chroma) var(--dx-neutral-hue));
18
49
 
50
+ /*
51
+ * Primary
52
+ */
19
53
  --color-primary-50: var(--color-blue-50);
20
54
  --color-primary-100: var(--color-blue-100);
21
55
  --color-primary-200: var(--color-blue-200);
@@ -1,116 +1,238 @@
1
1
  /**
2
2
  * Tokens
3
+ *
4
+ * Naming convention: --color-{name}-{part}[-{state}]
5
+ * part : surface | fg | border | bg | text
6
+ * state : hover | active (optional)
7
+ *
8
+ * See DESIGN_SYSTEM.md.
3
9
  */
4
10
 
5
11
  @theme {
6
- /**
7
- * Surfaces
12
+ /*
13
+ * Elevation ladder — strictly monotonic, z-order low → high.
14
+ * Dark: darker = lower. Light: lighter = higher (inverted toward white).
15
+ *
16
+ * Level Name Roles
17
+ * 0 void deck, scrim base
18
+ * 1 base base content, L0 icon rail
19
+ * 2 chrome L1/R sidebars, header
20
+ * 3 card card
21
+ * 4 raised group, input, focus/attention
22
+ * 5 bar dialog/modal, toolbar (sticky, drop-shadowed)
23
+ * 6 modal popover, menu, toast, tooltip
24
+ * 7 float
8
25
  *
9
- * TODO(burdon): Align suffix with styles.css?
10
- * -xxx-surface
11
- * -xxx-surface-text
26
+ * These are private (--dx-*) knobs use named surface tokens in components, not these directly.
27
+ */
28
+ --dx-elevation-0: light-dark(var(--color-neutral-300), var(--color-neutral-950));
29
+ --dx-elevation-1: light-dark(var(--color-neutral-200), var(--color-neutral-900));
30
+ --dx-elevation-2: light-dark(var(--color-neutral-125), var(--color-neutral-875));
31
+ --dx-elevation-3: light-dark(var(--color-neutral-125), var(--color-neutral-850));
32
+ --dx-elevation-4: light-dark(var(--color-neutral-100), var(--color-neutral-825));
33
+ --dx-elevation-5: light-dark(var(--color-neutral-75), var(--color-neutral-800));
34
+ --dx-elevation-6: light-dark(var(--color-neutral-50), var(--color-neutral-775));
35
+ --dx-elevation-7: light-dark(white, var(--color-neutral-750));
36
+
37
+ /**
38
+ * Elevation 0
12
39
  */
13
40
 
14
- --color-base-surface: light-dark(var(--color-neutral-50), var(--color-neutral-950));
15
- --color-base-surface-text: light-dark(var(--color-neutral-950), var(--color-neutral-50));
16
-
17
- --color-inverse-surface: light-dark(var(--color-neutral-800), var(--color-neutral-200));
18
- --color-inverse-surface-text: light-dark(var(--color-neutral-50), var(--color-neutral-950));
41
+ --color-deck-surface: var(--dx-elevation-0);
19
42
 
20
- --color-deck-surface: light-dark(var(--color-neutral-50), var(--color-neutral-950));
43
+ /* Translucent dimming layer; tracks the lowest elevation (void) rather than a raw neutral. */
21
44
  --color-scrim-surface: light-dark(
22
- oklch(from var(--color-neutral-50) l c h / 0.5),
23
- oklch(from var(--color-neutral-950) l c h / 0.25)
45
+ oklch(from var(--dx-elevation-0) l c h / 0.5),
46
+ oklch(from var(--dx-elevation-0) l c h / 0.25)
24
47
  );
25
48
 
26
- --color-toolbar-surface: light-dark(var(--color-neutral-75), var(--color-neutral-925));
27
- --color-card-surface: light-dark(var(--color-neutral-75), var(--color-neutral-925));
49
+ /**
50
+ * Elevation 1
51
+ */
28
52
 
29
- --color-group-surface: light-dark(var(--color-neutral-100), var(--color-neutral-900));
30
- --color-modal-surface: light-dark(var(--color-neutral-100), var(--color-neutral-900));
31
- --color-sidebar-surface: light-dark(var(--color-neutral-100), var(--color-neutral-900));
32
- --color-header-surface: light-dark(var(--color-neutral-100), var(--color-neutral-900));
53
+ --color-base-surface: var(--dx-elevation-1);
54
+ --color-base-fg: light-dark(var(--color-neutral-950), var(--color-neutral-150));
33
55
 
34
- --color-input-surface: light-dark(var(--color-neutral-200), var(--color-neutral-800));
35
- --color-input-surface-text: light-dark(var(--color-neutral-950), var(--color-neutral-50));
56
+ /**
57
+ * Elevation 2
58
+ */
36
59
 
37
- /** TODO(burdon): current vs active vs selected */
38
- --color-current-surface: light-dark(var(--color-neutral-200), var(--color-neutral-800));
39
- --color-active-surface: light-dark(var(--color-neutral-200), var(--color-neutral-800));
40
- --color-active-text: light-dark(var(--color-neutral-950), var(--color-neutral-50));
60
+ --color-header-surface: var(--dx-elevation-2);
41
61
 
42
- /** TODO(burdon): Merge overlay/surface? */
43
- --color-hover-overlay: light-dark(var(--color-neutral-250), var(--color-neutral-750));
44
- --color-hover-surface: light-dark(var(--color-neutral-250), var(--color-neutral-750));
45
- --color-hover-surface-text: light-dark(var(--color-neutral-950), var(--color-neutral-50));
62
+ --color-sidebar-surface: var(--dx-elevation-2);
63
+ /* Sidebar body text. Default sits one ramp stop below the current/selected emphasis. */
64
+ --color-sidebar-fg: light-dark(var(--color-neutral-700), var(--color-neutral-250));
65
+ --color-sidebar-current-fg: light-dark(var(--color-neutral-950), var(--color-neutral-75));
66
+
67
+ /* Sidebar / panel layout levels */
68
+ --color-l0-surface: var(--dx-elevation-1);
69
+ --color-l1-surface: var(--dx-elevation-2);
70
+ --color-r0-surface: var(--dx-elevation-2);
71
+ --color-r1-surface: var(--dx-elevation-2);
72
+
73
+ /**
74
+ * Elevation 3
75
+ */
76
+
77
+ --color-card-surface: var(--dx-elevation-3);
46
78
 
47
79
  /* Map attention to focus-surface logic so that elements acting as active attention zones highlight correctly on focus. */
48
- --color-attention-surface: var(--color-focus-surface);
49
- --color-attention-contains: oklch(from var(--color-accent-surface) l c h / 0.3);
50
- --color-focus-surface: light-dark(var(--color-neutral-50), var(--color-neutral-950));
51
- --color-neutral-focus-indicator: light-dark(var(--color-neutral-400), var(--color-neutral-600));
80
+ --color-attention-surface: var(--dx-elevation-3);
81
+ --color-attention-contains: oklch(from var(--color-accent-bg) l c h / 0.3);
52
82
 
53
- /* Highlight and Selected */
83
+ /**
84
+ * Elevation 4
85
+ */
54
86
 
55
- --color-highlight-surface: light-dark(var(--color-neutral-100), var(--color-neutral-900));
56
- --color-highlight-surface-hover: light-dark(var(--color-neutral-250), var(--color-neutral-750));
57
- --color-highlight-surface-text: light-dark(var(--color-neutral-950), var(--color-neutral-50));
87
+ /* Focus — a raised content surface (one level above card) so an attended pane reads as lifted. */
88
+ --color-focus-surface: var(--dx-elevation-4);
89
+ --color-focus-ring: light-dark(var(--color-blue-400), var(--color-blue-600));
90
+ --color-focus-ring-subtle: light-dark(var(--color-neutral-300), var(--color-neutral-600));
91
+
92
+ --color-group-surface: var(--dx-elevation-4);
93
+ /* Subtle alternate of group-surface for zebra striping (e.g. calendar months) — offset off
94
+ * elevation-4 via relative oklch so it tracks the ramp: darker in light mode, lighter in dark. */
95
+ --color-group-alt-surface: light-dark(
96
+ oklch(from var(--dx-elevation-4) calc(l - 0.03) c h),
97
+ oklch(from var(--dx-elevation-4) calc(l + 0.03) c h)
98
+ );
58
99
 
59
- --color-selected-surface: light-dark(var(--color-neutral-150), var(--color-neutral-850));
60
- --color-selected-surface-hover: light-dark(var(--color-neutral-250), var(--color-neutral-750));
61
- --color-selected-surface-text: light-dark(var(--color-neutral-950), var(--color-neutral-50));
100
+ --color-input-surface: var(--dx-elevation-4);
62
101
 
63
- /* Accent (primary) */
64
- /* TODO(burdon): Rename primary */
102
+ /**
103
+ * Elevation 5
104
+ */
105
+
106
+ --color-toolbar-surface: var(--dx-elevation-5);
107
+
108
+ --color-modal-surface: var(--dx-elevation-5);
109
+
110
+ /**
111
+ * Elevation 6
112
+ */
113
+
114
+ --color-popover-surface: var(--dx-elevation-6);
115
+
116
+ /**
117
+ * Elevation 7
118
+ */
119
+
120
+ /**
121
+ * Misc
122
+ */
123
+
124
+ --color-inverse-surface: light-dark(var(--color-neutral-800), var(--color-neutral-200));
125
+ --color-inverse-fg: light-dark(var(--color-neutral-50), var(--color-neutral-950));
126
+
127
+ /*
128
+ * Text emphasis — foregrounds at decreasing emphasis, anchored on --color-base-fg (strongest):
129
+ * base-fg → description → subdued → placeholder (weakest).
130
+ * Tuned for legibility against the surfaces rather than mapped to the elevation ladder (which
131
+ * governs backgrounds, not text contrast), so these stay explicit neutrals.
132
+ */
133
+ --color-description: light-dark(var(--color-neutral-600), var(--color-neutral-400));
134
+ --color-subdued: light-dark(var(--color-neutral-500), var(--color-neutral-600));
135
+ --color-placeholder: light-dark(var(--color-neutral-400), var(--color-neutral-600));
136
+
137
+ /*
138
+ * Controls — the input/control fill is a deliberate off-ladder token (cf. the grid "paper"
139
+ * surfaces). It backs text inputs and the default/ghost button (bg-input-bg) and must contrast
140
+ * whatever surface it sits on: a subtle inset well in light mode, a raised fill in dark mode that
141
+ * reads lighter than the topmost surface. Do not map it to an elevation level.
142
+ */
143
+ --color-input-bg: light-dark(var(--color-neutral-250), var(--color-neutral-700));
144
+ --color-input-fg: var(--color-base-fg);
145
+
146
+ /*
147
+ * State surfaces (hover, current, selected) are derived from the host surface (--surface-bg) via
148
+ * relative oklch — darker in light mode, lighter in dark — so a highlight stays visible at any
149
+ * elevation. The values here resolve against the root --surface-bg (= base-surface, set in
150
+ * base.css), giving the correct default for content outside any surface zone. Surface zones
151
+ * publish their own --surface-bg and re-derive these tokens in surface.css, which is where the
152
+ * substitution re-runs for that subtree.
153
+ *
154
+ * Offset magnitudes (lightness): hover ∓0.08, subtle ∓0.02, current ∓0.10, current-hover ∓0.12.
155
+ * Keep these in sync with the per-zone re-derivation in components/surface.css.
156
+ */
157
+ --color-hover-surface: light-dark(
158
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l - 0.08) c h),
159
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l + 0.08) c h)
160
+ );
161
+ --color-hover-fg: light-dark(var(--color-neutral-950), var(--color-neutral-150));
162
+
163
+ /*
164
+ * Subtle region hover for large highlight targets (list rows, tiles) where the full
165
+ * control-strength hover reads as too heavy. Consumed by `.dx-hover` / `.dx-hover-row`;
166
+ * controls (buttons) keep --color-hover-surface.
167
+ */
168
+ --color-hover-surface-subtle: light-dark(
169
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l - 0.02) c h),
170
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l + 0.02) c h)
171
+ );
172
+
173
+ /* current (aria-current) */
174
+ --color-current-surface: light-dark(
175
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l - 0.1) c h),
176
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l + 0.1) c h)
177
+ );
178
+ --color-current-surface-hover: light-dark(
179
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l - 0.12) c h),
180
+ oklch(from var(--surface-bg, var(--color-base-surface)) calc(l + 0.12) c h)
181
+ );
182
+ --color-current-fg: light-dark(var(--color-neutral-950), var(--color-neutral-50));
183
+
184
+ /* selected (aria-selected) tracks current */
185
+ --color-selected-surface: var(--color-current-surface);
186
+ --color-selected-surface-hover: var(--color-current-surface-hover);
187
+ --color-selected-fg: var(--color-current-fg);
65
188
 
66
- --color-accent-surface: light-dark(var(--color-blue-500), var(--color-blue-700));
67
- --color-accent-surface-hover: light-dark(var(--color-blue-800), var(--color-blue-800));
68
- --color-accent-surface-text: var(--color-blue-100);
189
+ /* Accent (primary) */
190
+ --color-accent-bg: light-dark(var(--color-blue-600), var(--color-blue-700));
191
+ --color-accent-bg-hover: light-dark(var(--color-blue-700), var(--color-blue-800));
192
+ --color-accent-fg: var(--color-blue-100);
69
193
  --color-accent-text: light-dark(var(--color-blue-600), var(--color-blue-400));
70
194
  --color-accent-text-hover: light-dark(var(--color-blue-500), var(--color-blue-500));
71
- --color-accent-focus-indicator: light-dark(var(--color-blue-600), var(--color-blue-600));
72
195
 
196
+ /* Unaccented */
73
197
  --color-un-accent: var(--color-neutral-400);
74
198
  --color-un-accent-hover: var(--color-neutral-500);
75
199
 
76
200
  /* Separator */
77
-
78
- --color-separator: light-dark(var(--color-neutral-200), var(--color-neutral-800));
79
- --color-subdued-separator: light-dark(var(--color-neutral-150), var(--color-neutral-850));
80
- --color-primary-separator: light-dark(var(--color-neutral-500), var(--color-neutral-700));
201
+ --color-primary-separator: light-dark(var(--color-neutral-300), var(--color-neutral-700));
202
+ --color-separator: light-dark(var(--color-neutral-200), var(--color-neutral-700));
203
+ --color-subdued-separator: light-dark(var(--color-neutral-250), var(--color-neutral-750));
81
204
  --color-active-separator: light-dark(var(--color-blue-500), var(--color-blue-500));
82
205
 
83
206
  /* Scrollbar */
84
-
85
207
  --color-scrollbar-track: light-dark(var(--color-neutral-50), var(--color-neutral-950));
86
- --color-scrollbar-thumb: light-dark(var(--color-neutral-200), var(--color-neutral-700));
208
+ --color-scrollbar-thumb: light-dark(var(--color-neutral-200), var(--color-neutral-600));
87
209
  --color-scrollbar-thumb-active: light-dark(var(--color-neutral-200), var(--color-neutral-600));
88
210
  --color-scrollbar-thumb-hover: light-dark(var(--color-neutral-200), var(--color-neutral-600));
89
211
 
90
- /* Sheet */
91
-
212
+ /*
213
+ * Sheet / Grid — intentionally OFF the elevation ladder.
214
+ * NOTE: Update main.css when changing grid tokens (and restart dev server).
215
+ *
216
+ * These are "paper" surfaces for the data grid: maximum-contrast canvases (near-white in light,
217
+ * near-black in dark) plus saturated selection/comment accents. The elevation ladder is
218
+ * monotonic (light: lighter = higher), so it cannot express a surface that is simultaneously the
219
+ * lightest in light mode and the darkest in dark mode. Keep these as explicit neutrals/accents;
220
+ * do not fold them into --dx-elevation-*.
221
+ */
222
+ --color-axis-surface: light-dark(var(--color-neutral-100), var(--color-neutral-900));
223
+ --color-axis-text: light-dark(var(--color-neutral-700), var(--color-neutral-300));
92
224
  --color-axis-selected-surface: light-dark(var(--color-neutral-100), var(--color-neutral-900));
93
225
  --color-axis-selected-text: light-dark(var(--color-neutral-100), var(--color-neutral-900));
94
- --color-axis-surface: light-dark(var(--color-neutral-50), var(--color-neutral-800));
95
- --color-axis-text: light-dark(var(--color-neutral-800), var(--color-neutral-200));
96
-
97
- /* Grid */
98
226
 
99
227
  --color-grid-surface: light-dark(var(--color-neutral-50), var(--color-neutral-950));
228
+ --color-grid-fg: light-dark(var(--color-neutral-950), var(--color-neutral-50));
229
+ --color-grid-line: light-dark(var(--color-neutral-200), var(--color-neutral-800));
100
230
  --color-grid-highlight: oklch(from var(--color-emerald-500) l c h / 0.5);
231
+ --color-grid-selection-surface: light-dark(var(--color-blue-500), var(--color-blue-400));
232
+ --color-grid-selection-fg: light-dark(var(--color-neutral-50), var(--color-neutral-950));
101
233
  --color-grid-comment: light-dark(var(--color-green-400), var(--color-green-600));
102
234
  --color-grid-comment-active: light-dark(
103
235
  oklch(from var(--color-green-400) l c h / 0.5),
104
236
  oklch(from var(--color-green-600) l c h / 0.5)
105
237
  );
106
- --color-grid-hover-overlay: oklch(from var(--color-neutral-500) l c h / 0.1);
107
- --color-grid-selection-overlay: var(--color-blue-500);
108
- --color-grid-line: light-dark(var(--color-neutral-200), var(--color-neutral-800));
109
- --color-grid-focus-indicator: light-dark(var(--color-primary-600), var(--color-primary-600));
110
-
111
- /* Text */
112
-
113
- --color-placeholder: light-dark(var(--color-neutral-400), var(--color-neutral-600));
114
- --color-subdued: light-dark(var(--color-neutral-500), var(--color-neutral-500));
115
- --color-description: light-dark(var(--color-neutral-600), var(--color-neutral-400));
116
238
  }