@titan-design/react-ui 0.3.0 → 0.4.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 (52) hide show
  1. package/dist/bodymap.js +441 -97
  2. package/dist/bodymap.js.map +1 -1
  3. package/dist/bodymap.mjs +49 -62
  4. package/dist/bodymap.mjs.map +1 -1
  5. package/dist/{chunk-TOD2WQBG.mjs → chunk-2SISKTWM.mjs} +22 -43
  6. package/dist/chunk-2SISKTWM.mjs.map +1 -0
  7. package/dist/{chunk-P7TSQUN6.mjs → chunk-SNVKL5WZ.mjs} +42 -5
  8. package/dist/chunk-SNVKL5WZ.mjs.map +1 -0
  9. package/dist/index.d.mts +42 -2
  10. package/dist/index.d.ts +42 -2
  11. package/dist/index.js +431 -328
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +397 -314
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/theme/index.d.mts +28 -2
  16. package/dist/theme/index.d.ts +28 -2
  17. package/dist/theme/index.js +37 -0
  18. package/dist/theme/index.js.map +1 -1
  19. package/dist/theme/index.mjs +1 -1
  20. package/package.json +1 -1
  21. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +10 -15
  22. package/src/components/custom/Workout/BodyMap.tsx +7 -8
  23. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +25 -28
  24. package/src/components/custom/Workout/CapacityBandChart.tsx +2 -3
  25. package/src/components/custom/Workout/ExerciseCard.tsx +12 -27
  26. package/src/components/custom/Workout/ExerciseDetailPage.tsx +21 -27
  27. package/src/components/custom/Workout/InputBar.tsx +10 -11
  28. package/src/components/custom/Workout/MesoCard.tsx +2 -6
  29. package/src/components/custom/Workout/MesoStatusCard.tsx +17 -15
  30. package/src/components/custom/Workout/MuscleGroupChip.tsx +2 -4
  31. package/src/components/custom/Workout/PlaceholderStrip.tsx +2 -3
  32. package/src/components/custom/Workout/PrHistoryModal.tsx +12 -14
  33. package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -12
  34. package/src/components/custom/Workout/ReadinessCheck.tsx +13 -11
  35. package/src/components/custom/Workout/RestTimer.tsx +8 -7
  36. package/src/components/custom/Workout/SetRow.tsx +10 -7
  37. package/src/components/custom/Workout/StrengthTrendChart.tsx +15 -17
  38. package/src/components/custom/Workout/TempoBar.stories.tsx +95 -0
  39. package/src/components/custom/Workout/TempoBar.test.tsx +103 -0
  40. package/src/components/custom/Workout/TempoBar.tsx +215 -0
  41. package/src/components/custom/Workout/TrainingStatusPage.tsx +8 -17
  42. package/src/components/custom/Workout/VelocityStrip.tsx +7 -5
  43. package/src/components/custom/Workout/WeekRow.tsx +2 -1
  44. package/src/components/custom/Workout/WorkoutCard.tsx +3 -8
  45. package/src/components/custom/Workout/index.ts +9 -0
  46. package/src/test/nativewind-stub.ts +13 -0
  47. package/src/theme/ThemeProvider.test.tsx +24 -0
  48. package/src/theme/ThemeProvider.tsx +50 -0
  49. package/src/theme/index.ts +2 -0
  50. package/src/theme/resolve-color.ts +19 -0
  51. package/dist/chunk-P7TSQUN6.mjs.map +0 -1
  52. package/dist/chunk-TOD2WQBG.mjs.map +0 -1
