@titan-design/react-ui 0.12.1 → 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.
Files changed (531) hide show
  1. package/README.md +60 -47
  2. package/dist/bodymap.js +856 -736
  3. package/dist/bodymap.js.map +1 -1
  4. package/dist/bodymap.mjs +858 -738
  5. package/dist/bodymap.mjs.map +1 -1
  6. package/dist/index.d.mts +1431 -237
  7. package/dist/index.d.ts +1431 -237
  8. package/dist/index.js +6506 -4781
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +6280 -4642
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/{pages-B1hqnGIC.d.ts → pages-CsjsUn0G.d.ts} +51 -16
  13. package/dist/{pages-CvsFqNtx.d.mts → pages-ZbT_pD_U.d.mts} +51 -16
  14. package/dist/pages.d.mts +1 -1
  15. package/dist/pages.d.ts +1 -1
  16. package/dist/pages.js +1919 -1937
  17. package/dist/pages.js.map +1 -1
  18. package/dist/pages.mjs +1927 -1945
  19. package/dist/pages.mjs.map +1 -1
  20. package/dist/theme/index.d.mts +225 -140
  21. package/dist/theme/index.d.ts +225 -140
  22. package/dist/theme/index.js +298 -319
  23. package/dist/theme/index.js.map +1 -1
  24. package/dist/theme/index.mjs +283 -315
  25. package/dist/theme/index.mjs.map +1 -1
  26. package/dist/theme/tokens-css.js +145 -24
  27. package/dist/theme/tokens-css.js.map +1 -1
  28. package/dist/theme/tokens-css.mjs +145 -24
  29. package/dist/theme/tokens-css.mjs.map +1 -1
  30. package/dist/theme/tokens.d.mts +128 -11
  31. package/dist/theme/tokens.d.ts +128 -11
  32. package/dist/theme/tokens.js +126 -26
  33. package/dist/theme/tokens.js.map +1 -1
  34. package/dist/theme/tokens.mjs +124 -27
  35. package/dist/theme/tokens.mjs.map +1 -1
  36. package/docs/audits/2026-09-08-critique-addenda.md +51 -0
  37. package/docs/audits/2026-09-08-library-critique.md +212 -0
  38. package/docs/library-roadmap.md +99 -0
  39. package/docs/render-testing-pattern.md +130 -0
  40. package/package.json +1 -1
  41. package/src/arch/Architecture.stories.tsx +3 -1
  42. package/src/arch/arch-graph.freshness.test.ts +52 -0
  43. package/src/arch/arch-graph.json +4989 -1583
  44. package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
  45. package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
  46. package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
  47. package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
  48. package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
  49. package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
  50. package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
  51. package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
  52. package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
  53. package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
  54. package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
  55. package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
  56. package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
  57. package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
  58. package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
  59. package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
  60. package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
  61. package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
  62. package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
  63. package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
  64. package/src/components/custom/ActiveWork/InitiativeBrief.tsx +182 -0
  65. package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
  66. package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
  67. package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
  68. package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
  69. package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
  70. package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
  71. package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
  72. package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
  73. package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
  74. package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
  75. package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
  76. package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
  77. package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
  78. package/src/components/custom/ActiveWork/README.md +305 -0
  79. package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
  80. package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
  81. package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
  82. package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
  83. package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
  84. package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
  85. package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
  86. package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
  87. package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
  88. package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
  89. package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
  90. package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
  91. package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
  92. package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
  93. package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
  94. package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
  95. package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
  96. package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
  97. package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
  98. package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
  99. package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
  100. package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
  101. package/src/components/custom/ActiveWork/format-time.ts +32 -0
  102. package/src/components/custom/ActiveWork/index.ts +19 -0
  103. package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
  104. package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
  105. package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
  106. package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
  107. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +12 -6
  108. package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
  109. package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
  110. package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
  111. package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
  112. package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
  113. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
  114. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
  115. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
  116. package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
  117. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
  118. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
  119. package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
  120. package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
  121. package/src/components/custom/Fatigue/README.md +40 -3
  122. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
  123. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
  124. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
  125. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
  126. package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
  127. package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
  128. package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
  129. package/src/components/custom/Fatigue/index.ts +17 -5
  130. package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
  131. package/src/components/custom/Fatigue/panel-layout.ts +185 -0
  132. package/src/components/custom/Gauge/Gauge.stories.tsx +6 -3
  133. package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
  134. package/src/components/custom/Gauge/Gauge.tsx +7 -2
  135. package/src/components/custom/Metric/Metric.stories.tsx +10 -1
  136. package/src/components/custom/Metric/Metric.test.tsx +1 -3
  137. package/src/components/custom/Metric/Metric.tsx +5 -20
  138. package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
  139. package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
  140. package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
  141. package/src/components/custom/Prose/README.md +58 -0
  142. package/src/components/custom/Prose/index.ts +1 -0
  143. package/src/components/custom/Scatter/Scatter.stories.tsx +55 -14
  144. package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
  145. package/src/components/custom/Scatter/Scatter.tsx +122 -18
  146. package/src/components/custom/Sidebar/Sidebar.stories.tsx +41 -8
  147. package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
  148. package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
  149. package/src/components/custom/Table/Table.stories.tsx +99 -16
  150. package/src/components/custom/Table/Table.test.tsx +273 -86
  151. package/src/components/custom/Table/Table.tsx +159 -67
  152. package/src/components/custom/Table/column-fit.test.ts +75 -0
  153. package/src/components/custom/Table/column-fit.ts +116 -0
  154. package/src/components/custom/Table/index.ts +9 -0
  155. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
  156. package/src/components/custom/Treemap/Treemap.stories.tsx +15 -12
  157. package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
  158. package/src/components/custom/Treemap/Treemap.tsx +11 -3
  159. package/src/components/custom/Typography/Typography.stories.tsx +28 -1
  160. package/src/components/custom/Typography/Typography.test.tsx +34 -0
  161. package/src/components/custom/Typography/Typography.tsx +6 -0
  162. package/src/components/custom/Typography/index.ts +1 -8
  163. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +11 -2
  164. package/src/components/custom/Workout/BaseBadge.stories.tsx +27 -11
  165. package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
  166. package/src/components/custom/Workout/BaseBadge.tsx +6 -2
  167. package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
  168. package/src/components/custom/Workout/BodyMap.tsx +8 -4
  169. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +28 -6
  170. package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
  171. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +50 -12
  172. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +12 -9
  173. package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
  174. package/src/components/custom/Workout/CapacityBandChart.tsx +144 -111
  175. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  176. package/src/components/custom/Workout/DeviationBar.test.tsx +10 -4
  177. package/src/components/custom/Workout/DeviationBar.tsx +24 -16
  178. package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +183 -0
  179. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +32 -18
  180. package/src/components/custom/Workout/ExerciseCard.stories.tsx +12 -11
  181. package/src/components/custom/Workout/ExerciseCard.test.tsx +52 -22
  182. package/src/components/custom/Workout/ExerciseCard.tsx +99 -183
  183. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +95 -12
  184. package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +189 -1
  185. package/src/components/custom/Workout/ExerciseCardHeading.tsx +167 -18
  186. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
  187. package/src/components/custom/Workout/ExerciseDetailPage.tsx +3 -2
  188. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
  189. package/src/components/custom/Workout/ExerciseHeading.tsx +194 -46
  190. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +12 -9
  191. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
  192. package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
  193. package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
  194. package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
  195. package/src/components/custom/Workout/InputBar.tsx +4 -2
  196. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  197. package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
  198. package/src/components/custom/Workout/IntensityBar.tsx +8 -3
  199. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
  200. package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
  201. package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
  202. package/src/components/custom/Workout/MesoCard.tsx +14 -10
  203. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  204. package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
  205. package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
  206. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
  207. package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
  208. package/src/components/custom/Workout/MesoStatusCard.tsx +20 -33
  209. package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
  210. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
  211. package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
  212. package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
  213. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +9 -4
  214. package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
  215. package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
  216. package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
  217. package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
  218. package/src/components/custom/Workout/PrBadge.tsx +13 -17
  219. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +16 -3
  220. package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
  221. package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
  222. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
  223. package/src/components/custom/Workout/README.md +68 -17
  224. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
  225. package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
  226. package/src/components/custom/Workout/ReadinessCheck.tsx +22 -4
  227. package/src/components/custom/Workout/RestTimer.stories.tsx +16 -4
  228. package/src/components/custom/Workout/RestTimer.tsx +4 -2
  229. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
  230. package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
  231. package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
  232. package/src/components/custom/Workout/SegmentedBar.stories.tsx +21 -17
  233. package/src/components/custom/Workout/SegmentedBar.tsx +10 -5
  234. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
  235. package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
  236. package/src/components/custom/Workout/SessionHeader.tsx +12 -12
  237. package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
  238. package/src/components/custom/Workout/SessionRail.tsx +7 -9
  239. package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
  240. package/src/components/custom/Workout/SetBar.test.tsx +49 -4
  241. package/src/components/custom/Workout/SetBar.tsx +38 -12
  242. package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
  243. package/src/components/custom/Workout/SetRow.test.tsx +16 -2
  244. package/src/components/custom/Workout/SetRow.tsx +61 -23
  245. package/src/components/custom/Workout/SetStrip.stories.tsx +63 -7
  246. package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
  247. package/src/components/custom/Workout/SetStrip.tsx +24 -4
  248. package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
  249. package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
  250. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
  251. package/src/components/custom/Workout/SetsRepsLoad.tsx +24 -12
  252. package/src/components/custom/Workout/Sparkline.stories.tsx +14 -11
  253. package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
  254. package/src/components/custom/Workout/Sparkline.tsx +14 -18
  255. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  256. package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
  257. package/src/components/custom/Workout/StatusDot.tsx +93 -63
  258. package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
  259. package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
  260. package/src/components/custom/Workout/StatusPill.tsx +27 -38
  261. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +11 -4
  262. package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
  263. package/src/components/custom/Workout/StrengthTrendChart.tsx +39 -36
  264. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
  265. package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
  266. package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
  267. package/src/components/custom/Workout/TempoDisplay.stories.tsx +26 -10
  268. package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
  269. package/src/components/custom/Workout/TempoDisplay.tsx +2 -0
  270. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
  271. package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
  272. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +10 -6
  273. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +5 -2
  274. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +44 -1
  275. package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
  276. package/src/components/custom/Workout/VelocityStrip.test.tsx +48 -6
  277. package/src/components/custom/Workout/VelocityStrip.tsx +26 -14
  278. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
  279. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
  280. package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
  281. package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
  282. package/src/components/custom/Workout/WeekRow.tsx +23 -16
  283. package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
  284. package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
  285. package/src/components/custom/Workout/WeightBadge.tsx +28 -27
  286. package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
  287. package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
  288. package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
  289. package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
  290. package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
  291. package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
  292. package/src/components/custom/Workout/ZoneTrack.stories.tsx +10 -7
  293. package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
  294. package/src/components/custom/Workout/exerciseRowState.ts +29 -0
  295. package/src/components/custom/Workout/index.ts +17 -2
  296. package/src/components/custom/Workout/metricText.stories.tsx +15 -13
  297. package/src/components/custom/Workout/metricText.tsx +8 -2
  298. package/src/components/custom/Workout/setHeadingKit.tsx +219 -36
  299. package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
  300. package/src/components/custom/charts/README.md +66 -0
  301. package/src/components/custom/charts/SetBarChart.test.tsx +46 -1
  302. package/src/components/custom/charts/SetBarChart.tsx +56 -9
  303. package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
  304. package/src/components/custom/charts/SparkBars.test.tsx +69 -0
  305. package/src/components/custom/charts/SparkBars.tsx +85 -0
  306. package/src/components/custom/charts/flatBarGeometry.test.ts +41 -0
  307. package/src/components/custom/charts/flatBarGeometry.ts +32 -0
  308. package/src/components/custom/charts/index.ts +3 -0
  309. package/src/components/custom/index.ts +3 -0
  310. package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
  311. package/src/components/custom/stepper/Stepper.test.tsx +1 -7
  312. package/src/components/custom/stepper/Stepper.tsx +21 -34
  313. package/src/components/icons/icons.stories.tsx +1 -1
  314. package/src/components/icons/icons.tsx +51 -0
  315. package/src/components/shell/AppShell.stories.tsx +150 -0
  316. package/src/components/shell/AppShell.test.tsx +70 -0
  317. package/src/components/shell/AppShell.tsx +90 -0
  318. package/src/components/shell/BrandLockup.stories.tsx +66 -5
  319. package/src/components/shell/BrandLockup.test.tsx +34 -1
  320. package/src/components/shell/BrandLockup.tsx +27 -11
  321. package/src/components/shell/NavItem.stories.tsx +4 -4
  322. package/src/components/shell/NavItem.test.tsx +17 -0
  323. package/src/components/shell/NavItem.tsx +17 -5
  324. package/src/components/shell/README.md +89 -26
  325. package/src/components/shell/SideNav.stories.tsx +38 -7
  326. package/src/components/shell/SideNav.test.tsx +16 -8
  327. package/src/components/shell/SideNav.tsx +17 -17
  328. package/src/components/shell/TopBar.stories.tsx +44 -19
  329. package/src/components/shell/TopBar.test.tsx +34 -12
  330. package/src/components/shell/TopBar.tsx +61 -40
  331. package/src/components/shell/brands.tsx +66 -0
  332. package/src/components/shell/index.ts +9 -8
  333. package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
  334. package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
  335. package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
  336. package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
  337. package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
  338. package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
  339. package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
  340. package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
  341. package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
  342. package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
  343. package/src/components/shell/workout/WorkoutShell.tsx +77 -0
  344. package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
  345. package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
  346. package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
  347. package/src/components/shell/workout/index.ts +9 -0
  348. package/src/components/shell/workout/workoutNavItems.tsx +16 -0
  349. package/src/components/ui/README.md +110 -0
  350. package/src/components/ui/alert/Alert.stories.tsx +15 -5
  351. package/src/components/ui/alert/Alert.tsx +24 -3
  352. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
  353. package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
  354. package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
  355. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  356. package/src/components/ui/avatar/Avatar.tsx +2 -10
  357. package/src/components/ui/badge/Badge.stories.tsx +83 -28
  358. package/src/components/ui/badge/Badge.test.tsx +19 -3
  359. package/src/components/ui/badge/Badge.tsx +48 -55
  360. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  361. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
  362. package/src/components/ui/button/Button.stories.tsx +46 -12
  363. package/src/components/ui/button/Button.tsx +44 -37
  364. package/src/components/ui/card/Card.stories.tsx +90 -94
  365. package/src/components/ui/card/Card.test.tsx +80 -6
  366. package/src/components/ui/card/Card.tsx +150 -203
  367. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  368. package/src/components/ui/checkbox/Checkbox.tsx +7 -27
  369. package/src/components/ui/chip/Chip.stories.tsx +37 -13
  370. package/src/components/ui/chip/Chip.test.tsx +10 -6
  371. package/src/components/ui/chip/Chip.tsx +76 -91
  372. package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
  373. package/src/components/ui/collapse/Collapse.tsx +6 -11
  374. package/src/components/ui/data-row/DataRow.stories.tsx +14 -3
  375. package/src/components/ui/data-row/DataRow.test.tsx +5 -15
  376. package/src/components/ui/data-row/DataRow.tsx +18 -7
  377. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  378. package/src/components/ui/divider/Divider.tsx +1 -5
  379. package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
  380. package/src/components/ui/drawer/Drawer.tsx +13 -27
  381. package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
  382. package/src/components/ui/form-field/FormField.stories.tsx +6 -20
  383. package/src/components/ui/form-field/FormField.test.tsx +1 -5
  384. package/src/components/ui/form-field/FormField.tsx +10 -46
  385. package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
  386. package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
  387. package/src/components/ui/help-tip/HelpTip.tsx +21 -22
  388. package/src/components/ui/help-tip/index.ts +7 -1
  389. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  390. package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
  391. package/src/components/ui/icon-box/IconBox.tsx +10 -18
  392. package/src/components/ui/indicator/Indicator.stories.tsx +5 -4
  393. package/src/components/ui/indicator/Indicator.tsx +20 -14
  394. package/src/components/ui/input/Input.stories.tsx +3 -11
  395. package/src/components/ui/input/Input.test.tsx +2 -10
  396. package/src/components/ui/input/Input.tsx +10 -25
  397. package/src/components/ui/input/index.ts +7 -1
  398. package/src/components/ui/link/Link.stories.tsx +19 -7
  399. package/src/components/ui/list-item/ListItem.stories.tsx +17 -5
  400. package/src/components/ui/list-item/ListItem.tsx +2 -9
  401. package/src/components/ui/menu/Menu.stories.tsx +21 -15
  402. package/src/components/ui/menu/Menu.test.tsx +2 -11
  403. package/src/components/ui/menu/Menu.tsx +12 -14
  404. package/src/components/ui/menu/index.ts +8 -1
  405. package/src/components/ui/modal/Modal.stories.tsx +2 -2
  406. package/src/components/ui/modal/Modal.tsx +31 -19
  407. package/src/components/ui/pill/Pill.stories.tsx +111 -23
  408. package/src/components/ui/pill/Pill.test.tsx +101 -3
  409. package/src/components/ui/pill/Pill.tsx +168 -49
  410. package/src/components/ui/pill/index.ts +1 -1
  411. package/src/components/ui/popover/Popover.stories.tsx +6 -8
  412. package/src/components/ui/popover/Popover.test.tsx +1 -6
  413. package/src/components/ui/popover/Popover.tsx +20 -15
  414. package/src/components/ui/popover/index.ts +7 -1
  415. package/src/components/ui/progress/Progress.stories.tsx +3 -12
  416. package/src/components/ui/progress/Progress.test.tsx +1 -5
  417. package/src/components/ui/progress/Progress.tsx +9 -6
  418. package/src/components/ui/radio/Radio.stories.tsx +42 -21
  419. package/src/components/ui/radio/Radio.test.tsx +6 -2
  420. package/src/components/ui/radio/Radio.tsx +23 -22
  421. package/src/components/ui/section/Section.stories.tsx +12 -21
  422. package/src/components/ui/section/Section.test.tsx +1 -6
  423. package/src/components/ui/section/Section.tsx +1 -3
  424. package/src/components/ui/section/index.ts +1 -5
  425. package/src/components/ui/select/Select.stories.tsx +3 -13
  426. package/src/components/ui/select/Select.test.tsx +2 -11
  427. package/src/components/ui/select/Select.tsx +16 -15
  428. package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
  429. package/src/components/ui/skeleton/Skeleton.tsx +3 -14
  430. package/src/components/ui/skeleton/index.ts +1 -7
  431. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  432. package/src/components/ui/spinner/Spinner.tsx +4 -5
  433. package/src/components/ui/stack/Stack.stories.tsx +8 -8
  434. package/src/components/ui/stack/Stack.tsx +1 -1
  435. package/src/components/ui/surface/Surface.stories.tsx +92 -33
  436. package/src/components/ui/surface/Surface.test.tsx +88 -28
  437. package/src/components/ui/surface/Surface.tsx +37 -87
  438. package/src/components/ui/surface/SurfaceContext.ts +22 -62
  439. package/src/components/ui/surface/index.ts +8 -0
  440. package/src/components/ui/surface/resolveSurface.ts +98 -0
  441. package/src/components/ui/surface/surface.contract.test.ts +6 -1
  442. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  443. package/src/components/ui/switch/Switch.tsx +7 -6
  444. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  445. package/src/components/ui/tabs/Tabs.tsx +8 -21
  446. package/src/components/ui/tabs/index.ts +1 -7
  447. package/src/components/ui/tile/Tile.stories.tsx +1 -1
  448. package/src/components/ui/tile/Tile.tsx +3 -0
  449. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  450. package/src/components/ui/toast/Toast.test.tsx +2 -8
  451. package/src/components/ui/toast/Toast.tsx +49 -57
  452. package/src/components/ui/toast/index.ts +0 -1
  453. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
  454. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
  455. package/src/components/ui/toolbar-button/ToolbarButton.tsx +38 -49
  456. package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
  457. package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
  458. package/src/components/ui/tooltip/Tooltip.tsx +55 -36
  459. package/src/components/ui/tooltip/index.ts +1 -1
  460. package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
  461. package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
  462. package/src/components/ui/trigger/index.ts +2 -0
  463. package/src/stories/PresetShowcase.stories.tsx +101 -48
  464. package/src/test/no-device-internals.test.ts +3 -3
  465. package/src/test/no-raw-color.test.ts +39 -0
  466. package/src/theme/Alpha.stories.tsx +103 -0
  467. package/src/theme/ChoosingTokens.stories.tsx +48 -0
  468. package/src/theme/ColorPalettes.stories.tsx +62 -45
  469. package/src/theme/ColorPrimitives.stories.tsx +35 -35
  470. package/src/theme/Depth.stories.tsx +132 -65
  471. package/src/theme/DepthCalibration.stories.tsx +23 -21
  472. package/src/theme/ProposedTokensVW82.stories.tsx +414 -0
  473. package/src/theme/ThemeProvider.test.tsx +4 -4
  474. package/src/theme/barrel.ts +7 -6
  475. package/src/theme/color-stories.coverage.test.ts +1 -1
  476. package/src/theme/color-utils.ts +41 -29
  477. package/src/theme/config.completeness.test.ts +1 -1
  478. package/src/theme/config.ts +40 -0
  479. package/src/theme/elevation.test.ts +82 -56
  480. package/src/theme/elevation.ts +77 -561
  481. package/src/theme/global.css +45 -5
  482. package/src/theme/grey-ramp.test.ts +24 -8
  483. package/src/theme/lift.test.ts +39 -0
  484. package/src/theme/lift.ts +102 -0
  485. package/src/theme/materials.test.ts +5 -2
  486. package/src/theme/materials.ts +38 -4
  487. package/src/theme/native-theming-guard.test.ts +5 -5
  488. package/src/theme/presets/apply.ts +4 -0
  489. package/src/theme/presets/audiobook.ts +5 -2
  490. package/src/theme/presets/default.ts +4 -0
  491. package/src/theme/presets/index.ts +14 -1
  492. package/src/theme/presets/types.ts +1 -1
  493. package/src/theme/semantic-contrast.test.ts +13 -4
  494. package/src/theme/status-distinctness.test.ts +66 -0
  495. package/src/theme/subtle-tone-weight.test.ts +163 -0
  496. package/src/theme/surface-planes.test.ts +37 -0
  497. package/src/theme/surface-planes.ts +68 -0
  498. package/src/theme/tailwind-var-opacity.test.ts +163 -0
  499. package/src/theme/token-export-guard.test.ts +1 -3
  500. package/src/theme/tokens/primitives.test.ts +15 -7
  501. package/src/theme/tokens/primitives.ts +98 -33
  502. package/src/theme/tokens/semantic-hex-guard.test.ts +322 -0
  503. package/src/theme/tokens/semantic.ts +124 -54
  504. package/src/theme/wash-ladder.test.ts +58 -0
  505. package/src/theme/workout-tokens.ts +1 -7
  506. package/src/types/jest-axe.d.ts +2 -6
  507. package/src/types/raw-md.d.ts +5 -0
  508. package/src/utils/colors.alpha-adoption.test.ts +408 -0
  509. package/src/utils/colors.ts +4 -4
  510. package/src/utils/form.ts +1 -3
  511. package/src/utils/index.ts +2 -7
  512. package/src/utils/number-format.ts +17 -0
  513. package/src/utils/workout-format.ts +15 -6
  514. package/src/web-jsx/jsx-runtime.ts +1 -5
  515. package/tailwind.config.js +55 -9
  516. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
  517. package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
  518. package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
  519. package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
  520. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
  521. package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
  522. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
  523. package/src/components/shell/DashboardShell.stories.tsx +0 -65
  524. package/src/components/shell/DashboardShell.tsx +0 -75
  525. package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
  526. package/src/theme/elevation.stories.tsx +0 -346
  527. package/src/utils/useTheme.ts +0 -72
  528. /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
  529. /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
  530. /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
  531. /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
