@titan-design/react-ui 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/dist/MesoStatusCard-CQk71hSi.d.mts +77 -0
  2. package/dist/MesoStatusCard-CQk71hSi.d.ts +77 -0
  3. package/dist/bodymap.d.mts +246 -3
  4. package/dist/bodymap.d.ts +246 -3
  5. package/dist/bodymap.js +232 -185
  6. package/dist/bodymap.js.map +1 -1
  7. package/dist/bodymap.mjs +1963 -11
  8. package/dist/bodymap.mjs.map +1 -1
  9. package/dist/index.d.mts +193 -744
  10. package/dist/index.d.ts +193 -744
  11. package/dist/index.js +1551 -1856
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +10770 -8213
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/pages-D7Jlssvp.d.ts +791 -0
  16. package/dist/pages-MO0JCySL.d.mts +791 -0
  17. package/dist/pages.d.mts +4 -0
  18. package/dist/pages.d.ts +4 -0
  19. package/dist/pages.js +6694 -0
  20. package/dist/pages.js.map +1 -0
  21. package/dist/pages.mjs +6674 -0
  22. package/dist/pages.mjs.map +1 -0
  23. package/dist/theme/index.d.mts +473 -211
  24. package/dist/theme/index.d.ts +473 -211
  25. package/dist/theme/index.js +341 -127
  26. package/dist/theme/index.js.map +1 -1
  27. package/dist/theme/index.mjs +2085 -2
  28. package/dist/theme/index.mjs.map +1 -1
  29. package/dist/theme/tokens-css.js +148 -139
  30. package/dist/theme/tokens-css.js.map +1 -1
  31. package/dist/theme/tokens-css.mjs +582 -1
  32. package/dist/theme/tokens-css.mjs.map +1 -1
  33. package/package.json +11 -7
  34. package/src/components/custom/DateTime/DateTime.stories.tsx +82 -6
  35. package/src/components/custom/DateTime/DateTime.test.tsx +29 -3
  36. package/src/components/custom/DateTime/DateTime.tsx +55 -15
  37. package/src/components/custom/Gauge/Gauge.test.tsx +2 -2
  38. package/src/components/custom/Gauge/Gauge.tsx +6 -3
  39. package/src/components/custom/Scatter/Scatter.tsx +3 -5
  40. package/src/components/custom/Treemap/Treemap.tsx +3 -5
  41. package/src/components/custom/Typography/Typography.stories.tsx +45 -27
  42. package/src/components/custom/Typography/Typography.test.tsx +13 -3
  43. package/src/components/custom/Typography/Typography.tsx +5 -0
  44. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +2 -1
  45. package/src/components/custom/Workout/BaseBadge.stories.tsx +3 -3
  46. package/src/components/custom/Workout/BaseBadge.test.tsx +1 -1
  47. package/src/components/custom/Workout/BaseBadge.tsx +1 -1
  48. package/src/components/custom/Workout/BodyMap.tsx +6 -3
  49. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +6 -3
  50. package/src/components/custom/Workout/CapacityBandChart.test.tsx +2 -2
  51. package/src/components/custom/Workout/CapacityBandChart.tsx +9 -6
  52. package/src/components/custom/Workout/DeviationBar.test.tsx +1 -1
  53. package/src/components/custom/Workout/DeviationBar.tsx +7 -4
  54. package/src/components/custom/Workout/ExerciseCard.tsx +5 -1
  55. package/src/components/custom/Workout/ExerciseDetailPage.tsx +19 -5
  56. package/src/components/custom/Workout/InputBar.tsx +2 -1
  57. package/src/components/custom/Workout/IntensityBar.test.tsx +112 -60
  58. package/src/components/custom/Workout/IntensityBar.tsx +113 -58
  59. package/src/components/custom/Workout/MesoCard.tsx +8 -3
  60. package/src/components/custom/Workout/MesoProgressBar.test.tsx +1 -1
  61. package/src/components/custom/Workout/MesoProgressBar.tsx +3 -2
  62. package/src/components/custom/Workout/MesoStatusCard.tsx +20 -13
  63. package/src/components/custom/Workout/MuscleGroupChip.tsx +7 -4
  64. package/src/components/custom/Workout/PlaceholderStrip.tsx +5 -9
  65. package/src/components/custom/Workout/PrBadge.tsx +7 -4
  66. package/src/components/custom/Workout/PrHistoryModal.tsx +6 -5
  67. package/src/components/custom/Workout/ProgramPlanningPage.tsx +2 -1
  68. package/src/components/custom/Workout/README.md +50 -0
  69. package/src/components/custom/Workout/ReadinessCheck.tsx +7 -4
  70. package/src/components/custom/Workout/RestTimer.test.tsx +41 -10
  71. package/src/components/custom/Workout/RestTimer.tsx +50 -44
  72. package/src/components/custom/Workout/SetRow.tsx +12 -2
  73. package/src/components/custom/Workout/Sparkline.tsx +2 -1
  74. package/src/components/custom/Workout/StatusDot.test.tsx +2 -2
  75. package/src/components/custom/Workout/StatusDot.tsx +12 -9
  76. package/src/components/custom/Workout/StrengthTrendChart.tsx +9 -6
  77. package/src/components/custom/Workout/SupersetWrapper.tsx +2 -1
  78. package/src/components/custom/Workout/TempoDisplay.stories.tsx +69 -2
  79. package/src/components/custom/Workout/TempoDisplay.test.tsx +35 -0
  80. package/src/components/custom/Workout/TempoDisplay.tsx +109 -3
  81. package/src/components/custom/Workout/VelocityStrip.test.tsx +89 -2
  82. package/src/components/custom/Workout/VelocityStrip.tsx +203 -38
  83. package/src/components/custom/Workout/WeekRow.test.tsx +2 -2
  84. package/src/components/custom/Workout/WeekRow.tsx +3 -2
  85. package/src/components/custom/Workout/WeightBadge.test.tsx +2 -2
  86. package/src/components/custom/Workout/WeightBadge.tsx +8 -4
  87. package/src/components/custom/Workout/WorkoutCard.tsx +5 -2
  88. package/src/components/custom/Workout/WorkoutPill.tsx +12 -8
  89. package/src/components/custom/Workout/icons.tsx +7 -0
  90. package/src/components/custom/Workout/index.ts +38 -47
  91. package/src/components/icons/SvgIcon.tsx +50 -0
  92. package/src/components/icons/icons.stories.tsx +57 -0
  93. package/src/components/icons/icons.test.tsx +43 -0
  94. package/src/components/icons/icons.tsx +45 -0
  95. package/src/components/icons/index.ts +4 -0
  96. package/src/components/index.ts +6 -0
  97. package/src/components/shell/BrandLockup.stories.tsx +27 -0
  98. package/src/components/shell/BrandLockup.test.tsx +23 -0
  99. package/src/components/shell/BrandLockup.tsx +47 -0
  100. package/src/components/shell/DeviceIndicator.stories.tsx +28 -0
  101. package/src/components/shell/DeviceIndicator.test.tsx +26 -0
  102. package/src/components/shell/DeviceIndicator.tsx +52 -0
  103. package/src/components/shell/DeviceMenu.stories.tsx +47 -0
  104. package/src/components/shell/DeviceMenu.test.tsx +40 -0
  105. package/src/components/shell/DeviceMenu.tsx +65 -0
  106. package/src/components/shell/DeviceRow.stories.tsx +38 -0
  107. package/src/components/shell/DeviceRow.test.tsx +37 -0
  108. package/src/components/shell/DeviceRow.tsx +58 -0
  109. package/src/components/shell/README.md +86 -0
  110. package/src/components/shell/SessionStatePill.stories.tsx +27 -0
  111. package/src/components/shell/SessionStatePill.test.tsx +25 -0
  112. package/src/components/shell/SessionStatePill.tsx +46 -0
  113. package/src/components/shell/TopBar.stories.tsx +49 -0
  114. package/src/components/shell/TopBar.test.tsx +36 -0
  115. package/src/components/shell/TopBar.tsx +89 -0
  116. package/src/components/shell/index.ts +8 -0
  117. package/src/components/ui/indicator/Indicator.stories.tsx +37 -1
  118. package/src/components/ui/indicator/Indicator.test.tsx +19 -1
  119. package/src/components/ui/indicator/Indicator.tsx +45 -6
  120. package/src/components/ui/indicator/index.ts +1 -1
  121. package/src/components/ui/spinner/Spinner.tsx +3 -2
  122. package/src/components/ui/toolbar-button/ToolbarButton.tsx +2 -1
  123. package/src/index.ts +3 -2
  124. package/src/pages.ts +61 -0
  125. package/src/test/stories-smoke.test.tsx +50 -0
  126. package/src/theme/ColorSystem.stories.tsx +323 -0
  127. package/src/theme/Colors.stories.tsx +69 -1
  128. package/src/theme/barrel.ts +54 -0
  129. package/src/theme/config.ts +16 -3
  130. package/src/theme/extracted-colors-dataviz.ts +21 -0
  131. package/src/theme/extracted-colors-ui.ts +20 -0
  132. package/src/theme/global.css +64 -52
  133. package/src/theme/gradients.test.ts +25 -0
  134. package/src/theme/gradients.ts +36 -0
  135. package/src/theme/index.ts +8 -43
  136. package/src/theme/native-theming-guard.test.ts +117 -0
  137. package/src/theme/tokens/primitives.test.ts +232 -0
  138. package/src/theme/tokens/primitives.ts +247 -0
  139. package/src/theme/tokens/semantic.ts +93 -81
  140. package/src/theme/workout-tokens.ts +22 -21
  141. package/src/utils/avatar-color.ts +3 -3
  142. package/tailwind.config.js +10 -3
  143. package/dist/bodymap-BhG55xHM.d.mts +0 -318
  144. package/dist/bodymap-BhG55xHM.d.ts +0 -318
  145. package/dist/chunk-2SISKTWM.mjs +0 -1027
  146. package/dist/chunk-2SISKTWM.mjs.map +0 -1
  147. package/dist/chunk-7XPB4NAO.mjs +0 -1013
  148. package/dist/chunk-7XPB4NAO.mjs.map +0 -1
  149. package/dist/chunk-SNVKL5WZ.mjs +0 -883
  150. package/dist/chunk-SNVKL5WZ.mjs.map +0 -1