@@ -16,14 +16,10 @@ import {
16
16
  import { ExerciseCard, type ExerciseCardProps } from './ExerciseCard'
17
17
  import { type SetRowProps } from './SetRow'
18
18
  import { VelocityStrip, calculateMeanVelocity, calculateVelocityLoss } from './VelocityStrip'
19
+ import { resolveColor } from '../../../theme/resolve-color'
20
+ import { cn } from '../../../utils/cn'
19
21
 
20
- const SURFACE_ELEVATED = 'var(--color-surface-elevated)'
21
- const BORDER_DEFAULT = 'var(--color-border-default)'
22
22
  const BRAND_PRIMARY = '#FF7900'
23
- const TEXT_PRIMARY = 'var(--color-text-primary)'
24
- const TEXT_SECONDARY = 'var(--color-text-secondary)'
25
- const TEXT_TERTIARY = 'var(--color-text-tertiary)'
26
- const PAGE_BG = 'var(--color-background-base)'
27
23
 
28
24
  /** Inner plot width: page width 390 − 16 page padding − 12 card padding on each side. */
29
25
  const CHART_WIDTH = 326
@@ -190,7 +186,7 @@ function TabBar({ active, onSelect }: TabBarProps) {
190
186
  className="flex-row"
191
187
  style={{
192
188
  borderBottomWidth: 1,
193
- borderBottomColor: BORDER_DEFAULT,
189
+ borderBottomColor: resolveColor('border-default'),
194
190
  }}
195
191
  accessibilityRole={'tablist' as ViewProps['accessibilityRole']}
196
192
  testID="exercise-detail-page-tabs"
@@ -213,11 +209,11 @@ function TabBar({ active, onSelect }: TabBarProps) {
213
209
  testID={`exercise-detail-page-tab-${key}`}
214
210
  >
215
211
  <Text
212
+ className={isActive ? 'text-text-primary' : 'text-text-tertiary'}
216
213
  style={{
217
214
  fontSize: 13,
218
215
  fontFamily: 'Inter, sans-serif',
219
216
  fontWeight: isActive ? '700' : '500',
220
- color: isActive ? TEXT_PRIMARY : TEXT_TERTIARY,
221
217
  }}
222
218
  >
223
219
  {label}
@@ -244,27 +240,27 @@ function StatStrip({ stats, unit }: { stats: ExerciseDetailStats; unit: 'lbs' |
244
240
  return (
245
241
  <View
246
242
  key={key}
243
+ className="bg-surface-elevated border-border"
247
244
  style={{
248
245
  flex: 1,
249
246
  padding: 12,
250
247
  borderRadius: 10,
251
- backgroundColor: SURFACE_ELEVATED,
252
248
  borderWidth: 1,
253
- borderColor: BORDER_DEFAULT,
254
249
  }}
255
250
  testID={`exercise-detail-page-stat-${key}`}
256
251
  >
257
252
  <Text
253
+ className="text-text-primary"
258
254
  style={{
259
255
  fontSize: 18,
260
256
  fontFamily: '"Space Grotesk", sans-serif',
261
257
  fontWeight: '700',
262
- color: TEXT_PRIMARY,
263
258
  }}
264
259
  >
265
260
  {value}
266
261
  </Text>
267
262
  <Text
263
+ className="text-text-tertiary"
268
264
  style={{
269
265
  marginTop: 2,
270
266
  fontSize: 10,
@@ -272,7 +268,6 @@ function StatStrip({ stats, unit }: { stats: ExerciseDetailStats; unit: 'lbs' |
272
268
  fontWeight: '600',
273
269
  letterSpacing: 0.4,
274
270
  textTransform: 'uppercase',
275
- color: TEXT_TERTIARY,
276
271
  }}
277
272
  >
278
273
  {label}
@@ -295,10 +290,9 @@ function SectionCard({
295
290
  }) {
296
291
  return (
297
292
  <View
293
+ className="bg-surface-elevated border-border"
298
294
  style={{
299
- backgroundColor: SURFACE_ELEVATED,
300
295
  borderWidth: 1,
301
- borderColor: BORDER_DEFAULT,
302
296
  borderRadius: 12,
303
297
  padding: 12,
304
298
  gap: 10,
@@ -306,13 +300,13 @@ function SectionCard({
306
300
  testID={testID}
307
301
  >
308
302
  <Text
303
+ className="text-text-tertiary"
309
304
  style={{
310
305
  fontSize: 11,
311
306
  fontFamily: 'Inter, sans-serif',
312
307
  fontWeight: '600',
313
308
  letterSpacing: 0.6,
314
309
  textTransform: 'uppercase',
315
- color: TEXT_TERTIARY,
316
310
  }}
317
311
  >
318
312
  {title}
@@ -334,7 +328,8 @@ function EntryList({ entries, expandedId, onToggle, emptyLabel, testID }: EntryL
334
328
  if (entries.length === 0) {
335
329
  return (
336
330
  <Text
337
- style={{ fontSize: 12, fontFamily: 'Inter, sans-serif', color: TEXT_TERTIARY }}
331
+ className="text-text-tertiary"
332
+ style={{ fontSize: 12, fontFamily: 'Inter, sans-serif' }}
338
333
  testID={`${testID}-empty`}
339
334
  >
340
335
  {emptyLabel}
@@ -367,12 +362,12 @@ function VbtBreakdown({ sets }: { sets: ExerciseVbtSet[] }) {
367
362
  testID="exercise-detail-page-vbt-set"
368
363
  >
369
364
  <Text
365
+ className="text-text-secondary"
370
366
  style={{
371
367
  width: 44,
372
368
  fontSize: 11,
373
369
  fontFamily: 'Inter, sans-serif',
374
370
  fontWeight: '600',
375
- color: TEXT_SECONDARY,
376
371
  }}
377
372
  >
378
373
  {set.label}
@@ -381,11 +376,11 @@ function VbtBreakdown({ sets }: { sets: ExerciseVbtSet[] }) {
381
376
  <VelocityStrip velocities={set.velocities} variant="mini" />
382
377
  </View>
383
378
  <Text
379
+ className="text-text-tertiary"
384
380
  style={{
385
381
  fontSize: 11,
386
382
  fontFamily: 'Inter, sans-serif',
387
383
  fontVariant: ['tabular-nums'],
388
- color: TEXT_TERTIARY,
389
384
  }}
390
385
  >
391
386
  {`${mean.toFixed(2)} · -${loss}%`}
@@ -407,26 +402,26 @@ function VbtSummaryRow({ summary }: { summary: VbtSummary }) {
407
402
  {cells.map((cell) => (
408
403
  <View
409
404
  key={cell.label}
405
+ className="bg-surface-elevated border-border"
410
406
  style={{
411
407
  flex: 1,
412
408
  padding: 12,
413
409
  borderRadius: 10,
414
- backgroundColor: SURFACE_ELEVATED,
415
410
  borderWidth: 1,
416
- borderColor: BORDER_DEFAULT,
417
411
  }}
418
412
  >
419
413
  <Text
414
+ className="text-text-primary"
420
415
  style={{
421
416
  fontSize: 16,
422
417
  fontFamily: '"Space Grotesk", sans-serif',
423
418
  fontWeight: '700',
424
- color: TEXT_PRIMARY,
425
419
  }}
426
420
  >
427
421
  {cell.value}
428
422
  </Text>
429
423
  <Text
424
+ className="text-text-tertiary"
430
425
  style={{
431
426
  marginTop: 2,
432
427
  fontSize: 10,
@@ -434,7 +429,6 @@ function VbtSummaryRow({ summary }: { summary: VbtSummary }) {
434
429
  fontWeight: '600',
435
430
  letterSpacing: 0.4,
436
431
  textTransform: 'uppercase',
437
- color: TEXT_TERTIARY,
438
432
  }}
439
433
  >
440
434
  {cell.label}
@@ -488,8 +482,8 @@ export function ExerciseDetailPage({
488
482
 
489
483
  return (
490
484
  <View
491
- className={className}
492
- style={{ width: 390, backgroundColor: PAGE_BG }}
485
+ className={cn('bg-background-base', className)}
486
+ style={{ width: 390 }}
493
487
  accessibilityRole={'main' as ViewProps['accessibilityRole']}
494
488
  aria-label={exercise.name}
495
489
  testID="exercise-detail-page"
@@ -504,22 +498,22 @@ export function ExerciseDetailPage({
504
498
  <View style={{ flexShrink: 1 }}>
505
499
  <Text
506
500
  accessibilityRole="header"
501
+ className="text-text-primary"
507
502
  style={{
508
503
  fontSize: 20,
509
504
  fontFamily: '"Space Grotesk", sans-serif',
510
505
  fontWeight: '700',
511
- color: TEXT_PRIMARY,
512
506
  }}
513
507
  testID="exercise-detail-page-title"
514
508
  >
515
509
  {exercise.name}
516
510
  </Text>
517
511
  <Text
512
+ className="text-text-secondary"
518
513
  style={{
519
514
  marginTop: 2,
520
515
  fontSize: 12,
521
516
  fontFamily: 'Inter, sans-serif',
522
- color: TEXT_SECONDARY,
523
517
  }}
524
518
  testID="exercise-detail-page-subtitle"
525
519
  >
@@ -539,13 +533,13 @@ export function ExerciseDetailPage({
539
533
  testID="exercise-detail-page-e1rm"
540
534
  >
541
535
  <Text
536
+ className="text-text-tertiary"
542
537
  style={{
543
538
  fontSize: 9,
544
539
  fontFamily: 'Inter, sans-serif',
545
540
  fontWeight: '600',
546
541
  letterSpacing: 0.4,
547
542
  textTransform: 'uppercase',
548
- color: TEXT_TERTIARY,
549
543
  }}
550
544
  >
551
545
  e1RM
@@ -1,6 +1,7 @@
1
1
  // Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
2
2
  import React from 'react'
3
3
  import { View, Text, Pressable, TextInput } from 'react-native'
4
+ import { resolveColor } from '../../../theme/resolve-color'
4
5
 
5
6
  export interface InputBarProps {
6
7
  exerciseName: string
@@ -17,19 +18,15 @@ export interface InputBarProps {
17
18
  }
18
19
 
19
20
  const BRAND_PRIMARY = '#FF7900'
20
- const TEXT_PRIMARY = 'var(--color-text-primary)'
21
- const TEXT_TERTIARY = 'var(--color-text-tertiary)'
21
+ const INPUT_CLASSNAME = 'bg-surface-raised border-border-strong text-text-primary'
22
22
 
23
23
  const inputStyle = {
24
24
  fontSize: 14,
25
25
  fontWeight: '600' as const,
26
26
  fontFamily: 'Inter, sans-serif',
27
- backgroundColor: 'var(--color-surface-raised)',
28
27
  borderWidth: 1,
29
- borderColor: 'var(--color-border-strong)',
30
28
  borderRadius: 6,
31
29
  textAlign: 'center' as const,
32
- color: TEXT_PRIMARY,
33
30
  paddingVertical: 5,
34
31
  paddingHorizontal: 2,
35
32
  }
@@ -53,11 +50,11 @@ export function InputBar({
53
50
 
54
51
  return (
55
52
  <View
53
+ className="bg-surface-elevated"
56
54
  style={{
57
55
  width: '100%',
58
- backgroundColor: 'var(--color-surface-elevated)',
59
56
  borderTopWidth: 1,
60
- borderTopColor: 'var(--color-border-default)',
57
+ borderTopColor: resolveColor('border-default'),
61
58
  paddingTop: 10,
62
59
  paddingHorizontal: 16,
63
60
  paddingBottom: 12,
@@ -70,11 +67,11 @@ export function InputBar({
70
67
  >
71
68
  <View style={{ minWidth: 80, flexDirection: 'column' }}>
72
69
  <Text
70
+ className="text-text-primary"
73
71
  style={{
74
72
  fontSize: 12,
75
73
  fontWeight: '700',
76
74
  fontFamily: '"Space Grotesk", sans-serif',
77
- color: TEXT_PRIMARY,
78
75
  }}
79
76
  testID="input-bar-exercise-name"
80
77
  numberOfLines={1}
@@ -82,10 +79,10 @@ export function InputBar({
82
79
  {exerciseName}
83
80
  </Text>
84
81
  <Text
82
+ className="text-text-tertiary"
85
83
  style={{
86
84
  fontSize: 10,
87
85
  fontFamily: 'Inter, sans-serif',
88
- color: TEXT_TERTIARY,
89
86
  }}
90
87
  testID="input-bar-set-info"
91
88
  >
@@ -97,16 +94,17 @@ export function InputBar({
97
94
  <TextInput
98
95
  value={reps}
99
96
  onChangeText={onRepsChange}
97
+ className={INPUT_CLASSNAME}
100
98
  style={{ ...inputStyle, width: 36 }}
101
99
  accessibilityLabel="Reps"
102
100
  testID="input-bar-reps"
103
101
  keyboardType="numeric"
104
102
  />
105
103
  <Text
104
+ className="text-text-tertiary"
106
105
  style={{
107
106
  fontSize: 12,
108
107
  fontFamily: 'Inter, sans-serif',
109
- color: TEXT_TERTIARY,
110
108
  }}
111
109
  >
112
110
  {'\u00D7'}
@@ -114,17 +112,18 @@ export function InputBar({
114
112
  <TextInput
115
113
  value={weight}
116
114
  onChangeText={onWeightChange}
115
+ className={INPUT_CLASSNAME}
117
116
  style={{ ...inputStyle, width: 52 }}
118
117
  accessibilityLabel={`Weight in ${unit}`}
119
118
  testID="input-bar-weight"
120
119
  keyboardType="numeric"
121
120
  />
122
121
  <Text
122
+ className="text-text-tertiary"
123
123
  style={{
124
124
  fontSize: 12,
125
125
  fontWeight: '500',
126
126
  fontFamily: 'Inter, sans-serif',
127
- color: TEXT_TERTIARY,
128
127
  }}
129
128
  testID="input-bar-unit"
130
129
  >
@@ -9,10 +9,6 @@ const BRAND_PRIMARY = '#FF7900'
9
9
  const BRAND_PRIMARY_DARK = '#C45E00'
10
10
  const BRAND_PRIMARY_LIGHT = '#FFB066'
11
11
  const BORDER_DEFAULT = '#1F1F1F'
12
- // Theme-aware foregrounds: resolve to a readable color in both light and dark
13
- // (react-native-web passes the CSS var through to the inline style).
14
- const TEXT_PRIMARY = 'var(--color-text-primary)'
15
- const TEXT_SECONDARY = 'var(--color-text-secondary)'
16
12
 
17
13
  /** Gradient stops for the 3px top accent: dark -> primary -> light. */
18
14
  const ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY, BRAND_PRIMARY_LIGHT]
@@ -119,11 +115,11 @@ export function MesoCard({
119
115
  <View style={{ paddingHorizontal: 14, paddingTop: 12, paddingBottom: 10 }} testID="meso-card-body">
120
116
  <View className="flex-row items-center" style={{ gap: 8 }} testID="meso-card-header">
121
117
  <Text
118
+ className="text-text-primary"
122
119
  style={{
123
120
  fontSize: 15,
124
121
  fontFamily: '"Space Grotesk", sans-serif',
125
122
  fontWeight: '700',
126
- color: TEXT_PRIMARY,
127
123
  }}
128
124
  testID="meso-card-name"
129
125
  >
@@ -135,11 +131,11 @@ export function MesoCard({
135
131
  </View>
136
132
 
137
133
  <Text
134
+ className="text-text-secondary"
138
135
  style={{
139
136
  marginTop: 4,
140
137
  fontSize: 12,
141
138
  fontFamily: 'Inter, sans-serif',
142
- color: TEXT_SECONDARY,
143
139
  }}
144
140
  testID="meso-card-subheader"
145
141
  >
@@ -3,13 +3,11 @@ import { Fragment, type ReactNode } from 'react'
3
3
  import { View, Text, type ViewProps, type ViewStyle } from 'react-native'
4
4
  import { Card } from '../../ui/card'
5
5
  import { StatusDot } from './StatusDot'
6
+ import { resolveColor } from '../../../theme/resolve-color'
6
7
 
7
8
  const BRAND_PRIMARY = '#FF7900'
8
9
  const BRAND_PRIMARY_DARK = '#C45E00'
9
10
  const BRAND_PRIMARY_LIGHT = '#FFB066'
10
- const TEXT_PRIMARY = 'var(--color-text-primary)'
11
- const TEXT_SECONDARY = 'var(--color-text-secondary)'
12
- const TEXT_TERTIARY = 'var(--color-text-tertiary)'
13
11
 
14
12
  const SUCCESS = '#14B8A6'
15
13
  const WARNING = '#FFB020'
@@ -18,9 +16,12 @@ const ERROR = '#D14343'
18
16
  /** Gradient stops for the 3px top accent: dark -> primary -> light (matches MesoCard). */
19
17
  const ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY, BRAND_PRIMARY_LIGHT]
20
18
 
21
- /** Card surface gradient: elevated -> raised at 135deg (theme-aware). */
22
- const CARD_GRADIENT =
23
- 'linear-gradient(135deg, var(--color-surface-elevated) 0%, var(--color-surface-raised) 100%)'
19
+ /**
20
+ * Card surface gradient: elevated -> raised at 135deg. Uses resolved dark-theme
21
+ * hexes (a gradient string can't carry a className token, and var() renders
22
+ * black on native).
23
+ */
24
+ const CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor('surface-elevated')} 0%, ${resolveColor('surface-raised')} 100%)`
24
25
 
25
26
  /** Gauge track gradient (teal -> amber -> red) at 0.25 alpha. */
26
27
  const GAUGE_GRADIENT =
@@ -118,7 +119,8 @@ function renderCoachingText(text: string, highlights?: string[]): ReactNode {
118
119
  highlights.includes(part) ? (
119
120
  <Text
120
121
  key={`${part}-${index}`}
121
- style={{ fontWeight: '700', color: TEXT_PRIMARY }}
122
+ className="text-text-primary"
123
+ style={{ fontWeight: '700' }}
122
124
  >
123
125
  {part}
124
126
  </Text>
@@ -166,24 +168,24 @@ function MetricCell({ metric }: { metric: MesoStatusMetric }) {
166
168
  return (
167
169
  <View style={{ width: '48%' }} testID="meso-status-card-metric">
168
170
  <Text
171
+ className="text-text-tertiary"
169
172
  style={{
170
173
  fontSize: 10,
171
174
  fontFamily: 'Inter, sans-serif',
172
175
  fontWeight: '600',
173
176
  letterSpacing: 0.5,
174
177
  textTransform: 'uppercase',
175
- color: TEXT_TERTIARY,
176
178
  }}
177
179
  >
178
180
  {metric.label}
179
181
  </Text>
180
182
  <Text
183
+ className="text-text-primary"
181
184
  style={{
182
185
  marginTop: 2,
183
186
  fontSize: 13,
184
187
  fontFamily: 'Inter, sans-serif',
185
188
  fontWeight: '600',
186
- color: TEXT_PRIMARY,
187
189
  }}
188
190
  >
189
191
  {metric.value}
@@ -212,24 +214,24 @@ function Gauge({ gauge }: { gauge: MesoStatusGauge }) {
212
214
  accessibilityElementsHidden
213
215
  >
214
216
  <Text
217
+ className="text-text-secondary"
215
218
  style={{
216
219
  fontSize: 10,
217
220
  fontFamily: 'Inter, sans-serif',
218
221
  fontWeight: '500',
219
222
  letterSpacing: 0.5,
220
223
  textTransform: 'uppercase',
221
- color: TEXT_SECONDARY,
222
224
  }}
223
225
  >
224
226
  {gauge.label}
225
227
  </Text>
226
228
  {gauge.sublabel != null && (
227
229
  <Text
230
+ className="text-text-tertiary"
228
231
  style={{
229
232
  fontSize: 10,
230
233
  fontFamily: 'Inter, sans-serif',
231
234
  fontWeight: '500',
232
- color: TEXT_TERTIARY,
233
235
  }}
234
236
  >
235
237
  {gauge.sublabel}
@@ -261,6 +263,7 @@ function Gauge({ gauge }: { gauge: MesoStatusGauge }) {
261
263
  testID="meso-status-card-gauge-center"
262
264
  />
263
265
  <View
266
+ className="border-text-primary"
264
267
  style={{
265
268
  position: 'absolute',
266
269
  left: `${percentage}%`,
@@ -270,7 +273,6 @@ function Gauge({ gauge }: { gauge: MesoStatusGauge }) {
270
273
  height: 14,
271
274
  borderRadius: 9999,
272
275
  borderWidth: 2,
273
- borderColor: TEXT_PRIMARY,
274
276
  backgroundColor: markerColor,
275
277
  boxShadow: '0 0 4px rgba(0,0,0,0.5)',
276
278
  }}
@@ -349,12 +351,12 @@ export function MesoStatusCard({
349
351
  style={{ gap: 8 }}
350
352
  >
351
353
  <Text
354
+ className="text-text-primary"
352
355
  style={{
353
356
  flexShrink: 1,
354
357
  fontSize: 15,
355
358
  fontFamily: '"Space Grotesk", sans-serif',
356
359
  fontWeight: '700',
357
- color: TEXT_PRIMARY,
358
360
  }}
359
361
  testID="meso-status-card-name"
360
362
  >
@@ -363,11 +365,11 @@ export function MesoStatusCard({
363
365
  <StatusPill badge={statusBadge} />
364
366
  </View>
365
367
  <Text
368
+ className="text-text-secondary"
366
369
  style={{
367
370
  marginTop: 4,
368
371
  fontSize: 12,
369
372
  fontFamily: 'Inter, sans-serif',
370
- color: TEXT_SECONDARY,
371
373
  }}
372
374
  testID="meso-status-card-subtitle"
373
375
  >
@@ -408,11 +410,11 @@ export function MesoStatusCard({
408
410
  testID="meso-status-card-coaching"
409
411
  >
410
412
  <Text
413
+ className="text-text-secondary"
411
414
  style={{
412
415
  fontSize: 12,
413
416
  lineHeight: 17,
414
417
  fontFamily: 'Inter, sans-serif',
415
- color: TEXT_SECONDARY,
416
418
  }}
417
419
  >
418
420
  {renderCoachingText(coaching.text, coaching.highlights)}
@@ -34,16 +34,14 @@ export function MuscleGroupChip({
34
34
 
35
35
  const content = (
36
36
  <View
37
- className={className}
37
+ className={['bg-surface-raised border-border', className].filter(Boolean).join(' ')}
38
38
  style={{
39
39
  flexDirection: 'row',
40
40
  alignItems: 'center',
41
41
  borderRadius: 9999,
42
42
  paddingHorizontal: 9,
43
43
  paddingVertical: 3,
44
- backgroundColor: 'var(--color-surface-raised)',
45
44
  borderWidth: 1,
46
- borderColor: 'var(--color-border-default)',
47
45
  }}
48
46
  accessibilityLabel={onPress ? undefined : `${name}, volume status: ${statusLabel}`}
49
47
  testID="muscle-group-chip"
@@ -62,11 +60,11 @@ export function MuscleGroupChip({
62
60
  testID="muscle-group-chip-dot"
63
61
  />
64
62
  <Text
63
+ className="text-text-secondary"
65
64
  style={{
66
65
  fontFamily: 'Inter, sans-serif',
67
66
  fontWeight: '500',
68
67
  fontSize: 11,
69
- color: 'var(--color-text-secondary)',
70
68
  }}
71
69
  accessibilityElementsHidden
72
70
  >
@@ -18,14 +18,13 @@ function SingleStrip({
18
18
  }: Omit<PlaceholderStripProps, 'mode' | 'segments'>) {
19
19
  return (
20
20
  <View
21
- className={cn(className)}
21
+ className={cn('border-border-strong', className)}
22
22
  style={[
23
23
  {
24
24
  height: 3,
25
25
  backgroundColor: 'transparent',
26
26
  borderWidth: 1,
27
27
  borderStyle: 'dashed',
28
- borderColor: 'var(--color-border-strong)',
29
28
  borderRadius: 1,
30
29
  opacity: 0.5,
31
30
  },
@@ -60,13 +59,13 @@ function SegmentedStrip({
60
59
  {Array.from({ length: segments }, (_, i) => (
61
60
  <View
62
61
  key={i}
62
+ className="border-border-strong"
63
63
  style={{
64
64
  flex: 1,
65
65
  height: 3,
66
66
  backgroundColor: 'transparent',
67
67
  borderWidth: 1,
68
68
  borderStyle: 'dashed',
69
- borderColor: 'var(--color-border-strong)',
70
69
  borderRadius: 1,
71
70
  minWidth: 4,
72
71
  }}