@@ -86,11 +86,50 @@ type props without pulling the dependency.
86
86
  └─ SetStrip
87
87
  └─ SetBar × N (one set's per-rep colour bar)
88
88
 
89
- ExerciseCard state="rail" ──delegates to──▶ ExerciseCardHeading
89
+ ExerciseCard (all three representations) ──delegates to──▶ ExerciseCardHeading
90
90
  ```
91
91
 
92
- `ExerciseCard`'s `rail` state is now a thin adapter that delegates to
93
- `ExerciseCardHeading` (so the heading is reusable without the card). `SetBar`
92
+ **TD-03.55 / TD-03.56 one row, three densities, and interaction states.**
93
+ `ExerciseCardHeading` IS the exercise row. Its `density` prop carries the only
94
+ axis that ever separated the three call sites:
95
+
96
+ | `density` | shape | was |
97
+ | ---------- | ------------------------------------------------------- | ---------------------------- |
98
+ | `rail` | two lines: name, then prescription beside the tempo | `ExerciseCardHeading` |
99
+ | `compact` | one line: name + prescription, strip below | `ExerciseCard`'s CollapsedCard |
100
+ | `upcoming` | `compact`, dimmed, previous best pinned right | `ExerciseCard`'s UpcomingCard |
101
+
102
+ `CollapsedCard` and `UpcomingCard` are deleted; `ExerciseCard` maps its props onto
103
+ the row, so **its own prop shape is unchanged** and no consumer migrates. Three
104
+ things converged in the process, each a consistency gain rather than a new idea:
105
+ the collapsed row's freeform `3×6 @ 175 lbs` caption became the shared
106
+ `SetsRepsLoad` line; its hand-rolled `VelocityStrip` + `PlaceholderStrip` row
107
+ became one `SetStrip` (so `velocityZones` no longer tints the collapsed glance —
108
+ the expanded header already ignored it); and `isPR` surfaces through the
109
+ `ExerciseIndicator` chip, which is what the expanded header already did.
110
+
111
+ The prescription is a **discriminated union**: either the structured
112
+ `sets`/`reps`/`load` triple, or a free-text `prescription` string for an exercise
113
+ whose numbers aren't loaded, or neither. Mixing them is a type error rather than a
114
+ half-rendered line.
115
+
116
+ Interaction states are `interactive-*` token washes on the row —
117
+ **press > selection > hover** — plus an `isLive` name tone (`status-live`). Every
118
+ one is static: this row renders on the wall during a set, where titan's "the grain
119
+ never animates" rule applies. Hover is web-only; RN Pressable's `onHoverIn` never
120
+ fires on a touch surface, so a touch consumer simply gets no hover state and
121
+ `isSelected` carries the same "this one" meaning. Selection has **no ARIA**:
122
+ `aria-selected` is not allowed on `role="button"`, so the wash is the whole signal
123
+ and list semantics stay the rail's job.
124
+
125
+ Two follow-ups are deliberately NOT taken here. The dim depths still differ by
126
+ density (rail 0.55, card 0.60) because they came from two specimens and converging
127
+ them needs an **opacity token the set does not have** — a foundations decision.
128
+ And `exerciseRowState.ts` (the `interactive-*` → literal-hex map, written in the
129
+ shape of `onSurfaceColors`) should be **promoted into the surface module** the
130
+ moment a second family needs row washes.
131
+
132
+ `SetBar`
94
133
  owns the per-set colour/pulse logic; `SetStrip` lays several side by side.
95
134
  Beyond the flat `done`/`active`/`todo` sets, `SetStripSet` models set-type
96
135
  prescriptions: `range` (variable rep-range — range-max segments, committed-todo grey
@@ -102,9 +141,13 @@ type props without pulling the dependency.
102
141
  (`SET_STRIP_VARIABLE_COLOR`) is the shared "variable / unknown / opportunity" pin.
103
142
  `SegmentedBar` carries these via additive `leadingGap` (per-segment left margin) and
104
143
  static `opacity` props — the flat sets stay byte-identical.
144
+ `active`/`todo` sets optionally carry the plan's prescribed rep RANGE (`repsLow`/
145
+ `repsHigh`, VMCP-03.04), rendered as a small label above the bar (`8–12`, or `8` when
146
+ equal/only one is given) via the shared `formatRepsRange` helper — independent of
147
+ `range`'s `floor`/`max` value range.
105
148
  `SetStrip`/`SetBar` colors are the real titan ramp pins (`primitiveRamps` red-600 /
106
- orange-400 / amber-300 / green-300); the rail surfaces bind to the charcoal ramp +
107
- a subtle neumorphic inset (`neumorphicShadows.charcoal.pressed.subtle`). The heading
149
+ orange-400 / amber-300 / green-300); the rail surfaces bind to the grey ramp and the
150
+ list is a well cut with the shared `insetWell` material. The heading
108
151
  design is locked in `sources/design/shell/S3-sessionrail/DECISIONS-ExerciseRow.md`; the
109
152
  exploration specimens live under `Custom/Workout/Explorations/*` (do not repoint yet).
110
153
  In Storybook the family nests by composition under **`Shell/SessionRail/…`**
@@ -126,7 +169,7 @@ type props without pulling the dependency.
126
169
  array (unchanged, still the source of truth for `SetRow` / `ExerciseCard`), the
127
170
  strip accepts an optional structured `VelocitySet` descriptor and renders the
128
171
  strength set-type vocabulary as a typed slot list. Slots are
129
- `rep` (velocity-coloured) · `todo` (charcoal-300 grey) · `variable` /
172
+ `rep` (velocity-coloured) · `todo` (`border-prominent` grey) · `variable` /
130
173
  `continue` (`SET_STRIP_VARIABLE_COLOR` cyan-900; `continue` adds a cyan-800
131
174
  outline to read as "keep going"). Types: `straight` (done + grey todo to
132
175
  `planned`), `range` (committed grey + a cyan variable window `floor..max`),
@@ -178,14 +221,22 @@ Modalities`** (each card carries a `Collapse` accordion; promoted from the
178
221
  when neither side carries one the gutter is omitted entirely. The label keeps the prior
179
222
  vertical (rotated) orientation so it never overlaps the bars. Two scales: `hero` (tall
180
223
  wings, per-rep m/s velocity labels, a dashed running-best reference line per side) and
181
- `rail` (compact — no velocity labels / reference lines, slot names in a narrow gutter).
182
- **Rep-index alignment is the invariant:** column *i* is rep *i* on
183
- both sides, so the set-type slot *kinds* carry through (rep / todo / variable / continue,
224
+ `dual-expanded` (compact — no velocity labels / reference lines, slot names in a narrow
225
+ gutter).
226
+ **Rep-index alignment is the invariant:** column _i_ is rep _i_ on
227
+ both sides, so the set-type slot _kinds_ carry through (rep / todo / variable / continue,
184
228
  coloured as in the single strip) but the wide-notch chunk **gaps** (drop / myo / cluster
185
229
  boundaries) are intentionally NOT rendered — per-side horizontal gaps would break the
186
230
  mirrored L↔R column alignment. Single-voltra sets keep using `VelocityStrip`
187
- `variant="hero"`. Documented by the `Playground` / `Hero*` / `Rail` stories on the wall
188
- background (`Workout/DataViz/DualVelocityStrip`).
231
+ `variant="hero"`. Documented by the `Playground` / `Hero*` / `DualExpanded` stories on the
232
+ wall background (`Custom/Workout/DataViz/DualVelocityStrip`).
233
+
234
+ **`variant="rail"` → `variant="dual-expanded"` (VW-97).** `rail` was a verified misnomer —
235
+ this variant is the value-height strip a session-rail row _expands into_, not the rail
236
+ itself (the rail stays 246px and never changes width; expansion lives in a separate detail
237
+ pane, per the VW-97 rail-width decision). `rail` is kept as a **deprecated alias** for one
238
+ release (same renderer, same output) so existing call sites keep working; migrate to
239
+ `dual-expanded` and expect `rail` to be removed in a future release.
189
240
 
190
241
  **Reuse audit — `DashedReferenceLine` (in-file today, top-level follow-up).** The dashed
191
242
  running-best line was hand-rolled three times inside `VelocityStrip.tsx` (the single
@@ -199,6 +250,7 @@ Modalities`** (each card carries a `Collapse` accordion; promoted from the
199
250
  a follow-up so the hero PR stays focused (the cross-file migration touches `Sparkline`'s
200
251
  test surface and the Lab specimens, which are out of this branch's scope). Proposed API:
201
252
  `<ReferenceLine anchor offset color dashed opacity? label? testID />`.
253
+
202
254
  - **RestTimer `ring` variant** — the across-the-room **wall** rest treatment (the
203
255
  north-star rest page). Built as a **three-tier decomposition** (not a one-off):
204
256
  `CircularProgress` (atom, gained a **`children`** center slot + a **`fill`**
@@ -215,7 +267,7 @@ Modalities`** (each card carries a `Collapse` accordion; promoted from the
215
267
  hides the shared `RestActions` (+30s/Skip, extracted, used by both variants);
216
268
  `size` (default 180) sets the diameter; the eyebrow/section title is organism
217
269
  chrome. Web/RNW-only (like `CircularProgress`) — the wall variant; mobile keeps
218
- `bar`. `Ring*` (RestTimer) + `Custom/CircularTimer` stories on the wall background.
270
+ `bar`. `Ring*` (RestTimer) + `Components/Molecules/CircularTimer` stories on the wall background.
219
271
  - **`size="wall"` density (FatigueMeter · ZoneTrack)** — the across-the-room
220
272
  dashboard scale, added as the idiomatic titan `size` union (a JS number-map per
221
273
  component; **`default` values are byte-identical** to before, so existing consumers are
@@ -298,8 +350,7 @@ responsive level views land (removal is out of scope for this scaffold ticket):
298
350
  (Workout Expansion), `S3SetTypes` (Set Types), `S3SessionPace` (Session Pace).
299
351
  Each is superseded by a real Shell/SessionRail component + its Storybook stories;
300
352
  `S3SessionPace` in particular is superseded by the `SessionHeader` pace glance.
301
- - **`ExerciseCard`'s `collapsed` / `upcoming` state representations** — the rail now
302
- owns the live-list heading (`rail` state `ExerciseCardHeading`) and the expanded
303
- view is moving to `ExpandedDrawer`. Once the responsive unification (TD-03.56)
304
- lands a single responsive card, the `collapsed`/`upcoming` branches of
305
- `ExerciseCard` are the superseded representations to retire.
353
+ - **`ExerciseCard`'s `collapsed` / `upcoming` state representations** — DONE
354
+ (TD-03.56). Both hand-rolled sub-cards are deleted; `ExerciseCard` now delegates
355
+ all three representations to `ExerciseCardHeading` and its `density` prop. What
356
+ remains to retire is the expanded view, which is moving to `ExpandedDrawer`.
@@ -16,8 +16,9 @@ const staticFactors: ReadinessFactor[] = FACTOR_SEED.map((f) => ({
16
16
  }))
17
17
 
18
18
  const meta: Meta<typeof ReadinessCheck> = {
19
- title: 'Workout/ReadinessCheck',
19
+ title: 'Custom/Workout/ReadinessCheck',
20
20
  component: ReadinessCheck,
21
+ parameters: { docs: { description: { component: 'Composes **Card** · **Badge**.' } } },
21
22
  tags: ['autodocs'],
22
23
  argTypes: {
23
24
  score: {
@@ -89,7 +90,7 @@ export const WithWarmUpCaution: Story = {
89
90
 
90
91
  function InteractiveReadinessCheck() {
91
92
  const [values, setValues] = useState<Record<string, number>>(
92
- Object.fromEntries(FACTOR_SEED.map((f) => [f.id, f.value])),
93
+ Object.fromEntries(FACTOR_SEED.map((f) => [f.id, f.value]))
93
94
  )
94
95
 
95
96
  const factors: ReadinessFactor[] = FACTOR_SEED.map((f) => ({
@@ -22,9 +22,7 @@ describe('ReadinessCheck', () => {
22
22
  describe('rendering', () => {
23
23
  it('renders the title and one row per factor', () => {
24
24
  render(<ReadinessCheck {...baseProps} factors={makeFactors()} />)
25
- expect(screen.getByTestId('readiness-check-title')).toHaveTextContent(
26
- 'How are you feeling?',
27
- )
25
+ expect(screen.getByTestId('readiness-check-title')).toHaveTextContent('How are you feeling?')
28
26
  expect(screen.getByTestId('readiness-check-factor-sleep')).toBeInTheDocument()
29
27
  expect(screen.getByTestId('readiness-check-factor-stress')).toBeInTheDocument()
30
28
  })
@@ -78,7 +76,7 @@ describe('ReadinessCheck', () => {
78
76
  {...baseProps}
79
77
  factors={makeFactors()}
80
78
  warmUpValidation={{ velocityDeficit: 5, recommendation: 'OK', status: 'good' }}
81
- />,
79
+ />
82
80
  )
83
81
  expect(screen.queryByTestId('readiness-check-warmup')).not.toBeInTheDocument()
84
82
  })
@@ -94,13 +92,13 @@ describe('ReadinessCheck', () => {
94
92
  recommendation: 'Reduce load today.',
95
93
  status: 'caution',
96
94
  }}
97
- />,
95
+ />
98
96
  )
99
97
  expect(screen.getByTestId('readiness-check-warmup-deficit')).toHaveTextContent(
100
- '18% below 14-day average',
98
+ '18% below 14-day average'
101
99
  )
102
100
  expect(screen.getByTestId('readiness-check-warmup-recommendation')).toHaveTextContent(
103
- 'Reduce load today.',
101
+ 'Reduce load today.'
104
102
  )
105
103
  expect(screen.getByTestId('readiness-check-warmup-badge')).toHaveTextContent('Caution')
106
104
  })
@@ -112,10 +110,10 @@ describe('ReadinessCheck', () => {
112
110
  factors={makeFactors()}
113
111
  warmUpCompleted
114
112
  warmUpValidation={{ velocityDeficit: 0, recommendation: 'Proceed.', status: 'good' }}
115
- />,
113
+ />
116
114
  )
117
115
  expect(screen.getByTestId('readiness-check-warmup-deficit')).toHaveTextContent(
118
- 'Velocity on 14-day average',
116
+ 'Velocity on 14-day average'
119
117
  )
120
118
  })
121
119
 
@@ -126,10 +124,10 @@ describe('ReadinessCheck', () => {
126
124
  factors={makeFactors()}
127
125
  warmUpCompleted
128
126
  warmUpValidation={{ velocityDeficit: -6, recommendation: 'Proceed.', status: 'good' }}
129
- />,
127
+ />
130
128
  )
131
129
  expect(screen.getByTestId('readiness-check-warmup-deficit')).toHaveTextContent(
132
- 'Velocity 6% above 14-day average',
130
+ 'Velocity 6% above 14-day average'
133
131
  )
134
132
  })
135
133
  })
@@ -149,15 +147,11 @@ describe('ReadinessCheck', () => {
149
147
 
150
148
  it('exposes the readiness score on the gauge', () => {
151
149
  render(<ReadinessCheck {...baseProps} factors={makeFactors()} score={78} />)
152
- expect(
153
- screen.getByLabelText('Readiness score: 78 out of 100'),
154
- ).toBeInTheDocument()
150
+ expect(screen.getByLabelText('Readiness score: 78 out of 100')).toBeInTheDocument()
155
151
  })
156
152
 
157
153
  it('has no accessibility violations', async () => {
158
- const { container } = render(
159
- <ReadinessCheck {...baseProps} factors={makeFactors()} />,
160
- )
154
+ const { container } = render(<ReadinessCheck {...baseProps} factors={makeFactors()} />)
161
155
  expect(await axe(container)).toHaveNoViolations()
162
156
  })
163
157
 
@@ -173,7 +167,7 @@ describe('ReadinessCheck', () => {
173
167
  status: 'moderate',
174
168
  }}
175
169
  onConfirm={vi.fn()}
176
- />,
170
+ />
177
171
  )
178
172
  expect(await axe(container)).toHaveNoViolations()
179
173
  })
@@ -3,11 +3,13 @@ import { View, Text, Pressable } from 'react-native'
3
3
  import { Card } from '../../ui/card'
4
4
  import { Badge, type BadgeColor } from '../../ui/badge'
5
5
  import { getSemanticColors } from '../../../theme/tokens/semantic'
6
+ import { alpha } from '../../../utils/colors'
6
7
 
7
8
  const t = getSemanticColors('dark')
8
9
 
9
10
  const BRAND_PRIMARY = t['brand-primary']
10
- const BRAND_PRIMARY_SUBTLE = 'rgba(255,121,0,0.12)'
11
+ const ON_BRAND_PRIMARY = t['on-brand-primary']
12
+ const BRAND_PRIMARY_SUBTLE = alpha(BRAND_PRIMARY, 0.12)
11
13
  const STATUS_SUCCESS = t['status-success']
12
14
  const STATUS_WARNING = t['status-warning']
13
15
  const STATUS_ERROR = t['status-error']
@@ -71,7 +73,11 @@ const WARMUP_BADGE: Record<WarmUpStatus, { color: BadgeColor; label: string }> =
71
73
  }
72
74
 
73
75
  function emojiSet(factor: ReadinessFactor): readonly string[] {
74
- return EMOJI_SETS[factor.id.toLowerCase()] ?? EMOJI_SETS[factor.label.toLowerCase()] ?? DEFAULT_EMOJI_SET
76
+ return (
77
+ EMOJI_SETS[factor.id.toLowerCase()] ??
78
+ EMOJI_SETS[factor.label.toLowerCase()] ??
79
+ DEFAULT_EMOJI_SET
80
+ )
75
81
  }
76
82
 
77
83
  /** Warm-up velocity phrasing. Deficit is % below the 14-day average, so a
@@ -158,7 +164,12 @@ function ScoreGauge({ score }: { score: number }) {
158
164
  }}
159
165
  >
160
166
  <Text
161
- style={{ fontSize: 20, fontWeight: '700', fontFamily: '"Space Grotesk", sans-serif', color }}
167
+ style={{
168
+ fontSize: 20,
169
+ fontWeight: '700',
170
+ fontFamily: '"Space Grotesk", sans-serif',
171
+ color,
172
+ }}
162
173
  testID="readiness-check-score-value"
163
174
  >
164
175
  {score}
@@ -260,7 +271,14 @@ export function ReadinessCheck({
260
271
  opacity: pressed ? 0.8 : 1,
261
272
  })}
262
273
  >
263
- <Text style={{ fontSize: 13, fontWeight: '700', fontFamily: 'Inter, sans-serif', color: '#FFFFFF' }}>
274
+ <Text
275
+ style={{
276
+ fontSize: 13,
277
+ fontWeight: '700',
278
+ fontFamily: 'Inter, sans-serif',
279
+ color: ON_BRAND_PRIMARY,
280
+ }}
281
+ >
264
282
  Start Workout
265
283
  </Text>
266
284
  </Pressable>
@@ -1,9 +1,13 @@
1
1
  import type { Decorator, Meta, StoryObj } from '@storybook/react-vite'
2
2
  import { View, Text } from 'react-native'
3
3
  import { RestTimer } from './RestTimer'
4
+ import { greyRamp } from '../../../theme/tokens/primitives'
5
+ import { getSemanticColors } from '../../../theme/tokens/semantic'
6
+
7
+ const t = getSemanticColors('dark')
4
8
 
5
9
  const meta: Meta<typeof RestTimer> = {
6
- title: 'Workout/RestTimer',
10
+ title: 'Custom/Workout/RestTimer',
7
11
  component: RestTimer,
8
12
  tags: ['autodocs'],
9
13
  parameters: {
@@ -16,7 +20,8 @@ const meta: Meta<typeof RestTimer> = {
16
20
  'across-the-room wall treatment: a draining countdown ring (composes `CircularProgress`) ' +
17
21
  'with the mm:ss countdown in its center, flipping to a full `success` ring reading "GO" ' +
18
22
  'when rest is up. `displayOnly` hides the +30s/Skip controls in either variant; `size` ' +
19
- 'sets the ring diameter.',
23
+ 'sets the ring diameter.' +
24
+ ' Composes **CircularTimer**.',
20
25
  },
21
26
  },
22
27
  },
@@ -99,10 +104,17 @@ export const JustStarted: Story = {
99
104
 
100
105
  /** Wall-background frame for the ring stories (mirrors the north-star rest page). */
101
106
  const ringDecorator: Decorator = (Story) => (
102
- <View style={{ width: 420, padding: 32, alignItems: 'center', backgroundColor: '#0E0E0E' }}>
107
+ <View
108
+ style={{
109
+ width: 420,
110
+ padding: 32,
111
+ alignItems: 'center',
112
+ backgroundColor: t['background-frame'],
113
+ }}
114
+ >
103
115
  <Text
104
116
  style={{
105
- color: '#5A5A5A',
117
+ color: greyRamp[700],
106
118
  fontSize: 10,
107
119
  fontWeight: '700',
108
120
  letterSpacing: 1,
@@ -2,6 +2,8 @@
2
2
  import { View, Text, Pressable } from 'react-native'
3
3
  import { resolveColor } from '../../../theme/resolve-color'
4
4
  import { getSemanticColors } from '../../../theme/tokens/semantic'
5
+ import { primitiveColors } from '../../../theme/tokens/primitives'
6
+ import { alpha } from '../../../utils/colors'
5
7
  import { useTimer } from '../../../hooks/useTimer'
6
8
  import { CircularTimer } from '../CircularTimer/CircularTimer'
7
9
 
@@ -37,7 +39,7 @@ function RestActions({ onAddTime, onSkip }: { onAddTime: () => void; onSkip: ()
37
39
  <Pressable
38
40
  onPress={onAddTime}
39
41
  style={{
40
- backgroundColor: 'rgba(255,255,255,0.06)',
42
+ backgroundColor: alpha(primitiveColors.white, 0.06),
41
43
  paddingVertical: 8,
42
44
  paddingHorizontal: 20,
43
45
  borderRadius: 8,
@@ -56,7 +58,7 @@ function RestActions({ onAddTime, onSkip }: { onAddTime: () => void; onSkip: ()
56
58
  <Pressable
57
59
  onPress={onSkip}
58
60
  style={{
59
- backgroundColor: 'rgba(255,121,0,0.12)',
61
+ backgroundColor: alpha(BRAND_PRIMARY, 0.12),
60
62
  paddingVertical: 8,
61
63
  paddingHorizontal: 20,
62
64
  borderRadius: 8,
@@ -9,14 +9,15 @@ const DAY = 24 * HOUR
9
9
  const NOW = Date.now()
10
10
 
11
11
  const meta: Meta<typeof ScheduleTiles> = {
12
- title: 'Workout/ScheduleTiles',
12
+ title: 'Custom/Workout/ScheduleTiles',
13
13
  component: ScheduleTiles,
14
14
  tags: ['autodocs'],
15
15
  parameters: {
16
16
  docs: {
17
17
  description: {
18
18
  component:
19
- '**Molecule.** An HStack of [Tile](?path=/docs/components-atoms-tile--docs); Until reuses [DateTime](?path=/docs/custom-datetime--docs) relative. Used-by ↑ SessionHeader.',
19
+ '**Molecule.** An HStack of [Tile](?path=/docs/components-atoms-tile--docs); Until reuses [DateTime](?path=/docs/custom-datetime--docs) relative. Used-by ↑ SessionHeader.' +
20
+ ' Composes **HStack** · **Tile**.',
20
21
  },
21
22
  },
22
23
  },
@@ -1,11 +1,10 @@
1
1
  import { describe, it, expect } from 'vitest'
2
2
  import { render, screen } from '@testing-library/react'
3
3
  import { ScheduleTiles, compactUntil } from './ScheduleTiles'
4
- import { primitiveRamps } from '../../../theme/tokens/primitives'
4
+ import { resolveColor } from '../../../theme/resolve-color'
5
5
 
6
6
  const HOUR = 60 * 60 * 1000
7
7
  const DAY = 24 * HOUR
8
- const ORANGE = primitiveRamps.orange[400]
9
8
 
10
9
  // A fixed reference; the compact Until label is deterministic from (when - now).
11
10
  const NOW = Date.now()
@@ -25,10 +24,10 @@ describe('ScheduleTiles', () => {
25
24
  expect(value.style.color).toBe('')
26
25
  })
27
26
 
28
- it('accents the Until value orange when less than a day away', () => {
27
+ it('accents the Until value with the brand token when less than a day away', () => {
29
28
  const when = NOW + 5 * HOUR
30
29
  render(<ScheduleTiles now={NOW} when={when} />)
31
30
  const value = screen.getByText(compactUntil(when - NOW))
32
- expect(value).toHaveStyle({ color: ORANGE })
31
+ expect(value).toHaveStyle({ color: resolveColor('brand-primary') })
33
32
  })
34
33
  })
@@ -1,15 +1,12 @@
1
1
  import { useState } from 'react'
2
2
  import { type ViewProps } from 'react-native'
3
- import { primitiveRamps } from '../../../theme/tokens/primitives'
3
+ import { resolveColor } from '../../../theme/resolve-color'
4
4
  import { HStack } from '../../ui/stack'
5
5
  import { Tile } from '../../ui/tile/Tile'
6
6
  import { formatDateTime } from '../DateTime/DateTime'
7
7
 
8
8
  const DAY_MS = 24 * 60 * 60 * 1000
9
9
 
10
- /** Accent applied to the Until value when the session is < 1 day away. */
11
- const SOON_ACCENT = primitiveRamps.orange[400]
12
-
13
10
  /** Compact time-until label: `30m` / `5h` / `2d` / `3w`. Deterministic from the delta. */
14
11
  export function compactUntil(ms: number): string {
15
12
  if (ms <= 0) return 'now'
@@ -37,8 +34,8 @@ export interface ScheduleTilesProps extends ViewProps {
37
34
  * ScheduleTiles — Date / Time / Until row for an upcoming session.
38
35
  *
39
36
  * An HStack of three {@link Tile}s derived from a single scheduled moment. The
40
- * Until value reuses {@link formatDateTime} relative formatting and turns
41
- * accent-orange only when the session is less than a day away.
37
+ * Until value reuses {@link formatDateTime} relative formatting and takes the
38
+ * `brand-primary` accent only when the session is less than a day away.
42
39
  *
43
40
  * @example
44
41
  * <ScheduleTiles when={Date.now() + 5 * 60 * 60 * 1000} />
@@ -63,7 +60,7 @@ export function ScheduleTiles({ when, now, gap = 1, ...props }: ScheduleTilesPro
63
60
  <Tile
64
61
  label="Until"
65
62
  value={compactUntil(whenMs - reference)}
66
- valueColor={soon ? SOON_ACCENT : undefined}
63
+ valueColor={soon ? resolveColor('brand-primary') : undefined}
67
64
  />
68
65
  </HStack>
69
66
  )
@@ -1,6 +1,10 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite'
2
- import { View } from 'react-native'
3
2
  import { SegmentedBar } from './SegmentedBar'
3
+ import { Surface } from '../../ui/surface'
4
+ import { primitiveColors, primitiveRamps } from '../../../theme/tokens/primitives'
5
+ import { getSemanticColors } from '../../../theme/tokens/semantic'
6
+
7
+ const t = getSemanticColors('dark')
4
8
 
5
9
  /**
6
10
  * `SegmentedBar` — a horizontal track split into weighted, individually-fillable
@@ -9,7 +13,7 @@ import { SegmentedBar } from './SegmentedBar'
9
13
  * vertical line at a fraction of the width. Colours are passed-in literal hex.
10
14
  */
11
15
  const meta: Meta<typeof SegmentedBar> = {
12
- title: 'Workout/SegmentedBar',
16
+ title: 'Custom/Workout/SegmentedBar',
13
17
  component: SegmentedBar,
14
18
  tags: ['autodocs'],
15
19
  parameters: {
@@ -19,7 +23,7 @@ const meta: Meta<typeof SegmentedBar> = {
19
23
  '**Atom.** A horizontal track split into weighted, individually-fillable ' +
20
24
  'segments (weight · fill · colour · pulse) with an optional marker line — the ' +
21
25
  'presentational primitive the per-set strips build on. ' +
22
- 'Used-by ↑ [SetStrip](?path=/docs/workout-setstrip--docs).',
26
+ 'Used-by ↑ [SetStrip](?path=/docs/custom-workout-setstrip--docs).',
23
27
  },
24
28
  },
25
29
  },
@@ -30,9 +34,9 @@ const meta: Meta<typeof SegmentedBar> = {
30
34
  },
31
35
  decorators: [
32
36
  (Story) => (
33
- <View style={{ width: 240, padding: 16, backgroundColor: '#131313' }}>
37
+ <Surface level="base" style={{ width: 240, padding: 16 }}>
34
38
  <Story />
35
- </View>
39
+ </Surface>
36
40
  ),
37
41
  ],
38
42
  }
@@ -44,10 +48,10 @@ export const EqualSegments: Story = {
44
48
  args: {
45
49
  height: 8,
46
50
  segments: [
47
- { color: '#D14343' },
48
- { color: '#FF7900' },
49
- { color: '#F9B415' },
50
- { color: '#2ED573' },
51
+ { color: primitiveRamps.red[600] },
52
+ { color: t['brand-primary'] },
53
+ { color: t['status-warning'] },
54
+ { color: t['status-success'] },
51
55
  ],
52
56
  },
53
57
  }
@@ -58,9 +62,9 @@ export const Weighted: Story = {
58
62
  gap: 4,
59
63
  radius: 2,
60
64
  segments: [
61
- { color: '#2ED573', weight: 3 },
62
- { color: '#F9B415', weight: 2 },
63
- { color: '#D14343', weight: 1 },
65
+ { color: t['status-success'], weight: 3 },
66
+ { color: t['status-warning'], weight: 2 },
67
+ { color: primitiveRamps.red[600], weight: 1 },
64
68
  ],
65
69
  },
66
70
  parameters: {
@@ -74,9 +78,9 @@ export const PartialFills: Story = {
74
78
  gap: 4,
75
79
  radius: 2,
76
80
  segments: [
77
- { color: '#2ED573', fill: 1 },
78
- { color: '#F9B415', fill: 0.6 },
79
- { color: '#01B5D1', fill: 0.3, pulse: true },
81
+ { color: t['status-success'], fill: 1 },
82
+ { color: t['status-warning'], fill: 0.6 },
83
+ { color: primitiveRamps.cyan[400], fill: 0.3, pulse: true },
80
84
  ],
81
85
  },
82
86
  parameters: {
@@ -90,8 +94,8 @@ export const WithMarker: Story = {
90
94
  args: {
91
95
  height: 10,
92
96
  radius: 2,
93
- segments: [{ color: '#01B5D1', fill: 0.7 }],
94
- marker: { position: 0.5, color: '#FFFFFF' },
97
+ segments: [{ color: primitiveRamps.cyan[400], fill: 0.7 }],
98
+ marker: { position: 0.5, color: primitiveColors.white },
95
99
  },
96
100
  parameters: {
97
101
  docs: { description: { story: 'A single fill with a target marker at the halfway point.' } },
@@ -1,6 +1,7 @@
1
1
  // Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
2
2
  import { useEffect, useState } from 'react'
3
3
  import { View, Animated, Easing, type ViewProps, type DimensionValue } from 'react-native'
4
+ import { SET_LEVEL_FLAT_BAR } from '../charts/flatBarGeometry'
4
5
 
5
6
  /** ~1.9s full cycle: a pulsing segment eases up then back down (2 × half). */
6
7
  const PULSE_HALF_MS = 950
@@ -9,20 +10,23 @@ const PULSE_HALF_MS = 950
9
10
  const PULSE_MIN_OPACITY = 0.45
10
11
 
11
12
  /** Default between-segment gap — matches SetStrip's between-set gap so strips read the same. */
12
- const SEGMENTED_BAR_GAP = 5
13
+ const SEGMENTED_BAR_GAP = SET_LEVEL_FLAT_BAR.gap
13
14
 
14
15
  export interface SegmentedBarSegment {
15
16
  /** Flex weight of this segment's slot. Default 1 (all segments equal width). */
16
17
  weight?: number
17
18
  /** Fraction 0..1 of the slot the coloured fill covers, left-aligned. Default 1 (full). */
18
19
  fill?: number
19
- /** Fill colour — a literal hex (RNW-safe), never a `var()` token ref. */
20
+ /** Fill colour. Pass `resolveColor(token)` — a plain fill takes a `var()` ref fine. */
20
21
  color: string
21
22
  /** When true the fill animates on the shared active-pulse loop. */
22
23
  pulse?: boolean
23
24
  /**
24
25
  * When pulsing, interpolate the fill's `backgroundColor` from→to over the loop
25
26
  * (full opacity). Omit to fall back to the default opacity breathe.
27
+ *
28
+ * Literal hex only: `Animated.interpolate` parses these two endpoints itself
29
+ * and cannot read a `var()` ref, so `resolveColor(token)` does not work here.
26
30
  */
27
31
  pulseColor?: [from: string, to: string]
28
32
  /**
@@ -90,13 +94,14 @@ function usePulse(active: boolean): Animated.Value {
90
94
  * presentational atom the per-set strips are built from. Each segment is a flex
91
95
  * slot (flex = `weight`) holding a left-aligned fill (`fill` fraction, `color`);
92
96
  * `pulse` segments breathe on a shared active-pulse loop, and `marker` drops a
93
- * vertical line at a fraction of the total width. Colours are passed-in literal hex.
97
+ * vertical line at a fraction of the total width. Every colour is injected by the
98
+ * composer, so this atom holds no palette of its own.
94
99
  */
95
100
  export function SegmentedBar({
96
101
  segments,
97
- height = 8,
102
+ height = SET_LEVEL_FLAT_BAR.height,
98
103
  gap = SEGMENTED_BAR_GAP,
99
- radius = 2,
104
+ radius = SET_LEVEL_FLAT_BAR.radius,
100
105
  marker = null,
101
106
  segmentTestID,
102
107
  style,
@@ -1,27 +1,27 @@
1
1
  // Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
2
2
  import type { Meta, StoryObj } from '@storybook/react-vite'
3
- import { View } from 'react-native'
4
3
  import { SegmentedProgressBar } from './SegmentedProgressBar'
4
+ import { Surface } from '../../ui/surface'
5
5
 
6
6
  const PLAN = [{ weight: 3 }, { weight: 3 }, { weight: 2 }, { weight: 2 }, { weight: 2 }]
7
7
 
8
8
  const meta: Meta<typeof SegmentedProgressBar> = {
9
- title: 'Workout/SegmentedProgressBar',
9
+ title: 'Custom/Workout/SegmentedProgressBar',
10
10
  component: SegmentedProgressBar,
11
11
  tags: ['autodocs'],
12
12
  parameters: {
13
13
  docs: {
14
14
  description: {
15
15
  component:
16
- '**Atom.** Composes [SegmentedBar](?path=/docs/workout-segmentedbar--docs) + paceTone. Used-by ↑ SessionHeader.',
16
+ '**Atom.** Composes [SegmentedBar](?path=/docs/custom-workout-segmentedbar--docs) + paceTone. Used-by ↑ SessionHeader.',
17
17
  },
18
18
  },
19
19
  },
20
20
  decorators: [
21
21
  (Story) => (
22
- <View style={{ width: 246, padding: 16, backgroundColor: '#242424' }}>
22
+ <Surface level="base" style={{ width: 246, padding: 16 }}>
23
23
  <Story />
24
- </View>
24
+ </Surface>
25
25
  ),
26
26
  ],
27
27
  }