@@ -17,49 +17,54 @@
17
17
  * - interactive-* : Hover/focus/active/disabled states
18
18
  */
19
19
 
20
- import { primitiveColors as p, discreteRainbow } from './primitives'
20
+ import { primitiveColors as p, primitiveRamps as ramp, discreteRainbow } from './primitives'
21
21
 
22
22
  // Light mode semantic colors (default)
23
23
  export const semanticColorsLight = {
24
24
  // Brand colors (brand-*)
25
- 'brand-primary': p.accent[400], // #FF7900
26
- 'brand-primary-light': p.accent[200], // #FF9630
27
- 'brand-primary-dark': p.accent[700], // #D0620C
25
+ 'brand-primary': ramp.orange[400],
26
+ 'brand-primary-light': ramp.orange[300],
27
+ 'brand-primary-dark': ramp.orange[500],
28
28
  'brand-primary-subtle': 'rgba(255, 121, 0, 0.08)',
29
- 'brand-primary-hover': p.accent[500],
30
- 'brand-primary-active': p.accent[600],
29
+ 'brand-primary-hover': ramp.orange[500],
30
+ 'brand-primary-active': ramp.orange[600],
31
31
 
32
- 'brand-secondary': p.steel[500], // #406D87
33
- 'brand-secondary-light': p.steel[300], // #678498
34
- 'brand-secondary-dark': p.steel[700], // #32556D
35
- 'brand-secondary-subtle': 'rgba(64, 109, 135, 0.08)',
36
- 'brand-secondary-hover': p.steel[600],
37
- 'brand-secondary-active': p.steel[700],
32
+ 'brand-secondary': ramp.cyan[600],
33
+ 'brand-secondary-light': ramp.cyan[500],
34
+ 'brand-secondary-dark': ramp.cyan[700],
35
+ 'brand-secondary-subtle': 'rgba(48, 123, 155, 0.08)',
36
+ 'brand-secondary-hover': ramp.cyan[700],
37
+ 'brand-secondary-active': ramp.cyan[800],
38
38
 
39
39
  // Text on brand backgrounds (on-*)
40
40
  'on-brand-primary': p.white,
41
41
  'on-brand-secondary': p.white,
42
42
 
43
43
  // Status colors (status-*)
44
- 'status-success': p.teal[500], // #14B8A6
45
- 'status-success-light': p.teal[400], // #43C6B7
46
- 'status-success-dark': p.teal[700], // #0E8074
47
- 'status-success-subtle': p.teal[50],
48
-
49
- 'status-error': p.red[600], // #D14343
50
- 'status-error-light': p.red[400], // #DA6868
51
- 'status-error-dark': p.red[700], // #922E2E
52
- 'status-error-subtle': p.red[50],
53
-
54
- 'status-warning': p.amber[500], // #FFB020
55
- 'status-warning-light': p.amber[400], // #FFBF4C
56
- 'status-warning-dark': p.amber[600], // #B27B16
57
- 'status-warning-subtle': p.amber[50],
58
-
59
- 'status-info': p.sky[500], // #2196F3
60
- 'status-info-light': p.sky[400], // #64B6F7
61
- 'status-info-dark': p.sky[700], // #0B79D0
62
- 'status-info-subtle': p.sky[50],
44
+ 'status-success': ramp.green[300],
45
+ 'status-success-light': ramp.green[200],
46
+ 'status-success-dark': ramp.green[600],
47
+ 'status-success-subtle': ramp.green[50],
48
+
49
+ 'status-error': ramp.red[600],
50
+ 'status-error-light': ramp.red[500],
51
+ 'status-error-dark': ramp.red[700],
52
+ 'status-error-subtle': ramp.red[50],
53
+
54
+ 'status-error-vivid': p.redVivid[500], // vivid alert red
55
+ 'status-error-vivid-light': p.redVivid[400],
56
+ 'status-error-vivid-dark': p.redVivid[700],
57
+ 'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',
58
+
59
+ 'status-warning': ramp.amber[300],
60
+ 'status-warning-light': ramp.amber[200],
61
+ 'status-warning-dark': ramp.amber[500],
62
+ 'status-warning-subtle': ramp.amber[50],
63
+
64
+ 'status-info': ramp.blue[500],
65
+ 'status-info-light': ramp.blue[300],
66
+ 'status-info-dark': ramp.blue[600],
67
+ 'status-info-subtle': ramp.blue[50],
63
68
 
64
69
  // Text on status backgrounds (on-status-*)
65
70
  'on-status-success': p.white,
@@ -85,16 +90,16 @@ export const semanticColorsLight = {
85
90
 
86
91
  // Data visualization colors (data-*)
87
92
  // First 10 colors from discrete rainbow optimized for charts
88
- 'data-1': discreteRainbow[9], // #1965B0 - Blue
89
- 'data-2': discreteRainbow[14], // #4EB265 - Green
90
- 'data-3': discreteRainbow[17], // #F7F056 - Yellow
91
- 'data-4': discreteRainbow[25], // #DC050C - Red
92
- 'data-5': discreteRainbow[8], // #882E72 - Purple
93
- 'data-6': discreteRainbow[20], // #F4A736 - Orange
94
- 'data-7': discreteRainbow[13], // #7BAFDE - Light Blue
95
- 'data-8': discreteRainbow[15], // #90C987 - Light Green
96
- 'data-9': discreteRainbow[3], // #CAACCB - Lavender
97
- 'data-10': discreteRainbow[22], // #EE8026 - Dark Orange
93
+ 'data-1': discreteRainbow[9], // Blue
94
+ 'data-2': discreteRainbow[14], // Green
95
+ 'data-3': discreteRainbow[17], // Yellow
96
+ 'data-4': discreteRainbow[25], // Red
97
+ 'data-5': discreteRainbow[8], // Purple
98
+ 'data-6': discreteRainbow[20], // Orange
99
+ 'data-7': discreteRainbow[13], // Light Blue
100
+ 'data-8': discreteRainbow[15], // Light Green
101
+ 'data-9': discreteRainbow[3], // Lavender
102
+ 'data-10': discreteRainbow[22], // Dark Orange
98
103
 
99
104
  // Text colors (text-*)
100
105
  'text-primary': '#121828',
@@ -107,8 +112,8 @@ export const semanticColorsLight = {
107
112
 
108
113
  // Surface colors (surface-*) - for elevated containers
109
114
  'surface-base': p.white,
110
- 'surface-elevated': p.neutral[50], // #FAFAFA - slightly off-white for elevated cards
111
- 'surface-raised': p.neutral[100], // #F3F4F6 - light gray for raised cards
115
+ 'surface-elevated': p.neutral[50], // slightly off-white for elevated cards
116
+ 'surface-raised': p.neutral[100], // light gray for raised cards
112
117
  'surface-overlay': p.white,
113
118
  'surface-input': p.neutral[50], // Input field background (filled variant)
114
119
 
@@ -121,6 +126,7 @@ export const semanticColorsLight = {
121
126
  'border-default': '#E8E9EB',
122
127
  'border-subtle': p.neutral[100],
123
128
  'border-strong': p.neutral[300],
129
+ 'border-prominent': p.neutral[400], // high-visibility divider
124
130
  'border-focus': p.blue[600],
125
131
  'border-input': p.neutral[300], // Input field border
126
132
  'border-input-hover': p.neutral[400], // Input field border on hover
@@ -146,43 +152,48 @@ export const semanticColorsLight = {
146
152
  // Dark mode semantic colors
147
153
  export const semanticColorsDark = {
148
154
  // Brand colors stay the same in dark mode
149
- 'brand-primary': p.accent[400],
150
- 'brand-primary-light': p.accent[200],
151
- 'brand-primary-dark': p.accent[700],
155
+ 'brand-primary': ramp.orange[400],
156
+ 'brand-primary-light': ramp.orange[300],
157
+ 'brand-primary-dark': ramp.orange[500],
152
158
  'brand-primary-subtle': 'rgba(255, 121, 0, 0.12)',
153
- 'brand-primary-hover': p.accent[300],
154
- 'brand-primary-active': p.accent[200],
159
+ 'brand-primary-hover': ramp.orange[300],
160
+ 'brand-primary-active': ramp.orange[200],
155
161
 
156
- 'brand-secondary': p.steel[500],
157
- 'brand-secondary-light': p.steel[300],
158
- 'brand-secondary-dark': p.steel[700],
159
- 'brand-secondary-subtle': 'rgba(64, 109, 135, 0.12)',
160
- 'brand-secondary-hover': p.steel[400],
161
- 'brand-secondary-active': p.steel[300],
162
+ 'brand-secondary': ramp.cyan[600],
163
+ 'brand-secondary-light': ramp.cyan[500],
164
+ 'brand-secondary-dark': ramp.cyan[700],
165
+ 'brand-secondary-subtle': 'rgba(48, 123, 155, 0.12)',
166
+ 'brand-secondary-hover': ramp.cyan[500],
167
+ 'brand-secondary-active': ramp.cyan[400],
162
168
 
163
169
  // Text on brand backgrounds
164
170
  'on-brand-primary': p.white,
165
171
  'on-brand-secondary': p.white,
166
172
 
167
173
  // Status colors
168
- 'status-success': p.teal[500],
169
- 'status-success-light': p.teal[400],
170
- 'status-success-dark': p.teal[700],
171
- 'status-success-subtle': 'rgba(20, 184, 166, 0.12)',
172
-
173
- 'status-error': p.red[600],
174
- 'status-error-light': p.red[400],
175
- 'status-error-dark': p.red[700],
174
+ 'status-success': ramp.green[300],
175
+ 'status-success-light': ramp.green[200],
176
+ 'status-success-dark': ramp.green[600],
177
+ 'status-success-subtle': 'rgba(46, 213, 115, 0.12)',
178
+
179
+ 'status-error': ramp.red[600],
180
+ 'status-error-light': ramp.red[500],
181
+ 'status-error-dark': ramp.red[700],
176
182
  'status-error-subtle': 'rgba(209, 67, 67, 0.12)',
177
183
 
178
- 'status-warning': p.amber[500],
179
- 'status-warning-light': p.amber[400],
180
- 'status-warning-dark': p.amber[600],
181
- 'status-warning-subtle': 'rgba(255, 176, 32, 0.12)',
184
+ 'status-error-vivid': p.redVivid[500],
185
+ 'status-error-vivid-light': p.redVivid[400],
186
+ 'status-error-vivid-dark': p.redVivid[700],
187
+ 'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',
182
188
 
183
- 'status-info': p.sky[500],
184
- 'status-info-light': p.sky[400],
185
- 'status-info-dark': p.sky[700],
189
+ 'status-warning': ramp.amber[300],
190
+ 'status-warning-light': ramp.amber[200],
191
+ 'status-warning-dark': ramp.amber[500],
192
+ 'status-warning-subtle': 'rgba(249, 180, 21, 0.12)',
193
+
194
+ 'status-info': ramp.blue[500],
195
+ 'status-info-light': ramp.blue[300],
196
+ 'status-info-dark': ramp.blue[600],
186
197
  'status-info-subtle': 'rgba(33, 150, 243, 0.12)',
187
198
 
188
199
  // Text on status backgrounds
@@ -229,21 +240,22 @@ export const semanticColorsDark = {
229
240
  'text-link-hover': p.blue[400],
230
241
 
231
242
  // Surface colors - dark backgrounds
232
- 'surface-base': p.charcoal[700], // #161616 - main surface
233
- 'surface-elevated': p.charcoal[600], // #191919 - elevated surface
234
- 'surface-raised': p.charcoal[500], // #1C1C1C - raised surface
235
- 'surface-overlay': p.charcoal[600], // #191919 - overlay surface
236
- 'surface-input': p.charcoal[600], // #191919 - input surface
243
+ 'surface-base': p.charcoal[700], // main surface
244
+ 'surface-elevated': p.charcoal[600], // elevated surface
245
+ 'surface-raised': p.charcoal[500], // raised surface
246
+ 'surface-overlay': p.charcoal[600], // overlay surface
247
+ 'surface-input': p.charcoal[600], // input surface
237
248
 
238
249
  // Background colors
239
- 'background-base': p.charcoal[900], // #101010 - darkest charcoal
240
- 'background-default': p.charcoal[700], // #161616 - main background
241
- 'background-subtle': p.charcoal[500], // #1C1C1C - subtle background
250
+ 'background-base': p.charcoal[900], // darkest charcoal
251
+ 'background-default': p.charcoal[700], // main background
252
+ 'background-subtle': p.charcoal[500], // subtle background
242
253
 
243
254
  // Border colors
244
- 'border-default': p.charcoal[400], // #1F1F1F - default border
245
- 'border-subtle': p.charcoal[500], // #1C1C1C - subtle border
246
- 'border-strong': p.charcoal[300], // #2C2C2C - strong border
255
+ 'border-default': p.charcoal[400], // default border
256
+ 'border-subtle': p.charcoal[500], // subtle border
257
+ 'border-strong': p.charcoal[300], // strong border
258
+ 'border-prominent': p.charcoal[200], // high-visibility divider
247
259
  'border-focus': '#828DF8',
248
260
  'border-input': p.neutral[600],
249
261
  'border-input-hover': p.neutral[500],
@@ -259,7 +271,7 @@ export const semanticColorsDark = {
259
271
  'interactive-disabled-text': 'rgba(255, 255, 255, 0.26)',
260
272
 
261
273
  // Divider
262
- 'divider': p.charcoal[400], // #1F1F1F - divider color
274
+ 'divider': p.charcoal[400], // divider color
263
275
 
264
276
  // Avatar default
265
277
  'avatar-background': p.neutral[600],
@@ -2,31 +2,32 @@
2
2
  * Workout-specific tokens not yet in the main Tailwind config.
3
3
  * Use these inline instead of Tailwind classes.
4
4
  */
5
+ import { divergingScale, sequentialEffort, primitiveRamps as ramp } from './tokens/primitives'
6
+
5
7
  export const WORKOUT_TOKENS = {
6
8
  // Canonical 4-band performance scale — the single source for BOTH the
7
9
  // VelocityStrip zone bars and the SetRow RPE color (TD-03.43). The direction
8
10
  // is intentionally inverted between the two consumers: for velocity, green =
9
- // fastest/best; for RPE, green = easiest. Each component maps its own
10
- // thresholds onto these four colors. Kept as vivid data-viz values (distinct
11
- // from the muted status tokens) and theme-independent, so — like the heatmap
12
- // scale below — they are consumed inline as a JS import rather than CSS vars.
13
- // A JS import also resolves on native RN, unlike var(--…) strings.
11
+ // fastest/best; for RPE, green = easiest. This is the [0,1,2,4] subsample of
12
+ // the canonical `sequentialEffort` primitive. The `orange` key is the band
13
+ // label. Consumed inline (RN).
14
14
  scale: {
15
- green: '#2ed573',
16
- yellow: '#ffd43b',
17
- orange: '#ffa502',
18
- red: '#ff4757',
15
+ green: sequentialEffort[0],
16
+ yellow: sequentialEffort[1],
17
+ orange: sequentialEffort[2], // gold band
18
+ red: sequentialEffort[4],
19
19
  },
20
20
 
21
- // BodyMap volume heatmap scale (drive dynamic SVG fills, so inline values).
22
- // Maps weekly-volume status against MEV/MAV/MRV landmarks to a fill color.
21
+ // BodyMap volume heatmap the canonical `divergingScale` (under optimal
22
+ // over): a true diverging shape with a light green center, cool-blue under-
23
+ // trained end and warm-red over-reaching end (colorblind-robust in lightness).
23
24
  heatmap: {
24
- none: '#E0E0E0', // gray — no training data
25
- under: '#4A90D9', // cool blue — below MEV
26
- maintenance: '#F5C842', // warm yellow — MEV to MAV
27
- productive: '#4CAF50', // green — MAV to MRV
28
- approaching: '#FFA502', // orange — near MRV
29
- over: '#FF6B35', // red-orange — over MRV
25
+ none: '#E0E0E0', // no training data
26
+ under: divergingScale[0], // below MEV
27
+ maintenance: divergingScale[1], // MEV to MAV
28
+ productive: divergingScale[2], // optimal center — MAV to MRV
29
+ approaching: divergingScale[3], // near MRV
30
+ over: divergingScale[4], // over MRV
30
31
  },
31
32
 
32
33
  // Badge border-radius (rounded-sm is 4px, we need 2px)
@@ -36,12 +37,12 @@ export const WORKOUT_TOKENS = {
36
37
  // components use the CSS custom properties (var(--color-surface-*/border-*))
37
38
  // directly. Only theme-independent data-viz values remain below.
38
39
 
39
- // Intensity bar specific
40
+ // Intensity bar specific — over-target tiers deepen along the red ramp.
40
41
  intensity: {
41
42
  track: '#333333',
42
- over1: '#D14343',
43
- over2: '#A62626',
44
- over3: '#7A1C1C',
43
+ over1: ramp.red[600], // matches status-error
44
+ over2: ramp.red[700],
45
+ over3: ramp.red[800],
45
46
  targetLine: 'rgba(33, 150, 243, 0.5)',
46
47
  atTargetGlow:
47
48
  '0 0 5px 1px rgba(33, 150, 243, 0.35), 0 0 10px 3px rgba(33, 150, 243, 0.15)',
@@ -1,6 +1,6 @@
1
- const AVATAR_COLORS = [
2
- '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8'
3
- ]
1
+ import { AVATAR_CATEGORICAL_COLORS } from '../theme/extracted-colors-ui'
2
+
3
+ const AVATAR_COLORS = AVATAR_CATEGORICAL_COLORS
4
4
 
5
5
  export function avatarColor(name: string): string {
6
6
  let hash = 0
@@ -44,6 +44,12 @@ module.exports = {
44
44
  dark: 'var(--color-status-error-dark)',
45
45
  subtle: 'var(--color-status-error-subtle)',
46
46
  },
47
+ 'error-vivid': {
48
+ DEFAULT: 'var(--color-status-error-vivid)',
49
+ light: 'var(--color-status-error-vivid-light)',
50
+ dark: 'var(--color-status-error-vivid-dark)',
51
+ subtle: 'var(--color-status-error-vivid-subtle)',
52
+ },
47
53
  warning: {
48
54
  DEFAULT: 'var(--color-status-warning)',
49
55
  light: 'var(--color-status-warning-light)',
@@ -132,6 +138,7 @@ module.exports = {
132
138
  DEFAULT: 'var(--color-border-default)',
133
139
  subtle: 'var(--color-border-subtle)',
134
140
  strong: 'var(--color-border-strong)',
141
+ prominent: 'var(--color-border-prominent)',
135
142
  focus: 'var(--color-border-focus)',
136
143
  input: {
137
144
  DEFAULT: 'var(--color-border-input)',
@@ -184,10 +191,10 @@ module.exports = {
184
191
  xl: '0px 20px 25px rgba(100, 116, 139, 0.12)',
185
192
  // Glow shadows (colored radial glow for emphasis)
186
193
  'glow-primary': '0 0 20px 2px rgba(var(--color-brand-primary-rgb, 255, 121, 0), 0.4)',
187
- 'glow-secondary': '0 0 20px 2px rgba(var(--color-brand-secondary-rgb, 64, 109, 135), 0.4)',
188
- 'glow-success': '0 0 20px 2px rgba(var(--color-status-success-rgb, 20, 184, 166), 0.35)',
194
+ 'glow-secondary': '0 0 20px 2px rgba(var(--color-brand-secondary-rgb, 48, 123, 155), 0.4)',
195
+ 'glow-success': '0 0 20px 2px rgba(var(--color-status-success-rgb, 46, 213, 115), 0.35)',
189
196
  'glow-error': '0 0 20px 2px rgba(var(--color-status-error-rgb, 209, 67, 67), 0.4)',
190
- 'glow-warning': '0 0 20px 2px rgba(var(--color-status-warning-rgb, 255, 176, 32), 0.35)',
197
+ 'glow-warning': '0 0 20px 2px rgba(var(--color-status-warning-rgb, 249, 180, 21), 0.35)',
191
198
  'glow-info': '0 0 20px 2px rgba(var(--color-status-info-rgb, 33, 150, 243), 0.35)',
192
199
  'glow-sm': '0 0 12px 0px',
193
200
  'glow-md': '0 0 20px 2px',