@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
@@ -1,95 +0,0 @@
1
- /**
2
- * SHEET · Session Pace — the rail-footer pace tile (NAV-D05: VMCP-primary, plan-aware trim/add).
3
- * PRESENTATIONAL only; the derivation (session time-model + trim/add heuristic) is a separate VMCP/WA
4
- * ticket (no WA support today). OPEN: which metrics earn the row · behind/ahead visual · idle treatment ·
5
- * whether it restores a CapacityBandChart. See DECISIONS-ExerciseRow doc.
6
- */
7
- import type { Meta, StoryObj } from '@storybook/react-vite'
8
- import type { ReactNode } from 'react'
9
- import { AMBER, GREEN, INSET, RAISED, T_PRIMARY, T_SECONDARY, T_TERTIARY, ORANGE, Page, monoTag } from './setHeadingKit'
10
-
11
- type PaceState = 'behind' | 'ahead' | 'idle'
12
-
13
- function Metric({ k, v, color }: { k: string; v: string; color?: string }) {
14
- return (
15
- <div style={{ flex: 1, textAlign: 'center', background: RAISED, borderRadius: 7, padding: '6px 3px' }}>
16
- <div style={{ fontSize: 8, textTransform: 'uppercase', letterSpacing: 0.4, color: T_TERTIARY, fontWeight: 800 }}>{k}</div>
17
- <div style={{ fontFamily: 'monospace', fontSize: 13, fontWeight: 800, marginTop: 2, color: color ?? T_PRIMARY }}>{v}</div>
18
- </div>
19
- )
20
- }
21
- function Suggest({ tone, children }: { tone: 'behind' | 'ahead'; children: ReactNode }) {
22
- const color = tone === 'behind' ? AMBER : GREEN
23
- return (
24
- <div style={{ fontSize: 10.5, lineHeight: 1.4, borderRadius: 8, padding: '8px 9px', display: 'flex', gap: 7, alignItems: 'flex-start', color, background: tone === 'behind' ? 'rgba(249,180,21,0.10)' : 'rgba(46,213,115,0.10)', border: `1px solid ${tone === 'behind' ? 'rgba(249,180,21,0.30)' : 'rgba(46,213,115,0.28)'}` }}>
25
- <span style={{ flex: '0 0 auto', fontSize: 12 }}>{tone === 'behind' ? '▲' : '+'}</span>
26
- <div>{children}</div>
27
- </div>
28
- )
29
- }
30
- const b = (t: string) => <b style={{ color: T_PRIMARY }}>{t}</b>
31
-
32
- // The pace tile — lives pinned in the rail footer (inset surface).
33
- function SessionPaceTile({ state }: { state: PaceState }) {
34
- if (state === 'idle') {
35
- return (
36
- <div style={{ width: 246, background: INSET, borderTop: `1px solid #1C1C1C`, padding: '11px 12px', display: 'flex', flexDirection: 'column', gap: 8 }}>
37
- <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: 0.6, textTransform: 'uppercase', color: ORANGE }}>Next session budget</div>
38
- <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, fontFamily: 'monospace' }}>
39
- <span style={{ fontSize: 20, fontWeight: 800, color: T_PRIMARY }}>~52:00</span>
40
- <span style={{ fontSize: 11, color: T_SECONDARY }}>planned · Lower B</span>
41
- </div>
42
- <Suggest tone="ahead">6 exercises · ~20 sets. Wall wakes to Live when the first set streams.</Suggest>
43
- </div>
44
- )
45
- }
46
- const behind = state === 'behind'
47
- return (
48
- <div style={{ width: 246, background: INSET, borderTop: `1px solid #1C1C1C`, padding: '11px 12px', display: 'flex', flexDirection: 'column', gap: 8 }}>
49
- <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
50
- <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: 0.6, textTransform: 'uppercase', color: ORANGE }}>Session Pace</span>
51
- <span style={{ fontSize: 8, fontFamily: 'monospace', color: T_TERTIARY, border: `1px solid #2C2C2C`, borderRadius: 5, padding: '2px 5px' }}>{behind ? 'show ahead ▸' : 'show behind ▸'}</span>
52
- </div>
53
- <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, fontFamily: 'monospace' }}>
54
- <span style={{ fontSize: 20, fontWeight: 800, color: T_PRIMARY }}>42:18</span>
55
- <span style={{ fontSize: 11, color: T_SECONDARY }}>of 60:00 budget</span>
56
- </div>
57
- <div style={{ height: 6, borderRadius: 3, background: '#22252c', position: 'relative', overflow: 'hidden' }}>
58
- <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: '70%', borderRadius: 3, background: behind ? AMBER : GREEN }} />
59
- </div>
60
- <div style={{ display: 'flex', gap: 4 }}>
61
- <Metric k="Volume" v="76%" />
62
- <Metric k="Load" v="7.3k" />
63
- <Metric k="Fatigue" v="MOD" color={AMBER} />
64
- </div>
65
- {behind ? (
66
- <Suggest tone="behind">{b('Behind pace')} — ~9 min over budget at this rate. Drop {b('Face Pull')} to 2 sets to finish on time.</Suggest>
67
- ) : (
68
- <Suggest tone="ahead">{b('Ahead of pace')} — ~7 min of headroom. Room to add a {b('Cable Fly')} drop-set or a back-off set on Row.</Suggest>
69
- )}
70
- </div>
71
- )
72
- }
73
-
74
- const meta: Meta = { title: 'Lab/Explorations/Session Pace', parameters: { layout: 'fullscreen' } }
75
- export default meta
76
- type Story = StoryObj
77
-
78
- export const States: Story = {
79
- name: 'Pace tile · behind / ahead / idle',
80
- render: () => (
81
- <Page
82
- title="Session Pace — rail footer tile"
83
- note="VMCP-primary (NAV-D05): behind → what to trim · ahead → what to add · idle → next-session budget. Presentational; derivation is a separate VMCP/WA ticket (no WA session time-model today). Surfaces on real tokens."
84
- >
85
- <div style={{ display: 'flex', gap: 32, flexWrap: 'wrap' }}>
86
- {(['behind', 'ahead', 'idle'] as PaceState[]).map((s) => (
87
- <div key={s} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
88
- <span style={monoTag}>{s}</span>
89
- <SessionPaceTile state={s} />
90
- </div>
91
- ))}
92
- </div>
93
- </Page>
94
- ),
95
- }
@@ -1,61 +0,0 @@
1
- /**
2
- * SHEET · Session Rail Heading — the always-shown exercise heading unit, in isolation.
3
- * Locked: name row + indicator · tight sets/reps/load (tempo language) + tempo · per-set segmented strip
4
- * (completed colored · active pulse + grey remainder · upcoming grey). OPEN: strip height · indicator taxonomy
5
- * · rep-range treatment · set-types (drop/myo). See DECISIONS-ExerciseRow doc.
6
- */
7
- import type { Meta, StoryObj } from '@storybook/react-vite'
8
- import { Heading, INSET, INSET_SHADOW, Page, monoTag, reps, type Exercise } from './setHeadingKit'
9
-
10
- const DONE: Exercise = { name: 'Seated Cable Row', sets: 5, reps: 8, load: 145, tempo: [3, 1, 2, 0], indicator: 'pr', setStates: [1.0, 0.9, 0.8, 0.7, 0.6].map((s) => ({ status: 'done', reps: reps(8, s) })) }
11
- const ACTIVE: Exercise = { name: 'Cable Chest Press', sets: 3, reps: 10, load: 90, tempo: [2, 1, 2, 0], indicator: 'info', setStates: [{ status: 'done', reps: reps(10, 0.72) }, { status: 'active', reps: reps(5, 0.62), planned: 10 }, { status: 'todo', planned: 10 }] }
12
- const UPCOMING: Exercise = { name: 'Standing Calf Raise', sets: 5, reps: 20, load: 25, tempo: [2, 1, 2, 0], upcoming: true, setStates: [1, 2, 3, 4, 5].map(() => ({ status: 'todo', planned: 20 })) }
13
- const RANGE: Exercise = { name: 'Face Pull', sets: 3, reps: '15-20', load: 40, tempo: [2, 1, 2, 0], setStates: [1, 2, 3].map(() => ({ status: 'todo', planned: 18 })) }
14
-
15
- // a heading on the sunk inset surface, at the real rail width
16
- function Row({ ex, h }: { ex: Exercise; h: number }) {
17
- return (
18
- <div style={{ width: 246, background: INSET, boxShadow: INSET_SHADOW }}>
19
- <Heading ex={ex} stripH={h} />
20
- </div>
21
- )
22
- }
23
-
24
- type Args = { stripHeight: number }
25
- const meta: Meta<Args> = {
26
- title: 'Lab/Explorations/Session Rail Heading',
27
- parameters: { layout: 'fullscreen' },
28
- argTypes: { stripHeight: { control: { type: 'range', min: 3, max: 14, step: 1 } } },
29
- args: { stripHeight: 8 },
30
- }
31
- export default meta
32
- type Story = StoryObj<Args>
33
-
34
- export const States: Story = {
35
- name: 'Heading · states + heights',
36
- render: (args) => (
37
- <Page
38
- title="Session rail heading — the exercise unit"
39
- note="The always-shown heading: name + indicator · tight sets/reps/load (tempo language) + tempo · per-set strip. Left column = the three states at the current height; right = the completed heading across 4 / 6 / 8 / 10px."
40
- >
41
- <div style={{ display: 'flex', gap: 48, flexWrap: 'wrap' }}>
42
- <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
43
- {([['completed', DONE], ['active (pulsing)', ACTIVE], ['upcoming', UPCOMING], ['rep range', RANGE]] as [string, Exercise][]).map(([lbl, ex]) => (
44
- <div key={lbl} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
45
- <span style={monoTag}>{lbl}</span>
46
- <Row ex={ex} h={args.stripHeight} />
47
- </div>
48
- ))}
49
- </div>
50
- <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
51
- {[4, 6, 8, 10].map((h) => (
52
- <div key={h} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
53
- <span style={monoTag}>strip {h}px</span>
54
- <Row ex={DONE} h={h} />
55
- </div>
56
- ))}
57
- </div>
58
- </div>
59
- </Page>
60
- ),
61
- }
@@ -1,176 +0,0 @@
1
- /**
2
- * SHEET · Session Rail — set-type encodings (R&D). Throwaway specimen at real rail width, on real tokens.
3
- * Explores the cases the flat `sets × reps @ load` strip doesn't model:
4
- * 1. Variable rep-range — range-max segments; the variable zone (floor→max) upcoming part gets its OWN color.
5
- * 2. Drop set — ONE bar, sub-loads separated by thin NOTCHES (< the between-set gap); reps velocity-colored.
6
- * 3. Myo-rep / rest-pause — activation chunk + mini-clusters separated by small cluster gaps.
7
- * Gap hierarchy: butted reps (0) < notch (2, drop sub-load) < cluster gap (3, myo rest-pause) < SET_GAP (5, sets).
8
- * Hardens into a SetStrip model extension (SetState variants: range/drop/myo) — a post-harden follow-up.
9
- */
10
- import type { Meta, StoryObj } from '@storybook/react-vite'
11
- import { Fragment } from 'react'
12
- import { primitiveRamps as ramp, greyRamp } from '../../../theme/tokens/primitives'
13
- import { GREY, RAIL_W, SET_GAP, T_PRIMARY, T_SECONDARY, T_TERTIARY, INSET, velColor, reps, Page, sectionTitle } from './setHeadingKit'
14
-
15
- // ---- variable-zone (floor→max) upcoming color — real ramp candidates (no invented hex)
16
- const VAR_GREY = greyRamp[800] // #3C3C3C — lighter grey (the paler-grey reference)
17
- const VAR_BLUE_800 = ramp.blue[800] // #14407E — clearly blue, a touch brighter
18
- const VAR_BLUE_900 = ramp.blue[900] // #112C5A — dark muted navy, recessive
19
- const VAR_CYAN_900 = ramp.cyan[900] // #0B3149 — teal alt, sidesteps info-blue adjacency
20
- const NOTCH = 2 // drop sub-load divider
21
- const CLUSTER_GAP = 3 // myo rest-pause divider
22
-
23
- type Chunk = { colors: string[]; gapAfter?: number }
24
- function Bar({ chunks, h }: { chunks: Chunk[]; h: number }) {
25
- return (
26
- <div style={{ display: 'flex', width: '100%', height: h, borderRadius: 2, overflow: 'hidden' }}>
27
- {chunks.map((ch, ci) => (
28
- <Fragment key={ci}>
29
- {ch.colors.map((c, i) => (
30
- <div key={i} style={{ flex: 1, minWidth: 0, height: '100%', background: c }} />
31
- ))}
32
- {ci < chunks.length - 1 && <div style={{ flex: `0 0 ${ch.gapAfter ?? NOTCH}px`, height: '100%', background: INSET }} />}
33
- </Fragment>
34
- ))}
35
- </div>
36
- )
37
- }
38
-
39
- // ---- 1. variable rep-range: `max` segments; committed 0..floor, variable floor..max; variable-todo gets VAR color
40
- function rangeColors(floor: number, max: number, doneVels: number[], varColor: string): string[] {
41
- return Array.from({ length: max }, (_, i) => {
42
- if (i < doneVels.length) return velColor(doneVels[i])
43
- return i < floor ? GREY : varColor
44
- })
45
- }
46
- function RangeBar({ floor, max, done, varColor, h }: { floor: number; max: number; done: number[]; varColor: string; h: number }) {
47
- return <Bar chunks={[{ colors: rangeColors(floor, max, done, varColor) }]} h={h} />
48
- }
49
-
50
- // ---- 2. drop set: one bar, sub-loads butted internally, separated by thin notches
51
- function DropBar({ subloads, h }: { subloads: number[][]; h: number }) {
52
- const chunks: Chunk[] = subloads.map((vels, i) => ({ colors: vels.map(velColor), gapAfter: NOTCH, ...(i === subloads.length - 1 ? { gapAfter: undefined } : {}) }))
53
- return <Bar chunks={chunks} h={h} />
54
- }
55
-
56
- // ---- 3. myo-rep: activation chunk + mini-clusters, separated by cluster gaps
57
- function MyoBar({ activation, clusters, h }: { activation: number[]; clusters: number[][]; h: number }) {
58
- const chunks: Chunk[] = [{ colors: activation.map(velColor), gapAfter: CLUSTER_GAP }, ...clusters.map((c) => ({ colors: c.map(velColor), gapAfter: CLUSTER_GAP }))]
59
- return <Bar chunks={chunks} h={h} />
60
- }
61
-
62
- // ---- 3b. UPCOMING myo, unknown length: grey activation (expected) + a blue "clusters-to-failure" trail
63
- // that fades and leaves the right edge open — signalling "N more clusters, count unknown".
64
- function MyoUpcomingBar({ activationLen, blue, h }: { activationLen: number; blue: string; h: number }) {
65
- const fades = [1, 0.6, 0.32] // decreasing opacity per expected cluster → "and maybe more"
66
- return (
67
- <div style={{ display: 'flex', width: '100%', height: h, gap: 0 }}>
68
- <div style={{ display: 'flex', flex: activationLen, height: '100%', borderRadius: '2px 0 0 2px', overflow: 'hidden' }}>
69
- {Array.from({ length: activationLen }, (_, i) => (
70
- <div key={i} style={{ flex: 1, height: '100%', background: GREY }} />
71
- ))}
72
- </div>
73
- {fades.map((op, ci) => (
74
- <Fragment key={ci}>
75
- <div style={{ flex: `0 0 ${CLUSTER_GAP}px`, height: '100%', background: INSET }} />
76
- <div style={{ display: 'flex', flex: 5, height: '100%', overflow: 'hidden', opacity: op }}>
77
- {Array.from({ length: 5 }, (_, i) => (
78
- <div key={i} style={{ flex: 1, height: '100%', background: blue }} />
79
- ))}
80
- </div>
81
- </Fragment>
82
- ))}
83
- </div>
84
- )
85
- }
86
-
87
- // ---- row scaffold at real rail width, on the sunk inset surface
88
- function Row({ name, meta, children }: { name: string; meta: string; children: React.ReactNode }) {
89
- return (
90
- <div style={{ width: RAIL_W, background: INSET, padding: '9px 12px', borderRadius: 4 }}>
91
- <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 6 }}>
92
- <span style={{ fontSize: 14, fontWeight: 800, color: T_PRIMARY }}>{name}</span>
93
- <div style={{ flex: 1 }} />
94
- <span style={{ fontSize: 10, fontFamily: 'monospace', color: T_TERTIARY }}>{meta}</span>
95
- </div>
96
- {children}
97
- </div>
98
- )
99
- }
100
- function Col({ label, children }: { label: string; children: React.ReactNode }) {
101
- return (
102
- <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
103
- <span style={{ ...sectionTitle, color: T_SECONDARY }}>{label}</span>
104
- {children}
105
- </div>
106
- )
107
- }
108
-
109
- const H = 8
110
-
111
- function Sheet() {
112
- return (
113
- <Page title="Session Rail — set-type encodings" note="R&D for prescriptions the flat sets×reps strip doesn't model. Rail width, real velocity ramp pins. Rep-range: range-max segments, the variable zone (floor→max) upcoming part gets its own color. Drop: one bar, sub-loads split by thin notches. Myo: activation + mini-clusters split by cluster gaps.">
114
- <div style={{ display: 'flex', gap: 40, flexWrap: 'wrap', alignItems: 'flex-start' }}>
115
- {/* 1. variable rep-range — real ramp candidates for the variable zone */}
116
- <Col label="1 · variable rep-range — LOCKED: cyan 900">
117
- {([
118
- ['grey · grey 200', VAR_GREY],
119
- ['blue 800 · #14407E', VAR_BLUE_800],
120
- ['blue 900 · #112C5A', VAR_BLUE_900],
121
- ['cyan 900 · #0B3149', VAR_CYAN_900],
122
- ] as const).map(([label, c]) => (
123
- <Row key={label} name="Face Pull" meta="3 × 15–20 @ 40">
124
- <span style={{ fontSize: 9, color: T_TERTIARY, display: 'block', marginBottom: 5 }}>{label}</span>
125
- <div style={{ display: 'flex', flexDirection: 'column', gap: SET_GAP }}>
126
- <RangeBar floor={15} max={20} done={[]} varColor={c} h={H} />
127
- <RangeBar floor={15} max={20} done={reps(12, 0.9)} varColor={c} h={H} />
128
- <RangeBar floor={15} max={20} done={reps(17, 0.8)} varColor={c} h={H} />
129
- </div>
130
- </Row>
131
- ))}
132
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>Each block: todo · 12 done (committed) · 17 done (into the variable zone). Variable-todo = the swatch; committed-todo = grey.</span>
133
- </Col>
134
-
135
- {/* 2. drop set */}
136
- <Col label="2 · drop set">
137
- <Row name="Lat Pulldown" meta="1 drop · 10→8→6 @ 120→80">
138
- <DropBar subloads={[reps(10, 0.85), reps(8, 0.7), reps(6, 0.6)]} h={H} />
139
- </Row>
140
- <Row name="Leg Extension" meta="1 drop · 12→10→8→6 @ 90→45">
141
- <DropBar subloads={[reps(12, 0.8), reps(10, 0.7), reps(8, 0.62), reps(6, 0.55)]} h={H} />
142
- </Row>
143
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>One set, no rest; notches mark each load drop. Notch (2px) &lt; set gap (5px) so drops read as sub-structure of a single set.</span>
144
- </Col>
145
-
146
- {/* 3. myo-rep */}
147
- <Col label="3 · myo-rep / rest-pause">
148
- <Row name="Cable Curl" meta="myo · done · 15 + 5 + 5 + 5">
149
- <MyoBar activation={reps(15, 0.75)} clusters={[reps(5, 0.6), reps(5, 0.55), reps(5, 0.5)]} h={H} />
150
- </Row>
151
- <Row name="Triceps Pushdown" meta="myo · done · 12 + 4 + 4">
152
- <MyoBar activation={reps(12, 0.7)} clusters={[reps(4, 0.55), reps(4, 0.5)]} h={H} />
153
- </Row>
154
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>Done: activation to near-failure, then rest-pause clusters. Cluster gap (3px) between notch and set gap.</span>
155
- <span style={{ ...sectionTitle, color: T_SECONDARY, marginTop: 6 }}>upcoming · length unknown</span>
156
- <Row name="Cable Curl" meta="myo · ~15 + clusters to failure">
157
- <MyoUpcomingBar activationLen={15} blue={VAR_CYAN_900} h={H} />
158
- </Row>
159
- <Row name="Triceps Pushdown" meta="myo · ~12 + clusters to failure">
160
- <MyoUpcomingBar activationLen={12} blue={VAR_CYAN_900} h={H} />
161
- </Row>
162
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>{'Grey activation (expected) + blue "clusters-to-failure" trail that fades and leaves the right edge open — reuses the variable/opportunity blue, signalling "more coming, count unknown."'}</span>
163
- </Col>
164
- </div>
165
- </Page>
166
- )
167
- }
168
-
169
- const meta: Meta = {
170
- title: 'Lab/Explorations/Set Types',
171
- parameters: { layout: 'fullscreen' },
172
- }
173
- export default meta
174
- type Story = StoryObj
175
-
176
- export const Encodings: Story = { render: () => <Sheet /> }
@@ -1,240 +0,0 @@
1
- /**
2
- * SHEET · Workout Expansion (page 2) — what a rail item reveals when expanded.
3
- * Anchored on the REAL unexpanded rail row (`ExerciseCardHeading`) as the persistent header, then the
4
- * revealed body in two REAL-component directions so the fork is concrete:
5
- * A — Table (real `SetTableHeader` + real `SetRow`s — the current expanded body).
6
- * C — Embed (real `VelocityStrip` full/expanded per set + a compact caption — the bar IS the set).
7
- * B (drop PREV) is a trivial prop on the table, noted but not forked here. Same data across both: set 1 done
8
- * · set 2 LIVE 5/10 · set 3 upcoming, with velocities that DECAY within a set so the "shape" reading is real.
9
- * OPEN: A-vs-C · live-set treatment in the body · read-only density (drop TEMPO row? per-row strips?). DECISIONS doc.
10
- */
11
- import type { Meta, StoryObj } from '@storybook/react-vite'
12
- import { View, Text } from 'react-native'
13
- import { ExerciseCardHeading } from './ExerciseCardHeading'
14
- import { SetTableHeader } from './SetTableHeader'
15
- import { SetRow, type SetRowProps } from './SetRow'
16
- import { VelocityStrip } from './VelocityStrip'
17
- import { type SetStripSet } from './SetStrip'
18
- import {
19
- INSET,
20
- INSET_SHADOW,
21
- RAISED,
22
- BORDER_SUBTLE,
23
- GREEN,
24
- T_PRIMARY,
25
- T_SECONDARY,
26
- T_TERTIARY,
27
- Page,
28
- sectionTitle,
29
- monoTag,
30
- } from './setHeadingKit'
31
-
32
- // Per-rep mean velocity that DECAYS across a set (fast → slow) so bar height/color carries shape.
33
- const decay = (n: number, start: number, span = 0.5) =>
34
- Array.from({ length: n }, (_, r) => +(start - (span * r) / Math.max(1, n - 1)).toFixed(3))
35
-
36
- // ---- shared data (real prop shapes) ------------------------------------------------
37
- // Heading strip (SetStripSet[]): set1 done · set2 active 5/10 · set3 todo.
38
- const HEADING_STATES: SetStripSet[] = [
39
- { status: 'done', velocities: decay(10, 1.05) },
40
- { status: 'active', velocities: decay(5, 0.95, 0.3), planned: 10 },
41
- { status: 'todo', planned: 10 },
42
- ]
43
- // Expanded-body per-set rows (real SetRowProps): set 1 done · set 2 LIVE · set 3 todo.
44
- const BODY_SETS: SetRowProps[] = [
45
- {
46
- state: 'done',
47
- setNumber: 1,
48
- reps: 10,
49
- weight: 90,
50
- rpe: 7.5,
51
- unit: 'lbs',
52
- velocities: decay(10, 1.05),
53
- },
54
- {
55
- state: 'live',
56
- setNumber: 2,
57
- unit: 'lbs',
58
- target: { reps: 10, weight: 90 },
59
- reps: 10,
60
- weight: 90,
61
- velocities: decay(5, 0.95, 0.3),
62
- },
63
- { state: 'todo', setNumber: 3, unit: 'lbs', target: { reps: 10, weight: 90 } },
64
- ]
65
-
66
- // ---- the real unexpanded rail row, used as the persistent expansion header ---------
67
- function RailHeader() {
68
- return (
69
- <View style={{ position: 'relative', zIndex: 2, backgroundColor: RAISED }}>
70
- <ExerciseCardHeading
71
- name="Cable Chest Press"
72
- sets={3}
73
- reps={10}
74
- load={90}
75
- unit="lbs"
76
- tempo={[2, 1, 2, 0]}
77
- indicator="info"
78
- setStates={HEADING_STATES}
79
- />
80
- </View>
81
- )
82
- }
83
-
84
- // ---- A · table body: real SetTableHeader + real SetRow (LOCKED: drop PREV, keep strips)
85
- function TableBody() {
86
- return (
87
- <View>
88
- <SetTableHeader unit="lbs" showPrevious={false} />
89
- {BODY_SETS.map((s, i) => (
90
- <SetRow key={i} {...s} />
91
- ))}
92
- </View>
93
- )
94
- }
95
-
96
- // ---- C · embed body: real VelocityStrip (full/expanded) per set + compact caption ---
97
- const capText = {
98
- fontFamily: 'Inter, sans-serif',
99
- fontSize: 11,
100
- fontWeight: '600' as const,
101
- color: T_PRIMARY,
102
- }
103
- const dimText = { ...capText, color: T_SECONDARY, fontWeight: '500' as const }
104
- function EmbedSetRow({ s }: { s: SetRowProps }) {
105
- const live = s.state === 'live'
106
- const todo = s.state === 'todo'
107
- const vels = s.state === 'done' || s.state === 'live' ? s.velocities : []
108
- const rpe = s.state === 'todo' ? null : s.rpe
109
- return (
110
- <View
111
- style={{
112
- paddingVertical: 7,
113
- paddingHorizontal: 10,
114
- marginHorizontal: 2,
115
- marginBottom: 4,
116
- borderRadius: 8,
117
- opacity: todo ? 0.55 : 1,
118
- ...(live
119
- ? {
120
- backgroundColor: 'rgba(46,213,115,0.06)',
121
- borderWidth: 1,
122
- borderColor: 'rgba(46,213,115,0.30)',
123
- }
124
- : {}),
125
- }}
126
- >
127
- <View style={{ flexDirection: 'row', alignItems: 'baseline', marginBottom: 6 }}>
128
- <Text style={{ ...dimText, width: 22, color: T_TERTIARY }}>{s.setNumber}</Text>
129
- {s.state === 'live' ? (
130
- <Text style={{ ...capText, color: GREEN, fontWeight: '700' }}>
131
- {vels.length}/{s.target.reps} × {s.target.weight}
132
- </Text>
133
- ) : s.state === 'done' ? (
134
- <Text style={capText}>
135
- {s.reps} × {s.weight}
136
- </Text>
137
- ) : (
138
- <Text style={dimText}>
139
- {s.target.reps} × {s.target.weight}
140
- </Text>
141
- )}
142
- <View style={{ flex: 1 }} />
143
- {rpe != null && <Text style={dimText}>RPE {rpe}</Text>}
144
- {live && <Text style={{ ...capText, color: GREEN, fontWeight: '700' }}>live</Text>}
145
- </View>
146
- {vels.length > 0 ? (
147
- <VelocityStrip velocities={vels} variant="expanded" showInfo={false} />
148
- ) : (
149
- <View style={{ height: 24, flexDirection: 'row', gap: 2 }}>
150
- {Array.from({ length: s.state === 'todo' ? s.target.reps : 10 }).map((_, i) => (
151
- <View
152
- key={i}
153
- style={{
154
- flex: 1,
155
- height: 6,
156
- alignSelf: 'flex-end',
157
- backgroundColor: '#2C2C2C',
158
- borderRadius: 1,
159
- opacity: 0.5,
160
- }}
161
- />
162
- ))}
163
- </View>
164
- )}
165
- </View>
166
- )
167
- }
168
- function EmbedBody() {
169
- return (
170
- <View style={{ paddingTop: 6 }}>
171
- {BODY_SETS.map((s, i) => (
172
- <EmbedSetRow key={i} s={s} />
173
- ))}
174
- </View>
175
- )
176
- }
177
-
178
- // ---- expanded item = real rail header + revealed body ------------------------------
179
- function ExpandedItem({ label, children }: { label: string; children: React.ReactNode }) {
180
- return (
181
- <View style={{ gap: 8 }}>
182
- <Text style={{ ...monoTag, color: T_SECONDARY }}>{label}</Text>
183
- <View
184
- style={
185
- {
186
- width: 260,
187
- backgroundColor: INSET,
188
- boxShadow: INSET_SHADOW,
189
- borderRadius: 4,
190
- overflow: 'hidden',
191
- } as object
192
- }
193
- >
194
- <RailHeader />
195
- <View
196
- style={{
197
- backgroundColor: INSET,
198
- paddingBottom: 8,
199
- borderTopWidth: 1,
200
- borderTopColor: BORDER_SUBTLE,
201
- }}
202
- >
203
- {children}
204
- </View>
205
- </View>
206
- </View>
207
- )
208
- }
209
-
210
- const meta: Meta = {
211
- title: 'Lab/Explorations/Workout Expansion',
212
- parameters: { layout: 'fullscreen' },
213
- }
214
- export default meta
215
- type Story = StoryObj
216
-
217
- export const DirectionStudy: Story = {
218
- name: 'Expanded item · A table / C embed-in-bar (real components)',
219
- render: () => (
220
- <Page
221
- title="Workout expansion — direction study (page 2)"
222
- note="LOCKED (2026-07-10): body = direction A, the SetTableHeader+SetRow table, with PREV dropped (real showPrevious={false}) and the per-row velocity strips kept. C (per-rep VelocityStrip becomes the set row) shown for the record — rejected as too novel; the table already carries velocity shape via the per-row strip. Anchored on the REAL unexpanded rail row (ExerciseCardHeading) as the persistent header; data: set 1 done · set 2 live 5/10 · set 3 upcoming, velocities decaying within a set."
223
- >
224
- <View style={{ flexDirection: 'row', gap: 44, alignItems: 'flex-start', flexWrap: 'wrap' }}>
225
- <View style={{ gap: 12 }}>
226
- <Text style={sectionTitle}>A · Table (current body)</Text>
227
- <ExpandedItem label="real SetTableHeader + SetRow">
228
- <TableBody />
229
- </ExpandedItem>
230
- </View>
231
- <View style={{ gap: 12 }}>
232
- <Text style={sectionTitle}>C · Embed in the bar</Text>
233
- <ExpandedItem label="real VelocityStrip (full) + caption">
234
- <EmbedBody />
235
- </ExpandedItem>
236
- </View>
237
- </View>
238
- </Page>
239
- ),
240
- }
@@ -1,65 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
- import { View, Text } from 'react-native'
3
- import { DashboardShell } from './DashboardShell'
4
-
5
- /**
6
- * `Pages/DashboardShell` — the wall-dashboard chrome as one registered surface.
7
- * Composes the shell-nav island (SideNav + TopBar and everything they pull in) over a
8
- * `children` content slot, so the dashboard app mounts a single component.
9
- */
10
- const meta: Meta<typeof DashboardShell> = {
11
- title: 'Pages/DashboardShell',
12
- component: DashboardShell,
13
- tags: ['autodocs'],
14
- parameters: {
15
- layout: 'fullscreen',
16
- docs: {
17
- description: {
18
- component:
19
- '**Page shell.** The wall-dashboard chrome. Composes ' +
20
- '[SideNav](?path=/docs/shell-sidenav--docs) + ' +
21
- '[TopBar](?path=/docs/shell-topbar--docs) — which pulls in DeviceMenu, DeviceRow, ' +
22
- 'DeviceIndicator, SessionStatePill, BrandLockup, DateTime and Divider — over a ' +
23
- '`children` content slot. Mount this instead of re-assembling the chrome per view.',
24
- },
25
- },
26
- },
27
- argTypes: {
28
- state: { control: 'select', options: ['live', 'rest', 'idle'] },
29
- activeKey: { control: 'select', options: ['live', 'review', 'program', 'body'] },
30
- liveKey: { control: 'select', options: [null, 'live', 'review', 'program', 'body'] },
31
- onNavigate: { control: false },
32
- onSelectDevice: { control: false },
33
- },
34
- decorators: [
35
- (Story) => (
36
- <View style={{ height: '100vh' as unknown as number, backgroundColor: '#0E0E0E' }}>
37
- <Story />
38
- </View>
39
- ),
40
- ],
41
- }
42
-
43
- export default meta
44
- type Story = StoryObj<typeof DashboardShell>
45
-
46
- export const Default: Story = {
47
- args: { activeKey: 'live', state: 'live' },
48
- }
49
-
50
- export const WithContent: Story = {
51
- args: { activeKey: 'review', state: 'rest', liveKey: 'live' },
52
- render: (args) => (
53
- <DashboardShell {...args}>
54
- <View style={{ flex: 1, padding: 28 }}>
55
- <Text style={{ color: '#E5E5E5', fontSize: 22, fontWeight: '700' }}>Review</Text>
56
- <Text style={{ color: '#8A8A8A', fontSize: 13, marginTop: 6 }}>
57
- A page mounts its content here; the shell keeps the nav + top-bar chrome persistent.
58
- </Text>
59
- </View>
60
- </DashboardShell>
61
- ),
62
- parameters: {
63
- docs: { description: { story: 'The shell with a page mounted in its content slot.' } },
64
- },
65
- }