@titan-design/react-ui 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/bodymap.js +129 -76
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +129 -76
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +117 -26
- package/dist/index.d.ts +117 -26
- package/dist/index.js +677 -450
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +673 -451
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-_3Ajpiqu.d.ts → pages-CsjsUn0G.d.ts} +30 -13
- package/dist/{pages-CpW3OB3g.d.mts → pages-ZbT_pD_U.d.mts} +30 -13
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +676 -701
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +676 -701
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +31 -7
- package/dist/theme/index.d.ts +31 -7
- package/dist/theme/index.js +84 -20
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +83 -21
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +84 -20
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +84 -20
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/dist/theme/tokens.d.mts +56 -7
- package/dist/theme/tokens.d.ts +56 -7
- package/dist/theme/tokens.js +72 -20
- package/dist/theme/tokens.js.map +1 -1
- package/dist/theme/tokens.mjs +71 -21
- package/dist/theme/tokens.mjs.map +1 -1
- package/docs/render-testing-pattern.md +130 -0
- package/package.json +1 -1
- package/src/arch/Architecture.stories.tsx +3 -1
- package/src/arch/arch-graph.json +74 -72
- package/src/components/custom/ActiveWork/InitiativeBrief.tsx +2 -1
- package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +8 -3
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.stories.tsx +4 -1
- package/src/components/custom/Gauge/Gauge.tsx +3 -1
- package/src/components/custom/Scatter/Scatter.stories.tsx +10 -7
- package/src/components/custom/Scatter/Scatter.tsx +6 -4
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
- package/src/components/custom/Table/Table.stories.tsx +1 -1
- package/src/components/custom/Table/Table.tsx +2 -2
- package/src/components/custom/Treemap/Treemap.stories.tsx +13 -10
- package/src/components/custom/Treemap/Treemap.tsx +4 -1
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +2 -1
- package/src/components/custom/Workout/BaseBadge.stories.tsx +11 -7
- package/src/components/custom/Workout/BaseBadge.tsx +3 -2
- package/src/components/custom/Workout/BodyMap.tsx +5 -3
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +13 -3
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +5 -3
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +2 -1
- package/src/components/custom/Workout/CapacityBandChart.tsx +5 -3
- package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
- package/src/components/custom/Workout/DeviationBar.tsx +5 -2
- package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +7 -6
- package/src/components/custom/Workout/DualVelocityStrip.test.tsx +29 -16
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -8
- package/src/components/custom/Workout/ExerciseCard.test.tsx +39 -19
- package/src/components/custom/Workout/ExerciseCard.tsx +92 -167
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +89 -6
- package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +189 -1
- package/src/components/custom/Workout/ExerciseCardHeading.tsx +167 -18
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +3 -2
- package/src/components/custom/Workout/ExerciseHeading.tsx +192 -47
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -5
- package/src/components/custom/Workout/InputBar.tsx +4 -2
- package/src/components/custom/Workout/IntensityBar.tsx +4 -1
- package/src/components/custom/Workout/MesoCard.tsx +2 -1
- package/src/components/custom/Workout/MesoStatusCard.tsx +11 -10
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +8 -3
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +12 -2
- package/src/components/custom/Workout/README.md +58 -12
- package/src/components/custom/Workout/ReadinessCheck.tsx +4 -2
- package/src/components/custom/Workout/RestTimer.stories.tsx +13 -2
- package/src/components/custom/Workout/RestTimer.tsx +4 -2
- package/src/components/custom/Workout/SegmentedBar.stories.tsx +16 -12
- package/src/components/custom/Workout/SegmentedBar.tsx +4 -3
- package/src/components/custom/Workout/SetStrip.stories.tsx +3 -2
- package/src/components/custom/Workout/SetsRepsLoad.tsx +23 -9
- package/src/components/custom/Workout/Sparkline.stories.tsx +13 -10
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +2 -1
- package/src/components/custom/Workout/StrengthTrendChart.tsx +8 -6
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +4 -3
- package/src/components/custom/Workout/TempoDisplay.tsx +2 -0
- package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +3 -2
- package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +1 -1
- package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +40 -0
- package/src/components/custom/Workout/VelocityStrip.test.tsx +48 -6
- package/src/components/custom/Workout/VelocityStrip.tsx +23 -14
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +3 -1
- package/src/components/custom/Workout/exerciseRowState.ts +29 -0
- package/src/components/custom/Workout/index.ts +12 -2
- package/src/components/custom/Workout/metricText.stories.tsx +9 -8
- package/src/components/custom/Workout/metricText.tsx +4 -2
- package/src/components/custom/Workout/setHeadingKit.tsx +12 -10
- package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
- package/src/components/custom/charts/README.md +5 -0
- package/src/components/custom/charts/SetBarChart.test.tsx +16 -0
- package/src/components/custom/charts/SetBarChart.tsx +14 -5
- package/src/components/custom/charts/flatBarGeometry.test.ts +41 -0
- package/src/components/custom/charts/flatBarGeometry.ts +32 -0
- package/src/components/custom/stepper/Stepper.tsx +8 -6
- package/src/components/ui/alert/Alert.stories.tsx +14 -4
- package/src/components/ui/alert/Alert.tsx +24 -3
- package/src/components/ui/button/Button.tsx +12 -12
- package/src/components/ui/checkbox/Checkbox.tsx +2 -2
- package/src/components/ui/data-row/DataRow.stories.tsx +6 -2
- package/src/components/ui/drawer/Drawer.tsx +4 -1
- package/src/components/ui/icon-box/IconBox.tsx +8 -6
- package/src/components/ui/indicator/Indicator.stories.tsx +4 -3
- package/src/components/ui/list-item/ListItem.stories.tsx +7 -4
- package/src/components/ui/modal/Modal.tsx +2 -0
- package/src/components/ui/pill/Pill.stories.tsx +53 -0
- package/src/components/ui/pill/Pill.tsx +10 -6
- package/src/components/ui/popover/Popover.stories.tsx +1 -1
- package/src/components/ui/progress/Progress.tsx +9 -6
- package/src/components/ui/radio/Radio.tsx +1 -1
- package/src/components/ui/section/Section.stories.tsx +10 -10
- package/src/components/ui/select/Select.tsx +2 -1
- package/src/components/ui/spinner/Spinner.tsx +3 -1
- package/src/components/ui/stack/Stack.stories.tsx +7 -7
- package/src/components/ui/surface/Surface.stories.tsx +75 -28
- package/src/components/ui/switch/Switch.tsx +1 -1
- package/src/components/ui/tabs/Tabs.tsx +4 -2
- package/src/components/ui/toast/Toast.tsx +6 -4
- package/src/components/ui/toolbar-button/ToolbarButton.tsx +13 -6
- package/src/stories/PresetShowcase.stories.tsx +1 -1
- package/src/test/no-raw-color.test.ts +39 -0
- package/src/theme/Alpha.stories.tsx +103 -0
- package/src/theme/ProposedTokensVW82.stories.tsx +414 -0
- package/src/theme/config.ts +12 -0
- package/src/theme/global.css +15 -3
- package/src/theme/subtle-tone-weight.test.ts +163 -0
- package/src/theme/tailwind-var-opacity.test.ts +163 -0
- package/src/theme/tokens/primitives.ts +33 -0
- package/src/theme/tokens/semantic-hex-guard.test.ts +322 -0
- package/src/theme/tokens/semantic.ts +56 -20
- package/src/utils/colors.alpha-adoption.test.ts +408 -0
- package/tailwind.config.js +50 -9
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { semanticColorsLight, semanticColorsDark, getSemanticColors } from './semantic'
|
|
3
|
+
import {
|
|
4
|
+
primitiveColors,
|
|
5
|
+
primitiveRamps,
|
|
6
|
+
greyRamp,
|
|
7
|
+
discreteRainbow,
|
|
8
|
+
alertRedVivid,
|
|
9
|
+
resultPaletteColors,
|
|
10
|
+
semanticPins,
|
|
11
|
+
} from './primitives'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Guard (VW-83): every hex-looking semantic token value must be a `primitiveRamps`
|
|
15
|
+
* step or a named primitive from `./primitives` — never a literal typed straight
|
|
16
|
+
* into `semantic.ts`. Scoped to hex values only: the many `rgba(...)` alpha
|
|
17
|
+
* overlays in this file are hand-composited, pre-existing, and out of scope for
|
|
18
|
+
* this ticket (which is about raw HEX occurrences).
|
|
19
|
+
*
|
|
20
|
+
* Deep-equal against the primitives module (not a regex on shape) so a future
|
|
21
|
+
* hex that happens to be well-formed but unbacked by any primitive still fails.
|
|
22
|
+
*/
|
|
23
|
+
const HEX = /^#[0-9A-Fa-f]{3,8}$/
|
|
24
|
+
|
|
25
|
+
const allowedHexValues = new Set(
|
|
26
|
+
[
|
|
27
|
+
...Object.values(primitiveColors),
|
|
28
|
+
...Object.values(greyRamp),
|
|
29
|
+
...Object.values(primitiveRamps).flatMap((hue) => Object.values(hue)),
|
|
30
|
+
...discreteRainbow,
|
|
31
|
+
alertRedVivid,
|
|
32
|
+
...Object.values(resultPaletteColors),
|
|
33
|
+
...Object.values(semanticPins),
|
|
34
|
+
]
|
|
35
|
+
.filter((v): v is string => HEX.test(v))
|
|
36
|
+
.map((v) => v.toLowerCase())
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
function hexEntries(colors: Record<string, string>): [string, string][] {
|
|
40
|
+
return Object.entries(colors).filter(([, value]) => HEX.test(value))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe('semantic token hex guard (VW-83)', () => {
|
|
44
|
+
it('has hex tokens to check in both modes (sanity: the guard is not vacuous)', () => {
|
|
45
|
+
expect(hexEntries(semanticColorsLight).length).toBeGreaterThan(0)
|
|
46
|
+
expect(hexEntries(semanticColorsDark).length).toBeGreaterThan(0)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('resolves every light-mode hex token to a ramp step or a named primitive', () => {
|
|
50
|
+
for (const [token, value] of hexEntries(semanticColorsLight)) {
|
|
51
|
+
expect(allowedHexValues.has(value.toLowerCase()), `light '${token}': ${value}`).toBe(true)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('resolves every dark-mode hex token to a ramp step or a named primitive', () => {
|
|
56
|
+
for (const [token, value] of hexEntries(semanticColorsDark)) {
|
|
57
|
+
expect(allowedHexValues.has(value.toLowerCase()), `dark '${token}': ${value}`).toBe(true)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Resolved values captured from `main` (pre-VW-83), before any semantic.ts
|
|
64
|
+
* literal was replaced by a ramp step or a named primitive. The migration must
|
|
65
|
+
* not change what any token paints — only where its value comes from.
|
|
66
|
+
*
|
|
67
|
+
* AMENDED by AW-133, which is NOT a refactor and does change what some tokens
|
|
68
|
+
* paint. Splitting text-on-subtle from the base tone token added the six
|
|
69
|
+
* `on-*-subtle` entries, and rebased three dark `-subtle` fills onto the hue
|
|
70
|
+
* their label now uses (`brand-secondary`, `status-error`, `status-info`). Those
|
|
71
|
+
* deltas are deliberate and reviewed; everything else here is still the
|
|
72
|
+
* pre-migration pin. Treat a diff against this fixture as a question to answer,
|
|
73
|
+
* not a number to refresh — regenerating it wholesale defeats the guard.
|
|
74
|
+
*/
|
|
75
|
+
const resolvedBeforeFixture = {
|
|
76
|
+
light: {
|
|
77
|
+
'brand-primary': '#FF7900',
|
|
78
|
+
'brand-primary-light': '#FFA063',
|
|
79
|
+
'brand-primary-dark': '#DA5F00',
|
|
80
|
+
'brand-primary-subtle': 'rgba(255, 121, 0, 0.08)',
|
|
81
|
+
'brand-primary-muted': 'rgba(255, 121, 0, 0.30)',
|
|
82
|
+
'brand-primary-strong': 'rgba(255, 121, 0, 0.50)',
|
|
83
|
+
'brand-primary-hover': '#DA5F00',
|
|
84
|
+
'brand-primary-active': '#B94A00',
|
|
85
|
+
'brand-secondary': '#307B9B',
|
|
86
|
+
'brand-secondary-light': '#2697B7',
|
|
87
|
+
'brand-secondary-dark': '#2A617F',
|
|
88
|
+
'brand-secondary-subtle': 'rgba(48, 123, 155, 0.08)',
|
|
89
|
+
'brand-secondary-muted': 'rgba(48, 123, 155, 0.30)',
|
|
90
|
+
'brand-secondary-strong': 'rgba(48, 123, 155, 0.50)',
|
|
91
|
+
'brand-secondary-hover': '#2A617F',
|
|
92
|
+
'brand-secondary-active': '#22465F',
|
|
93
|
+
'on-brand-primary': '#FFFFFF',
|
|
94
|
+
'on-brand-secondary': '#FFFFFF',
|
|
95
|
+
'on-brand-primary-subtle': '#FF7900',
|
|
96
|
+
'on-brand-secondary-subtle': '#307B9B',
|
|
97
|
+
'status-success': '#2ED573',
|
|
98
|
+
'status-success-light': '#58F69E',
|
|
99
|
+
'status-success-dark': '#298732',
|
|
100
|
+
'status-success-subtle': '#E3FFEE',
|
|
101
|
+
'status-success-muted': 'rgba(46, 213, 115, 0.30)',
|
|
102
|
+
'status-success-strong': 'rgba(46, 213, 115, 0.50)',
|
|
103
|
+
'status-live': '#2ED573',
|
|
104
|
+
'status-live-muted': '#22A444',
|
|
105
|
+
'status-error': '#D14343',
|
|
106
|
+
'status-error-light': '#E05254',
|
|
107
|
+
'status-error-dark': '#A4221C',
|
|
108
|
+
'status-error-subtle': '#FFF4F4',
|
|
109
|
+
'status-error-muted': 'rgba(209, 67, 67, 0.30)',
|
|
110
|
+
'status-error-strong': 'rgba(209, 67, 67, 0.50)',
|
|
111
|
+
'status-error-vivid': '#FF4757',
|
|
112
|
+
'status-error-vivid-light': '#E05254',
|
|
113
|
+
'status-error-vivid-dark': '#A4221C',
|
|
114
|
+
'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',
|
|
115
|
+
'status-error-vivid-muted': 'rgba(255, 71, 87, 0.30)',
|
|
116
|
+
'status-error-vivid-strong': 'rgba(255, 71, 87, 0.50)',
|
|
117
|
+
'status-warning': '#F9B415',
|
|
118
|
+
'status-warning-light': '#FFD352',
|
|
119
|
+
'status-warning-dark': '#C27400',
|
|
120
|
+
'status-warning-subtle': '#FFF7DD',
|
|
121
|
+
'status-warning-muted': 'rgba(249, 180, 21, 0.30)',
|
|
122
|
+
'status-warning-strong': 'rgba(249, 180, 21, 0.50)',
|
|
123
|
+
'status-info': '#2196F3',
|
|
124
|
+
'status-info-light': '#78C2FF',
|
|
125
|
+
'status-info-dark': '#1072CB',
|
|
126
|
+
'status-info-subtle': '#EFF8FF',
|
|
127
|
+
'status-info-muted': 'rgba(33, 150, 243, 0.30)',
|
|
128
|
+
'status-info-strong': 'rgba(33, 150, 243, 0.50)',
|
|
129
|
+
'on-status-success': '#FFFFFF',
|
|
130
|
+
'on-status-error': '#FFFFFF',
|
|
131
|
+
'on-status-warning': '#FFFFFF',
|
|
132
|
+
'on-status-info': '#FFFFFF',
|
|
133
|
+
'on-status-success-subtle': '#2ED573',
|
|
134
|
+
'on-status-error-subtle': '#D14343',
|
|
135
|
+
'on-status-warning-subtle': '#F9B415',
|
|
136
|
+
'on-status-info-subtle': '#2196F3',
|
|
137
|
+
'result-improve': '#4caf50',
|
|
138
|
+
'result-improve-light': 'rgba(76, 175, 80, 0.12)',
|
|
139
|
+
'result-improve-dark': '#248a24',
|
|
140
|
+
'result-degrade': '#ef5350',
|
|
141
|
+
'result-degrade-light': 'rgba(239, 83, 80, 0.12)',
|
|
142
|
+
'result-degrade-dark': '#b30000',
|
|
143
|
+
'result-inconclusive': '#9E9A97',
|
|
144
|
+
'result-inconclusive-light': 'rgba(158, 154, 151, 0.12)',
|
|
145
|
+
'result-neutral': '#72716F',
|
|
146
|
+
'on-result-improve': '#FFFFFF',
|
|
147
|
+
'on-result-degrade': '#FFFFFF',
|
|
148
|
+
'on-result-inconclusive': '#FFFFFF',
|
|
149
|
+
'data-1': '#1965B0',
|
|
150
|
+
'data-2': '#4EB265',
|
|
151
|
+
'data-3': '#F7F056',
|
|
152
|
+
'data-4': '#DC050C',
|
|
153
|
+
'data-5': '#882E72',
|
|
154
|
+
'data-6': '#F4A736',
|
|
155
|
+
'data-7': '#7BAFDE',
|
|
156
|
+
'data-8': '#90C987',
|
|
157
|
+
'data-9': '#CAACCB',
|
|
158
|
+
'data-10': '#EE8026',
|
|
159
|
+
'text-primary': '#121828',
|
|
160
|
+
'text-secondary': '#65748B',
|
|
161
|
+
'text-tertiary': '#A29F9D',
|
|
162
|
+
'text-disabled': 'rgba(55, 65, 81, 0.48)',
|
|
163
|
+
'text-inverse': '#FFFFFF',
|
|
164
|
+
'text-link': '#1072CB',
|
|
165
|
+
'text-link-hover': '#135AA8',
|
|
166
|
+
'surface-base': '#FFFFFF',
|
|
167
|
+
'surface-elevated': '#F9F6F3',
|
|
168
|
+
'surface-raised': '#EDEAE7',
|
|
169
|
+
'surface-overlay': '#FFFFFF',
|
|
170
|
+
'surface-input': '#F9F6F3',
|
|
171
|
+
'background-base': '#EBEBEB',
|
|
172
|
+
'background-default': '#FFFFFF',
|
|
173
|
+
'background-subtle': '#F9F6F3',
|
|
174
|
+
'background-frame': '#A29F9D',
|
|
175
|
+
'border-prominent': '#A29F9D',
|
|
176
|
+
'border-focus': '#1072CB',
|
|
177
|
+
'border-input': '#D4D1CE',
|
|
178
|
+
'border-input-hover': '#A29F9D',
|
|
179
|
+
'border-input-focus': '#1072CB',
|
|
180
|
+
'border-input-error': '#D14343',
|
|
181
|
+
'hairline-subtle': 'rgba(0, 0, 0, 0.06)',
|
|
182
|
+
'hairline-default': 'rgba(0, 0, 0, 0.09)',
|
|
183
|
+
'hairline-strong': 'rgba(0, 0, 0, 0.14)',
|
|
184
|
+
'interactive-hover': 'rgba(55, 65, 81, 0.04)',
|
|
185
|
+
'interactive-focus': 'rgba(55, 65, 81, 0.12)',
|
|
186
|
+
'interactive-active': 'rgba(55, 65, 81, 0.16)',
|
|
187
|
+
'interactive-selected': 'rgba(55, 65, 81, 0.08)',
|
|
188
|
+
'interactive-disabled': 'rgba(55, 65, 81, 0.12)',
|
|
189
|
+
'interactive-disabled-text': 'rgba(55, 65, 81, 0.26)',
|
|
190
|
+
divider: '#E8E9EB',
|
|
191
|
+
'avatar-background': '#72716F',
|
|
192
|
+
'avatar-text': '#FFFFFF',
|
|
193
|
+
},
|
|
194
|
+
dark: {
|
|
195
|
+
'brand-primary': '#FF7900',
|
|
196
|
+
'brand-primary-light': '#FFA063',
|
|
197
|
+
'brand-primary-dark': '#DA5F00',
|
|
198
|
+
'brand-primary-subtle': 'rgba(255, 121, 0, 0.12)',
|
|
199
|
+
'brand-primary-muted': 'rgba(255, 121, 0, 0.30)',
|
|
200
|
+
'brand-primary-strong': 'rgba(255, 121, 0, 0.50)',
|
|
201
|
+
'brand-primary-hover': '#FFA063',
|
|
202
|
+
'brand-primary-active': '#FFC7A2',
|
|
203
|
+
'brand-secondary': '#307B9B',
|
|
204
|
+
'brand-secondary-light': '#2697B7',
|
|
205
|
+
'brand-secondary-dark': '#2A617F',
|
|
206
|
+
'brand-secondary-subtle': 'rgba(34, 211, 238, 0.12)',
|
|
207
|
+
'brand-secondary-muted': 'rgba(48, 123, 155, 0.30)',
|
|
208
|
+
'brand-secondary-strong': 'rgba(48, 123, 155, 0.50)',
|
|
209
|
+
'brand-secondary-hover': '#2697B7',
|
|
210
|
+
'brand-secondary-active': '#01B5D1',
|
|
211
|
+
'on-brand-primary': '#FFFFFF',
|
|
212
|
+
'on-brand-secondary': '#FFFFFF',
|
|
213
|
+
'on-brand-primary-subtle': '#FF7900',
|
|
214
|
+
'on-brand-secondary-subtle': '#22D3EE',
|
|
215
|
+
'status-success': '#2ED573',
|
|
216
|
+
'status-success-light': '#58F69E',
|
|
217
|
+
'status-success-dark': '#298732',
|
|
218
|
+
'status-success-subtle': 'rgba(46, 213, 115, 0.12)',
|
|
219
|
+
'status-success-muted': 'rgba(46, 213, 115, 0.30)',
|
|
220
|
+
'status-success-strong': 'rgba(46, 213, 115, 0.50)',
|
|
221
|
+
'status-live': '#2ED573',
|
|
222
|
+
'status-live-muted': '#22A444',
|
|
223
|
+
'status-error': '#D14343',
|
|
224
|
+
'status-error-light': '#E05254',
|
|
225
|
+
'status-error-dark': '#A4221C',
|
|
226
|
+
'status-error-subtle': 'rgba(247, 113, 117, 0.08)',
|
|
227
|
+
'status-error-muted': 'rgba(209, 67, 67, 0.30)',
|
|
228
|
+
'status-error-strong': 'rgba(209, 67, 67, 0.50)',
|
|
229
|
+
'status-error-vivid': '#FF4757',
|
|
230
|
+
'status-error-vivid-light': '#E05254',
|
|
231
|
+
'status-error-vivid-dark': '#A4221C',
|
|
232
|
+
'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',
|
|
233
|
+
'status-error-vivid-muted': 'rgba(255, 71, 87, 0.30)',
|
|
234
|
+
'status-error-vivid-strong': 'rgba(255, 71, 87, 0.50)',
|
|
235
|
+
'status-warning': '#F9B415',
|
|
236
|
+
'status-warning-light': '#FFD352',
|
|
237
|
+
'status-warning-dark': '#C27400',
|
|
238
|
+
'status-warning-subtle': 'rgba(249, 180, 21, 0.12)',
|
|
239
|
+
'status-warning-muted': 'rgba(249, 180, 21, 0.30)',
|
|
240
|
+
'status-warning-strong': 'rgba(249, 180, 21, 0.50)',
|
|
241
|
+
'status-info': '#2196F3',
|
|
242
|
+
'status-info-light': '#78C2FF',
|
|
243
|
+
'status-info-dark': '#1072CB',
|
|
244
|
+
'status-info-subtle': 'rgba(120, 194, 255, 0.12)',
|
|
245
|
+
'status-info-muted': 'rgba(33, 150, 243, 0.30)',
|
|
246
|
+
'status-info-strong': 'rgba(33, 150, 243, 0.50)',
|
|
247
|
+
'on-status-success': '#FFFFFF',
|
|
248
|
+
'on-status-error': '#FFFFFF',
|
|
249
|
+
'on-status-warning': '#FFFFFF',
|
|
250
|
+
'on-status-info': '#FFFFFF',
|
|
251
|
+
'on-status-success-subtle': '#2ED573',
|
|
252
|
+
'on-status-error-subtle': '#F77175',
|
|
253
|
+
'on-status-warning-subtle': '#F9B415',
|
|
254
|
+
'on-status-info-subtle': '#78C2FF',
|
|
255
|
+
'result-improve': '#4caf50',
|
|
256
|
+
'result-improve-light': 'rgba(76, 175, 80, 0.16)',
|
|
257
|
+
'result-improve-dark': '#248a24',
|
|
258
|
+
'result-degrade': '#ef5350',
|
|
259
|
+
'result-degrade-light': 'rgba(239, 83, 80, 0.16)',
|
|
260
|
+
'result-degrade-dark': '#b30000',
|
|
261
|
+
'result-inconclusive': '#9E9A97',
|
|
262
|
+
'result-inconclusive-light': 'rgba(158, 154, 151, 0.16)',
|
|
263
|
+
'result-neutral': '#A29F9D',
|
|
264
|
+
'on-result-improve': '#FFFFFF',
|
|
265
|
+
'on-result-degrade': '#FFFFFF',
|
|
266
|
+
'on-result-inconclusive': '#FFFFFF',
|
|
267
|
+
'data-1': '#1965B0',
|
|
268
|
+
'data-2': '#4EB265',
|
|
269
|
+
'data-3': '#F7F056',
|
|
270
|
+
'data-4': '#DC050C',
|
|
271
|
+
'data-5': '#882E72',
|
|
272
|
+
'data-6': '#F4A736',
|
|
273
|
+
'data-7': '#7BAFDE',
|
|
274
|
+
'data-8': '#90C987',
|
|
275
|
+
'data-9': '#CAACCB',
|
|
276
|
+
'data-10': '#EE8026',
|
|
277
|
+
'text-primary': '#F9F6F3',
|
|
278
|
+
'text-secondary': '#A29F9D',
|
|
279
|
+
'text-tertiary': '#888684',
|
|
280
|
+
'text-disabled': 'rgba(255, 255, 255, 0.38)',
|
|
281
|
+
'text-inverse': '#1C1916',
|
|
282
|
+
'text-link': '#828DF8',
|
|
283
|
+
'text-link-hover': '#3CA8FF',
|
|
284
|
+
'surface-base': '#252321',
|
|
285
|
+
'surface-elevated': '#2C2A28',
|
|
286
|
+
'surface-raised': '#31302F',
|
|
287
|
+
'surface-overlay': '#373635',
|
|
288
|
+
'surface-input': '#2C2A28',
|
|
289
|
+
'background-base': '#1C1916',
|
|
290
|
+
'background-default': '#252321',
|
|
291
|
+
'background-subtle': '#2C2A28',
|
|
292
|
+
'background-frame': '#100D0A',
|
|
293
|
+
'border-prominent': '#424140',
|
|
294
|
+
'border-focus': '#828DF8',
|
|
295
|
+
'border-input': '#5A5958',
|
|
296
|
+
'border-input-hover': '#72716F',
|
|
297
|
+
'border-input-focus': '#828DF8',
|
|
298
|
+
'border-input-error': '#E05254',
|
|
299
|
+
'hairline-subtle': 'rgba(255, 255, 255, 0.10)',
|
|
300
|
+
'hairline-default': 'rgba(255, 255, 255, 0.15)',
|
|
301
|
+
'hairline-strong': 'rgba(255, 255, 255, 0.22)',
|
|
302
|
+
'interactive-hover': 'rgba(255, 255, 255, 0.04)',
|
|
303
|
+
'interactive-focus': 'rgba(255, 255, 255, 0.12)',
|
|
304
|
+
'interactive-active': 'rgba(255, 255, 255, 0.16)',
|
|
305
|
+
'interactive-selected': 'rgba(255, 255, 255, 0.08)',
|
|
306
|
+
'interactive-disabled': 'rgba(255, 255, 255, 0.12)',
|
|
307
|
+
'interactive-disabled-text': 'rgba(255, 255, 255, 0.26)',
|
|
308
|
+
divider: 'rgba(255, 255, 255, 0.09)',
|
|
309
|
+
'avatar-background': '#5A5958',
|
|
310
|
+
'avatar-text': '#FFFFFF',
|
|
311
|
+
},
|
|
312
|
+
} as const
|
|
313
|
+
|
|
314
|
+
describe('semantic token resolved values are unchanged by the hex migration (VW-83)', () => {
|
|
315
|
+
it('matches the pre-migration fixture in light mode', () => {
|
|
316
|
+
expect(getSemanticColors('light')).toEqual(resolvedBeforeFixture.light)
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
it('matches the pre-migration fixture in dark mode', () => {
|
|
320
|
+
expect(getSemanticColors('dark')).toEqual(resolvedBeforeFixture.dark)
|
|
321
|
+
})
|
|
322
|
+
})
|
|
@@ -23,6 +23,8 @@ import {
|
|
|
23
23
|
greyRamp,
|
|
24
24
|
discreteRainbow,
|
|
25
25
|
alertRedVivid,
|
|
26
|
+
resultPaletteColors,
|
|
27
|
+
semanticPins,
|
|
26
28
|
} from './primitives'
|
|
27
29
|
|
|
28
30
|
/**
|
|
@@ -77,6 +79,13 @@ export const semanticColorsLight = {
|
|
|
77
79
|
'on-brand-primary': p.white,
|
|
78
80
|
'on-brand-secondary': p.white,
|
|
79
81
|
|
|
82
|
+
// Text ON a `-subtle` fill. Light mode keeps today's pairing (the base token) so
|
|
83
|
+
// nothing moves here: light has the same disease mirrored — a light rung on a
|
|
84
|
+
// near-white ramp[50] fill — but correcting it belongs with the light-mode pass
|
|
85
|
+
// in AW-121, not this one.
|
|
86
|
+
'on-brand-primary-subtle': ramp.orange[400],
|
|
87
|
+
'on-brand-secondary-subtle': ramp.cyan[600],
|
|
88
|
+
|
|
80
89
|
// Status colors (status-*)
|
|
81
90
|
'status-success': ramp.green[300],
|
|
82
91
|
'status-success-light': ramp.green[200],
|
|
@@ -117,6 +126,12 @@ export const semanticColorsLight = {
|
|
|
117
126
|
'status-info-muted': 'rgba(33, 150, 243, 0.30)',
|
|
118
127
|
'status-info-strong': 'rgba(33, 150, 243, 0.50)',
|
|
119
128
|
|
|
129
|
+
// Text ON a `-subtle` fill — see the on-brand-*-subtle note above.
|
|
130
|
+
'on-status-success-subtle': ramp.green[300],
|
|
131
|
+
'on-status-error-subtle': ramp.red[600],
|
|
132
|
+
'on-status-warning-subtle': ramp.amber[300],
|
|
133
|
+
'on-status-info-subtle': ramp.blue[500],
|
|
134
|
+
|
|
120
135
|
// Text on status backgrounds (on-status-*)
|
|
121
136
|
'on-status-success': p.white,
|
|
122
137
|
'on-status-error': p.white,
|
|
@@ -124,13 +139,13 @@ export const semanticColorsLight = {
|
|
|
124
139
|
'on-status-info': p.white,
|
|
125
140
|
|
|
126
141
|
// Result/outcome indicators (result-*)
|
|
127
|
-
'result-improve':
|
|
142
|
+
'result-improve': resultPaletteColors.improve, // Green - positive outcome
|
|
128
143
|
'result-improve-light': 'rgba(76, 175, 80, 0.12)',
|
|
129
|
-
'result-improve-dark':
|
|
130
|
-
'result-degrade':
|
|
144
|
+
'result-improve-dark': resultPaletteColors.improveDark,
|
|
145
|
+
'result-degrade': resultPaletteColors.degrade, // Red - negative outcome
|
|
131
146
|
'result-degrade-light': 'rgba(239, 83, 80, 0.12)',
|
|
132
|
-
'result-degrade-dark':
|
|
133
|
-
'result-inconclusive':
|
|
147
|
+
'result-degrade-dark': resultPaletteColors.degradeDark,
|
|
148
|
+
'result-inconclusive': resultPaletteColors.inconclusive, // Gray - no clear result
|
|
134
149
|
'result-inconclusive-light': 'rgba(158, 154, 151, 0.12)',
|
|
135
150
|
'result-neutral': greyRamp[600], // Neutral baseline
|
|
136
151
|
|
|
@@ -153,8 +168,8 @@ export const semanticColorsLight = {
|
|
|
153
168
|
'data-10': discreteRainbow[22], // Dark Orange
|
|
154
169
|
|
|
155
170
|
// Text colors (text-*)
|
|
156
|
-
'text-primary':
|
|
157
|
-
'text-secondary':
|
|
171
|
+
'text-primary': semanticPins.textPrimaryLight,
|
|
172
|
+
'text-secondary': semanticPins.textSecondaryLight,
|
|
158
173
|
'text-tertiary': greyRamp[400],
|
|
159
174
|
'text-disabled': 'rgba(55, 65, 81, 0.48)',
|
|
160
175
|
'text-inverse': p.white,
|
|
@@ -169,7 +184,7 @@ export const semanticColorsLight = {
|
|
|
169
184
|
'surface-input': greyRamp[50], // Input field background (filled variant)
|
|
170
185
|
|
|
171
186
|
// Background colors (background-*)
|
|
172
|
-
'background-base':
|
|
187
|
+
'background-base': semanticPins.backgroundBaseLight,
|
|
173
188
|
'background-default': p.white,
|
|
174
189
|
'background-subtle': greyRamp[50],
|
|
175
190
|
// Frame/bezel chrome — top bar + side nav shell, one step below
|
|
@@ -199,7 +214,7 @@ export const semanticColorsLight = {
|
|
|
199
214
|
'interactive-disabled-text': 'rgba(55, 65, 81, 0.26)',
|
|
200
215
|
|
|
201
216
|
// Divider
|
|
202
|
-
divider:
|
|
217
|
+
divider: semanticPins.dividerLight,
|
|
203
218
|
|
|
204
219
|
// Avatar default
|
|
205
220
|
'avatar-background': greyRamp[600],
|
|
@@ -221,7 +236,7 @@ export const semanticColorsDark = {
|
|
|
221
236
|
'brand-secondary': ramp.cyan[600],
|
|
222
237
|
'brand-secondary-light': ramp.cyan[500],
|
|
223
238
|
'brand-secondary-dark': ramp.cyan[700],
|
|
224
|
-
'brand-secondary-subtle': 'rgba(
|
|
239
|
+
'brand-secondary-subtle': 'rgba(34, 211, 238, 0.12)',
|
|
225
240
|
'brand-secondary-muted': 'rgba(48, 123, 155, 0.30)',
|
|
226
241
|
'brand-secondary-strong': 'rgba(48, 123, 155, 0.50)',
|
|
227
242
|
'brand-secondary-hover': ramp.cyan[500],
|
|
@@ -231,6 +246,15 @@ export const semanticColorsDark = {
|
|
|
231
246
|
'on-brand-primary': p.white,
|
|
232
247
|
'on-brand-secondary': p.white,
|
|
233
248
|
|
|
249
|
+
// Text ON a `-subtle` fill. Its own role: `brand-primary` and friends are tuned to
|
|
250
|
+
// carry a white label as a solid fill, which makes the two deepest of them
|
|
251
|
+
// (cyan[600], red[600]) too dark to read as text on a dark plane. Levelling the
|
|
252
|
+
// family at rung 300 puts every tone within OKLCH L 0.769-0.813 instead of
|
|
253
|
+
// 0.550-0.813. Brand is deliberately left at its own orange[400] (operator, AW-133)
|
|
254
|
+
// so the Voltras tone never drifts; it is the one tone under AA on a raised card.
|
|
255
|
+
'on-brand-primary-subtle': ramp.orange[400],
|
|
256
|
+
'on-brand-secondary-subtle': ramp.cyan[300],
|
|
257
|
+
|
|
234
258
|
// Status colors
|
|
235
259
|
'status-success': ramp.green[300],
|
|
236
260
|
'status-success-light': ramp.green[200],
|
|
@@ -246,7 +270,10 @@ export const semanticColorsDark = {
|
|
|
246
270
|
'status-error': ramp.red[600],
|
|
247
271
|
'status-error-light': ramp.red[500],
|
|
248
272
|
'status-error-dark': ramp.red[700],
|
|
249
|
-
|
|
273
|
+
// Alpha 0.08, not the family's 0.12: error's label is red[400], a rung darker than
|
|
274
|
+
// its siblings so it reads RED rather than pink (rung 300 has only 0.121 chroma).
|
|
275
|
+
// Thinning the fill buys back the contrast that extra darkness costs. See AW-133.
|
|
276
|
+
'status-error-subtle': 'rgba(247, 113, 117, 0.08)',
|
|
250
277
|
'status-error-muted': 'rgba(209, 67, 67, 0.30)',
|
|
251
278
|
'status-error-strong': 'rgba(209, 67, 67, 0.50)',
|
|
252
279
|
|
|
@@ -267,7 +294,7 @@ export const semanticColorsDark = {
|
|
|
267
294
|
'status-info': ramp.blue[500],
|
|
268
295
|
'status-info-light': ramp.blue[300],
|
|
269
296
|
'status-info-dark': ramp.blue[600],
|
|
270
|
-
'status-info-subtle': 'rgba(
|
|
297
|
+
'status-info-subtle': 'rgba(120, 194, 255, 0.12)',
|
|
271
298
|
'status-info-muted': 'rgba(33, 150, 243, 0.30)',
|
|
272
299
|
'status-info-strong': 'rgba(33, 150, 243, 0.50)',
|
|
273
300
|
|
|
@@ -277,14 +304,23 @@ export const semanticColorsDark = {
|
|
|
277
304
|
'on-status-warning': p.white,
|
|
278
305
|
'on-status-info': p.white,
|
|
279
306
|
|
|
307
|
+
// Text ON a `-subtle` fill — see the on-brand-*-subtle note above. Error is the
|
|
308
|
+
// second deliberate exception to the rung-300 rule (operator, AW-133): red[300]
|
|
309
|
+
// levelled perfectly but read PINK, because a red that light can only hold 0.121
|
|
310
|
+
// chroma. red[400] carries 0.165 and reads red; its fill is thinned to compensate.
|
|
311
|
+
'on-status-success-subtle': ramp.green[300],
|
|
312
|
+
'on-status-error-subtle': ramp.red[400],
|
|
313
|
+
'on-status-warning-subtle': ramp.amber[300],
|
|
314
|
+
'on-status-info-subtle': ramp.blue[300],
|
|
315
|
+
|
|
280
316
|
// Result/outcome indicators (result-*)
|
|
281
|
-
'result-improve':
|
|
317
|
+
'result-improve': resultPaletteColors.improve,
|
|
282
318
|
'result-improve-light': 'rgba(76, 175, 80, 0.16)',
|
|
283
|
-
'result-improve-dark':
|
|
284
|
-
'result-degrade':
|
|
319
|
+
'result-improve-dark': resultPaletteColors.improveDark,
|
|
320
|
+
'result-degrade': resultPaletteColors.degrade,
|
|
285
321
|
'result-degrade-light': 'rgba(239, 83, 80, 0.16)',
|
|
286
|
-
'result-degrade-dark':
|
|
287
|
-
'result-inconclusive':
|
|
322
|
+
'result-degrade-dark': resultPaletteColors.degradeDark,
|
|
323
|
+
'result-inconclusive': resultPaletteColors.inconclusive,
|
|
288
324
|
'result-inconclusive-light': 'rgba(158, 154, 151, 0.16)',
|
|
289
325
|
'result-neutral': greyRamp[400],
|
|
290
326
|
|
|
@@ -318,7 +354,7 @@ export const semanticColorsDark = {
|
|
|
318
354
|
'text-tertiary': greyRamp[500],
|
|
319
355
|
'text-disabled': 'rgba(255, 255, 255, 0.38)',
|
|
320
356
|
'text-inverse': greyRamp[950],
|
|
321
|
-
'text-link':
|
|
357
|
+
'text-link': semanticPins.focusIndigoDark,
|
|
322
358
|
'text-link-hover': ramp.blue[400],
|
|
323
359
|
|
|
324
360
|
// Surface colors - dark backgrounds — warm-tapered DERIVED ramp (TD-surface-tokens,
|
|
@@ -361,10 +397,10 @@ export const semanticColorsDark = {
|
|
|
361
397
|
// outright (4 call sites, high-visibility dividers), and grey-800 is not a
|
|
362
398
|
// plane, so it keeps its job without collision.
|
|
363
399
|
'border-prominent': greyRamp[800], // high-visibility divider
|
|
364
|
-
'border-focus':
|
|
400
|
+
'border-focus': semanticPins.focusIndigoDark,
|
|
365
401
|
'border-input': greyRamp[700],
|
|
366
402
|
'border-input-hover': greyRamp[600],
|
|
367
|
-
'border-input-focus':
|
|
403
|
+
'border-input-focus': semanticPins.focusIndigoDark,
|
|
368
404
|
'border-input-error': ramp.red[500],
|
|
369
405
|
|
|
370
406
|
// Alpha hairline separators — the primary separation cue (§4/S-2). Self-
|