@titan-design/react-ui 0.12.1 → 0.13.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 (509) hide show
  1. package/README.md +46 -47
  2. package/dist/bodymap.js +768 -701
  3. package/dist/bodymap.js.map +1 -1
  4. package/dist/bodymap.mjs +770 -703
  5. package/dist/bodymap.mjs.map +1 -1
  6. package/dist/index.d.mts +1319 -216
  7. package/dist/index.d.ts +1319 -216
  8. package/dist/index.js +5996 -4498
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +5773 -4357
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/{pages-CvsFqNtx.d.mts → pages-CpW3OB3g.d.mts} +21 -3
  13. package/dist/{pages-B1hqnGIC.d.ts → pages-_3Ajpiqu.d.ts} +21 -3
  14. package/dist/pages.d.mts +1 -1
  15. package/dist/pages.d.ts +1 -1
  16. package/dist/pages.js +1435 -1428
  17. package/dist/pages.js.map +1 -1
  18. package/dist/pages.mjs +1443 -1436
  19. package/dist/pages.mjs.map +1 -1
  20. package/dist/theme/index.d.mts +195 -134
  21. package/dist/theme/index.d.ts +195 -134
  22. package/dist/theme/index.js +215 -300
  23. package/dist/theme/index.js.map +1 -1
  24. package/dist/theme/index.mjs +202 -296
  25. package/dist/theme/index.mjs.map +1 -1
  26. package/dist/theme/tokens-css.js +62 -5
  27. package/dist/theme/tokens-css.js.map +1 -1
  28. package/dist/theme/tokens-css.mjs +62 -5
  29. package/dist/theme/tokens-css.mjs.map +1 -1
  30. package/dist/theme/tokens.d.mts +73 -5
  31. package/dist/theme/tokens.d.ts +73 -5
  32. package/dist/theme/tokens.js +55 -7
  33. package/dist/theme/tokens.js.map +1 -1
  34. package/dist/theme/tokens.mjs +55 -8
  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/package.json +1 -1
  40. package/src/arch/arch-graph.freshness.test.ts +52 -0
  41. package/src/arch/arch-graph.json +5021 -1617
  42. package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
  43. package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
  44. package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
  45. package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
  46. package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
  47. package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
  48. package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
  49. package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
  50. package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
  51. package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
  52. package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
  53. package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
  54. package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
  55. package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
  56. package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
  57. package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
  58. package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
  59. package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
  60. package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
  61. package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
  62. package/src/components/custom/ActiveWork/InitiativeBrief.tsx +181 -0
  63. package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
  64. package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
  65. package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
  66. package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
  67. package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
  68. package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
  69. package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
  70. package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
  71. package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
  72. package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
  73. package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
  74. package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
  75. package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
  76. package/src/components/custom/ActiveWork/README.md +305 -0
  77. package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
  78. package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
  79. package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
  80. package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
  81. package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
  82. package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
  83. package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
  84. package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
  85. package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
  86. package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
  87. package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
  88. package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
  89. package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
  90. package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
  91. package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
  92. package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
  93. package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
  94. package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
  95. package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
  96. package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
  97. package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
  98. package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
  99. package/src/components/custom/ActiveWork/format-time.ts +32 -0
  100. package/src/components/custom/ActiveWork/index.ts +19 -0
  101. package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
  102. package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
  103. package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
  104. package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
  105. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +4 -3
  106. package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
  107. package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
  108. package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
  109. package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
  110. package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
  111. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
  112. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
  113. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
  114. package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
  115. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
  116. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
  117. package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
  118. package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
  119. package/src/components/custom/Fatigue/README.md +40 -3
  120. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
  121. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
  122. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
  123. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
  124. package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
  125. package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
  126. package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
  127. package/src/components/custom/Fatigue/index.ts +17 -5
  128. package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
  129. package/src/components/custom/Fatigue/panel-layout.ts +185 -0
  130. package/src/components/custom/Gauge/Gauge.stories.tsx +2 -2
  131. package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
  132. package/src/components/custom/Gauge/Gauge.tsx +4 -1
  133. package/src/components/custom/Metric/Metric.stories.tsx +10 -1
  134. package/src/components/custom/Metric/Metric.test.tsx +1 -3
  135. package/src/components/custom/Metric/Metric.tsx +5 -20
  136. package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
  137. package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
  138. package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
  139. package/src/components/custom/Prose/README.md +58 -0
  140. package/src/components/custom/Prose/index.ts +1 -0
  141. package/src/components/custom/Scatter/Scatter.stories.tsx +46 -8
  142. package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
  143. package/src/components/custom/Scatter/Scatter.tsx +116 -14
  144. package/src/components/custom/Sidebar/Sidebar.stories.tsx +40 -7
  145. package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
  146. package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
  147. package/src/components/custom/Table/Table.stories.tsx +98 -15
  148. package/src/components/custom/Table/Table.test.tsx +273 -86
  149. package/src/components/custom/Table/Table.tsx +159 -67
  150. package/src/components/custom/Table/column-fit.test.ts +75 -0
  151. package/src/components/custom/Table/column-fit.ts +116 -0
  152. package/src/components/custom/Table/index.ts +9 -0
  153. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
  154. package/src/components/custom/Treemap/Treemap.stories.tsx +2 -2
  155. package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
  156. package/src/components/custom/Treemap/Treemap.tsx +7 -2
  157. package/src/components/custom/Typography/Typography.stories.tsx +28 -1
  158. package/src/components/custom/Typography/Typography.test.tsx +34 -0
  159. package/src/components/custom/Typography/Typography.tsx +6 -0
  160. package/src/components/custom/Typography/index.ts +1 -8
  161. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +9 -1
  162. package/src/components/custom/Workout/BaseBadge.stories.tsx +19 -7
  163. package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
  164. package/src/components/custom/Workout/BaseBadge.tsx +3 -0
  165. package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
  166. package/src/components/custom/Workout/BodyMap.tsx +3 -1
  167. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +16 -4
  168. package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
  169. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +45 -9
  170. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +10 -8
  171. package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
  172. package/src/components/custom/Workout/CapacityBandChart.tsx +139 -108
  173. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  174. package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
  175. package/src/components/custom/Workout/DeviationBar.tsx +21 -16
  176. package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +182 -0
  177. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +3 -2
  178. package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -7
  179. package/src/components/custom/Workout/ExerciseCard.test.tsx +13 -3
  180. package/src/components/custom/Workout/ExerciseCard.tsx +42 -51
  181. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +7 -7
  182. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
  183. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
  184. package/src/components/custom/Workout/ExerciseHeading.tsx +8 -5
  185. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -4
  186. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
  187. package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
  188. package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
  189. package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
  190. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  191. package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
  192. package/src/components/custom/Workout/IntensityBar.tsx +4 -2
  193. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
  194. package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
  195. package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
  196. package/src/components/custom/Workout/MesoCard.tsx +12 -9
  197. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  198. package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
  199. package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
  200. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
  201. package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
  202. package/src/components/custom/Workout/MesoStatusCard.tsx +9 -23
  203. package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
  204. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
  205. package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
  206. package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
  207. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
  208. package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
  209. package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
  210. package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
  211. package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
  212. package/src/components/custom/Workout/PrBadge.tsx +13 -17
  213. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +4 -1
  214. package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
  215. package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
  216. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
  217. package/src/components/custom/Workout/README.md +11 -6
  218. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
  219. package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
  220. package/src/components/custom/Workout/ReadinessCheck.tsx +19 -3
  221. package/src/components/custom/Workout/RestTimer.stories.tsx +3 -2
  222. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
  223. package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
  224. package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
  225. package/src/components/custom/Workout/SegmentedBar.stories.tsx +5 -5
  226. package/src/components/custom/Workout/SegmentedBar.tsx +6 -2
  227. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
  228. package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
  229. package/src/components/custom/Workout/SessionHeader.tsx +12 -12
  230. package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
  231. package/src/components/custom/Workout/SessionRail.tsx +7 -9
  232. package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
  233. package/src/components/custom/Workout/SetBar.test.tsx +49 -4
  234. package/src/components/custom/Workout/SetBar.tsx +38 -12
  235. package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
  236. package/src/components/custom/Workout/SetRow.test.tsx +16 -2
  237. package/src/components/custom/Workout/SetRow.tsx +61 -23
  238. package/src/components/custom/Workout/SetStrip.stories.tsx +60 -5
  239. package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
  240. package/src/components/custom/Workout/SetStrip.tsx +24 -4
  241. package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
  242. package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
  243. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
  244. package/src/components/custom/Workout/SetsRepsLoad.tsx +3 -5
  245. package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
  246. package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
  247. package/src/components/custom/Workout/Sparkline.tsx +14 -18
  248. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  249. package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
  250. package/src/components/custom/Workout/StatusDot.tsx +93 -63
  251. package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
  252. package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
  253. package/src/components/custom/Workout/StatusPill.tsx +27 -38
  254. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +9 -3
  255. package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
  256. package/src/components/custom/Workout/StrengthTrendChart.tsx +31 -30
  257. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
  258. package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
  259. package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
  260. package/src/components/custom/Workout/TempoDisplay.stories.tsx +22 -7
  261. package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
  262. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
  263. package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
  264. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +7 -4
  265. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +4 -1
  266. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +4 -1
  267. package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
  268. package/src/components/custom/Workout/VelocityStrip.tsx +3 -0
  269. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
  270. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
  271. package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
  272. package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
  273. package/src/components/custom/Workout/WeekRow.tsx +23 -16
  274. package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
  275. package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
  276. package/src/components/custom/Workout/WeightBadge.tsx +28 -27
  277. package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
  278. package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
  279. package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
  280. package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
  281. package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
  282. package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
  283. package/src/components/custom/Workout/ZoneTrack.stories.tsx +7 -6
  284. package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
  285. package/src/components/custom/Workout/index.ts +5 -0
  286. package/src/components/custom/Workout/metricText.stories.tsx +6 -5
  287. package/src/components/custom/Workout/metricText.tsx +4 -0
  288. package/src/components/custom/Workout/setHeadingKit.tsx +207 -26
  289. package/src/components/custom/charts/README.md +61 -0
  290. package/src/components/custom/charts/SetBarChart.test.tsx +30 -1
  291. package/src/components/custom/charts/SetBarChart.tsx +42 -4
  292. package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
  293. package/src/components/custom/charts/SparkBars.test.tsx +69 -0
  294. package/src/components/custom/charts/SparkBars.tsx +85 -0
  295. package/src/components/custom/charts/index.ts +3 -0
  296. package/src/components/custom/index.ts +3 -0
  297. package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
  298. package/src/components/custom/stepper/Stepper.test.tsx +1 -7
  299. package/src/components/custom/stepper/Stepper.tsx +13 -28
  300. package/src/components/icons/icons.stories.tsx +1 -1
  301. package/src/components/icons/icons.tsx +51 -0
  302. package/src/components/shell/AppShell.stories.tsx +150 -0
  303. package/src/components/shell/AppShell.test.tsx +70 -0
  304. package/src/components/shell/AppShell.tsx +90 -0
  305. package/src/components/shell/BrandLockup.stories.tsx +66 -5
  306. package/src/components/shell/BrandLockup.test.tsx +34 -1
  307. package/src/components/shell/BrandLockup.tsx +27 -11
  308. package/src/components/shell/NavItem.stories.tsx +4 -4
  309. package/src/components/shell/NavItem.test.tsx +17 -0
  310. package/src/components/shell/NavItem.tsx +17 -5
  311. package/src/components/shell/README.md +89 -26
  312. package/src/components/shell/SideNav.stories.tsx +38 -7
  313. package/src/components/shell/SideNav.test.tsx +16 -8
  314. package/src/components/shell/SideNav.tsx +17 -17
  315. package/src/components/shell/TopBar.stories.tsx +44 -19
  316. package/src/components/shell/TopBar.test.tsx +34 -12
  317. package/src/components/shell/TopBar.tsx +61 -40
  318. package/src/components/shell/brands.tsx +66 -0
  319. package/src/components/shell/index.ts +9 -8
  320. package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
  321. package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
  322. package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
  323. package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
  324. package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
  325. package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
  326. package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
  327. package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
  328. package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
  329. package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
  330. package/src/components/shell/workout/WorkoutShell.tsx +77 -0
  331. package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
  332. package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
  333. package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
  334. package/src/components/shell/workout/index.ts +9 -0
  335. package/src/components/shell/workout/workoutNavItems.tsx +16 -0
  336. package/src/components/ui/README.md +110 -0
  337. package/src/components/ui/alert/Alert.stories.tsx +1 -1
  338. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
  339. package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
  340. package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
  341. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  342. package/src/components/ui/avatar/Avatar.tsx +2 -10
  343. package/src/components/ui/badge/Badge.stories.tsx +83 -28
  344. package/src/components/ui/badge/Badge.test.tsx +19 -3
  345. package/src/components/ui/badge/Badge.tsx +48 -55
  346. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  347. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
  348. package/src/components/ui/button/Button.stories.tsx +46 -12
  349. package/src/components/ui/button/Button.tsx +32 -25
  350. package/src/components/ui/card/Card.stories.tsx +90 -94
  351. package/src/components/ui/card/Card.test.tsx +80 -6
  352. package/src/components/ui/card/Card.tsx +150 -203
  353. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  354. package/src/components/ui/checkbox/Checkbox.tsx +6 -26
  355. package/src/components/ui/chip/Chip.stories.tsx +37 -13
  356. package/src/components/ui/chip/Chip.test.tsx +10 -6
  357. package/src/components/ui/chip/Chip.tsx +76 -91
  358. package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
  359. package/src/components/ui/collapse/Collapse.tsx +6 -11
  360. package/src/components/ui/data-row/DataRow.stories.tsx +9 -2
  361. package/src/components/ui/data-row/DataRow.test.tsx +5 -15
  362. package/src/components/ui/data-row/DataRow.tsx +18 -7
  363. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  364. package/src/components/ui/divider/Divider.tsx +1 -5
  365. package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
  366. package/src/components/ui/drawer/Drawer.tsx +13 -30
  367. package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
  368. package/src/components/ui/form-field/FormField.stories.tsx +6 -20
  369. package/src/components/ui/form-field/FormField.test.tsx +1 -5
  370. package/src/components/ui/form-field/FormField.tsx +10 -46
  371. package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
  372. package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
  373. package/src/components/ui/help-tip/HelpTip.tsx +21 -22
  374. package/src/components/ui/help-tip/index.ts +7 -1
  375. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  376. package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
  377. package/src/components/ui/icon-box/IconBox.tsx +2 -12
  378. package/src/components/ui/indicator/Indicator.stories.tsx +1 -1
  379. package/src/components/ui/indicator/Indicator.tsx +20 -14
  380. package/src/components/ui/input/Input.stories.tsx +3 -11
  381. package/src/components/ui/input/Input.test.tsx +2 -10
  382. package/src/components/ui/input/Input.tsx +10 -25
  383. package/src/components/ui/input/index.ts +7 -1
  384. package/src/components/ui/link/Link.stories.tsx +19 -7
  385. package/src/components/ui/list-item/ListItem.stories.tsx +11 -2
  386. package/src/components/ui/list-item/ListItem.tsx +2 -9
  387. package/src/components/ui/menu/Menu.stories.tsx +21 -15
  388. package/src/components/ui/menu/Menu.test.tsx +2 -11
  389. package/src/components/ui/menu/Menu.tsx +12 -14
  390. package/src/components/ui/menu/index.ts +8 -1
  391. package/src/components/ui/modal/Modal.stories.tsx +2 -2
  392. package/src/components/ui/modal/Modal.tsx +29 -19
  393. package/src/components/ui/pill/Pill.stories.tsx +58 -23
  394. package/src/components/ui/pill/Pill.test.tsx +101 -3
  395. package/src/components/ui/pill/Pill.tsx +164 -49
  396. package/src/components/ui/pill/index.ts +1 -1
  397. package/src/components/ui/popover/Popover.stories.tsx +5 -7
  398. package/src/components/ui/popover/Popover.test.tsx +1 -6
  399. package/src/components/ui/popover/Popover.tsx +20 -15
  400. package/src/components/ui/popover/index.ts +7 -1
  401. package/src/components/ui/progress/Progress.stories.tsx +3 -12
  402. package/src/components/ui/progress/Progress.test.tsx +1 -5
  403. package/src/components/ui/radio/Radio.stories.tsx +42 -21
  404. package/src/components/ui/radio/Radio.test.tsx +6 -2
  405. package/src/components/ui/radio/Radio.tsx +23 -22
  406. package/src/components/ui/section/Section.stories.tsx +5 -14
  407. package/src/components/ui/section/Section.test.tsx +1 -6
  408. package/src/components/ui/section/Section.tsx +1 -3
  409. package/src/components/ui/section/index.ts +1 -5
  410. package/src/components/ui/select/Select.stories.tsx +3 -13
  411. package/src/components/ui/select/Select.test.tsx +2 -11
  412. package/src/components/ui/select/Select.tsx +14 -14
  413. package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
  414. package/src/components/ui/skeleton/Skeleton.tsx +3 -14
  415. package/src/components/ui/skeleton/index.ts +1 -7
  416. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  417. package/src/components/ui/spinner/Spinner.tsx +1 -4
  418. package/src/components/ui/stack/Stack.stories.tsx +1 -1
  419. package/src/components/ui/stack/Stack.tsx +1 -1
  420. package/src/components/ui/surface/Surface.stories.tsx +17 -5
  421. package/src/components/ui/surface/Surface.test.tsx +88 -28
  422. package/src/components/ui/surface/Surface.tsx +37 -87
  423. package/src/components/ui/surface/SurfaceContext.ts +22 -62
  424. package/src/components/ui/surface/index.ts +8 -0
  425. package/src/components/ui/surface/resolveSurface.ts +98 -0
  426. package/src/components/ui/surface/surface.contract.test.ts +6 -1
  427. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  428. package/src/components/ui/switch/Switch.tsx +7 -6
  429. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  430. package/src/components/ui/tabs/Tabs.tsx +7 -22
  431. package/src/components/ui/tabs/index.ts +1 -7
  432. package/src/components/ui/tile/Tile.stories.tsx +1 -1
  433. package/src/components/ui/tile/Tile.tsx +3 -0
  434. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  435. package/src/components/ui/toast/Toast.test.tsx +2 -8
  436. package/src/components/ui/toast/Toast.tsx +43 -53
  437. package/src/components/ui/toast/index.ts +0 -1
  438. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
  439. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
  440. package/src/components/ui/toolbar-button/ToolbarButton.tsx +25 -43
  441. package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
  442. package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
  443. package/src/components/ui/tooltip/Tooltip.tsx +55 -36
  444. package/src/components/ui/tooltip/index.ts +1 -1
  445. package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
  446. package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
  447. package/src/components/ui/trigger/index.ts +2 -0
  448. package/src/stories/PresetShowcase.stories.tsx +100 -47
  449. package/src/test/no-device-internals.test.ts +3 -3
  450. package/src/theme/ChoosingTokens.stories.tsx +48 -0
  451. package/src/theme/ColorPalettes.stories.tsx +62 -45
  452. package/src/theme/ColorPrimitives.stories.tsx +35 -35
  453. package/src/theme/Depth.stories.tsx +132 -65
  454. package/src/theme/DepthCalibration.stories.tsx +23 -21
  455. package/src/theme/ThemeProvider.test.tsx +4 -4
  456. package/src/theme/barrel.ts +7 -6
  457. package/src/theme/color-stories.coverage.test.ts +1 -1
  458. package/src/theme/color-utils.ts +41 -29
  459. package/src/theme/config.completeness.test.ts +1 -1
  460. package/src/theme/config.ts +28 -0
  461. package/src/theme/elevation.test.ts +82 -56
  462. package/src/theme/elevation.ts +77 -561
  463. package/src/theme/global.css +30 -2
  464. package/src/theme/grey-ramp.test.ts +24 -8
  465. package/src/theme/lift.test.ts +39 -0
  466. package/src/theme/lift.ts +102 -0
  467. package/src/theme/materials.test.ts +5 -2
  468. package/src/theme/materials.ts +38 -4
  469. package/src/theme/native-theming-guard.test.ts +5 -5
  470. package/src/theme/presets/apply.ts +4 -0
  471. package/src/theme/presets/audiobook.ts +5 -2
  472. package/src/theme/presets/default.ts +4 -0
  473. package/src/theme/presets/index.ts +14 -1
  474. package/src/theme/presets/types.ts +1 -1
  475. package/src/theme/semantic-contrast.test.ts +13 -4
  476. package/src/theme/status-distinctness.test.ts +66 -0
  477. package/src/theme/surface-planes.test.ts +37 -0
  478. package/src/theme/surface-planes.ts +68 -0
  479. package/src/theme/token-export-guard.test.ts +1 -3
  480. package/src/theme/tokens/primitives.test.ts +15 -7
  481. package/src/theme/tokens/primitives.ts +65 -33
  482. package/src/theme/tokens/semantic.ts +71 -37
  483. package/src/theme/wash-ladder.test.ts +58 -0
  484. package/src/theme/workout-tokens.ts +1 -7
  485. package/src/types/jest-axe.d.ts +2 -6
  486. package/src/types/raw-md.d.ts +5 -0
  487. package/src/utils/colors.ts +4 -4
  488. package/src/utils/form.ts +1 -3
  489. package/src/utils/index.ts +2 -7
  490. package/src/utils/number-format.ts +17 -0
  491. package/src/utils/workout-format.ts +15 -6
  492. package/src/web-jsx/jsx-runtime.ts +1 -5
  493. package/tailwind.config.js +5 -0
  494. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
  495. package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
  496. package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
  497. package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
  498. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
  499. package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
  500. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
  501. package/src/components/shell/DashboardShell.stories.tsx +0 -65
  502. package/src/components/shell/DashboardShell.tsx +0 -75
  503. package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
  504. package/src/theme/elevation.stories.tsx +0 -346
  505. package/src/utils/useTheme.ts +0 -72
  506. /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
  507. /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
  508. /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
  509. /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
@@ -78,27 +78,42 @@ export interface ButtonProps extends Omit<PressableProps, 'children'> {
78
78
 
79
79
  const variantStyles: Record<ButtonVariant, Record<ButtonColor, string>> = {
80
80
  solid: {
81
- primary: 'bg-brand-primary active:bg-brand-primary-dark active:scale-[0.98] web:hover:bg-brand-primary-dark web:active:scale-[0.98]',
82
- secondary: 'bg-brand-secondary active:bg-brand-secondary-dark active:scale-[0.98] web:hover:bg-brand-secondary-dark web:active:scale-[0.98]',
83
- success: 'bg-status-success active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]',
84
- error: 'bg-status-error active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]',
85
- warning: 'bg-status-warning active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]',
81
+ primary:
82
+ 'bg-brand-primary active:bg-brand-primary-dark active:scale-[0.98] web:hover:bg-brand-primary-dark web:active:scale-[0.98]',
83
+ secondary:
84
+ 'bg-brand-secondary active:bg-brand-secondary-dark active:scale-[0.98] web:hover:bg-brand-secondary-dark web:active:scale-[0.98]',
85
+ success:
86
+ 'bg-status-success active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]',
87
+ error:
88
+ 'bg-status-error active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]',
89
+ warning:
90
+ 'bg-status-warning active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]',
86
91
  info: 'bg-status-info active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]',
87
92
  },
88
93
  outline: {
89
- primary: 'border-2 border-brand-primary bg-transparent active:bg-brand-primary-subtle active:scale-[0.98] web:hover:bg-brand-primary-subtle web:active:scale-[0.98]',
90
- secondary: 'border-2 border-brand-secondary bg-transparent active:bg-brand-secondary-subtle active:scale-[0.98] web:hover:bg-brand-secondary-subtle web:active:scale-[0.98]',
91
- success: 'border-2 border-status-success bg-transparent active:bg-status-success-subtle active:scale-[0.98] web:hover:bg-status-success-subtle web:active:scale-[0.98]',
92
- error: 'border-2 border-status-error bg-transparent active:bg-status-error-subtle active:scale-[0.98] web:hover:bg-status-error-subtle web:active:scale-[0.98]',
93
- warning: 'border-2 border-status-warning bg-transparent active:bg-status-warning-subtle active:scale-[0.98] web:hover:bg-status-warning-subtle web:active:scale-[0.98]',
94
+ primary:
95
+ 'border-2 border-brand-primary bg-transparent active:bg-brand-primary-subtle active:scale-[0.98] web:hover:bg-brand-primary-subtle web:active:scale-[0.98]',
96
+ secondary:
97
+ 'border-2 border-brand-secondary bg-transparent active:bg-brand-secondary-subtle active:scale-[0.98] web:hover:bg-brand-secondary-subtle web:active:scale-[0.98]',
98
+ success:
99
+ 'border-2 border-status-success bg-transparent active:bg-status-success-subtle active:scale-[0.98] web:hover:bg-status-success-subtle web:active:scale-[0.98]',
100
+ error:
101
+ 'border-2 border-status-error bg-transparent active:bg-status-error-subtle active:scale-[0.98] web:hover:bg-status-error-subtle web:active:scale-[0.98]',
102
+ warning:
103
+ 'border-2 border-status-warning bg-transparent active:bg-status-warning-subtle active:scale-[0.98] web:hover:bg-status-warning-subtle web:active:scale-[0.98]',
94
104
  info: 'border-2 border-status-info bg-transparent active:bg-status-info-subtle active:scale-[0.98] web:hover:bg-status-info-subtle web:active:scale-[0.98]',
95
105
  },
96
106
  ghost: {
97
- primary: 'bg-transparent active:bg-brand-primary-subtle active:scale-[0.98] web:hover:bg-brand-primary-subtle web:active:scale-[0.98]',
98
- secondary: 'bg-transparent active:bg-brand-secondary-subtle active:scale-[0.98] web:hover:bg-brand-secondary-subtle web:active:scale-[0.98]',
99
- success: 'bg-transparent active:bg-status-success-subtle active:scale-[0.98] web:hover:bg-status-success-subtle web:active:scale-[0.98]',
100
- error: 'bg-transparent active:bg-status-error-subtle active:scale-[0.98] web:hover:bg-status-error-subtle web:active:scale-[0.98]',
101
- warning: 'bg-transparent active:bg-status-warning-subtle active:scale-[0.98] web:hover:bg-status-warning-subtle web:active:scale-[0.98]',
107
+ primary:
108
+ 'bg-transparent active:bg-brand-primary-subtle active:scale-[0.98] web:hover:bg-brand-primary-subtle web:active:scale-[0.98]',
109
+ secondary:
110
+ 'bg-transparent active:bg-brand-secondary-subtle active:scale-[0.98] web:hover:bg-brand-secondary-subtle web:active:scale-[0.98]',
111
+ success:
112
+ 'bg-transparent active:bg-status-success-subtle active:scale-[0.98] web:hover:bg-status-success-subtle web:active:scale-[0.98]',
113
+ error:
114
+ 'bg-transparent active:bg-status-error-subtle active:scale-[0.98] web:hover:bg-status-error-subtle web:active:scale-[0.98]',
115
+ warning:
116
+ 'bg-transparent active:bg-status-warning-subtle active:scale-[0.98] web:hover:bg-status-warning-subtle web:active:scale-[0.98]',
102
117
  info: 'bg-transparent active:bg-status-info-subtle active:scale-[0.98] web:hover:bg-status-info-subtle web:active:scale-[0.98]',
103
118
  },
104
119
  link: {
@@ -237,11 +252,7 @@ export const Button = forwardRef<View, ButtonProps>(function Button(
237
252
  )}
238
253
  {isLoading && loadingText ? (
239
254
  <Text
240
- className={cn(
241
- 'font-semibold',
242
- textSizeStyles[size],
243
- textStyles[variant][color]
244
- )}
255
+ className={cn('font-semibold', textSizeStyles[size], textStyles[variant][color])}
245
256
  style={{ color: textColorMap[variant][color] }}
246
257
  >
247
258
  {loadingText}
@@ -262,11 +273,7 @@ export interface ButtonTextProps {
262
273
  * Text component for Button. Use inside Button for consistent styling.
263
274
  */
264
275
  export function ButtonText({ children, className }: ButtonTextProps) {
265
- return (
266
- <Text className={cn('font-semibold text-inherit', className)}>
267
- {children}
268
- </Text>
269
- )
276
+ return <Text className={cn('font-semibold text-inherit', className)}>{children}</Text>
270
277
  }
271
278
 
272
279
  export interface ButtonIconProps {
@@ -15,16 +15,21 @@ import { Button, ButtonText } from '../button'
15
15
  const meta: Meta<typeof Card> = {
16
16
  title: 'Components/Molecules/Card',
17
17
  component: Card,
18
- tags: ['autodocs'],
18
+ parameters: {
19
+ docs: { description: { component: 'Composes **Surface**.' } },
20
+ },
21
+ tags: ['autodocs', 'status:stable', '!status:review'],
19
22
  argTypes: {
20
23
  variant: {
21
24
  control: 'select',
22
- options: ['elevated', 'outline', 'filled'],
25
+ options: ['elevated', 'accent', 'filled', 'outline', 'subtle'],
26
+ description:
27
+ 'elevated/accent lift with rim + shadow · filled lifts by tone only · outline/subtle stay on the host plane with a hairline edge',
23
28
  },
24
29
  elevation: {
25
30
  control: 'select',
26
31
  options: [1, 2, 3],
27
- description: 'Elevation level (1=subtle, 2=standard, 3=prominent)',
32
+ description: 'Planes to lift above the enclosing Surface (default 2: page → card plane)',
28
33
  },
29
34
  isInteractive: { control: 'boolean' },
30
35
  isLoading: { control: 'boolean' },
@@ -128,35 +133,65 @@ export const SimpleCard: Story = {
128
133
  ),
129
134
  }
130
135
 
136
+ // Each level is one more plane up the ramp from the page (base): elevated,
137
+ // raised, overlay. The lift (rim + shadow) grows with the number of planes crossed.
131
138
  export const ElevationLevels: Story = {
132
139
  render: () => (
133
140
  <View style={{ flexDirection: 'row', gap: 16, flexWrap: 'wrap' }}>
134
141
  <Card elevation={1} style={{ width: 140 }}>
135
142
  <CardContent>
136
- <Text className="text-text-primary font-semibold">Subtle (1)</Text>
143
+ <Text className="text-text-primary font-semibold">1 · elevated</Text>
137
144
  </CardContent>
138
145
  </Card>
139
146
  <Card elevation={2} style={{ width: 140 }}>
140
147
  <CardContent>
141
- <Text className="text-text-primary font-semibold">Standard (2)</Text>
148
+ <Text className="text-text-primary font-semibold">2 · raised</Text>
142
149
  </CardContent>
143
150
  </Card>
144
151
  <Card elevation={3} style={{ width: 140 }}>
145
152
  <CardContent>
146
- <Text className="text-text-primary font-semibold">Prominent (3)</Text>
153
+ <Text className="text-text-primary font-semibold">3 · overlay</Text>
147
154
  </CardContent>
148
155
  </Card>
149
156
  </View>
150
157
  ),
151
158
  }
152
159
 
160
+ // Depth is relative to the enclosing Surface: the same default Card steps up
161
+ // from wherever it is nested. Inside a card, prefer organising with an inset
162
+ // well or a tone-only `filled` tile over lifting again; a second lift is for a
163
+ // surface that genuinely floats over the first, and it clamps at overlay.
164
+ export const InsideACard: Story = {
165
+ render: () => (
166
+ <Card style={{ width: 360 }}>
167
+ <CardHeader>
168
+ <CardTitle>Outer · raised</CardTitle>
169
+ <CardDescription>Two planes up from the page</CardDescription>
170
+ </CardHeader>
171
+ <CardContent className="gap-3">
172
+ <CardInset className="p-3">
173
+ <Text className="text-text-secondary text-sm">CardInset · one plane down, recessed</Text>
174
+ </CardInset>
175
+ <Card variant="filled" elevation={1}>
176
+ <CardContent>
177
+ <Text className="text-text-primary text-sm">filled · one plane up, tone only</Text>
178
+ </CardContent>
179
+ </Card>
180
+ <Card>
181
+ <CardContent>
182
+ <Text className="text-text-primary text-sm">
183
+ lifted again · overlay (clamped) — sparingly
184
+ </Text>
185
+ </CardContent>
186
+ </Card>
187
+ </CardContent>
188
+ </Card>
189
+ ),
190
+ }
191
+
153
192
  export const Clickable: Story = {
154
193
  render: () => (
155
- <Card
156
- isInteractive
157
- onPress={() => console.log('Card clicked!')}
158
- style={{ width: 320 }}
159
- >
194
+ <Card isInteractive onPress={() => console.log('Card clicked!')} style={{ width: 320 }}>
160
195
  <CardHeader>
161
196
  <CardTitle>Clickable Card</CardTitle>
162
197
  <CardDescription>Click anywhere on this card</CardDescription>
@@ -199,49 +234,32 @@ export const Skeleton: Story = {
199
234
  ),
200
235
  }
201
236
 
237
+ // A CardInset is a pressed well one plane DOWN from the card, with the insetWell
238
+ // recess. Nesting one inside another steps down again.
202
239
  export const InsetElements: Story = {
203
240
  render: () => (
204
241
  <View style={{ gap: 16 }}>
205
- <Card elevation={2} style={{ width: 320 }}>
242
+ <Card style={{ width: 320 }}>
206
243
  <CardHeader>
207
244
  <CardTitle>Card with Inset</CardTitle>
208
- <CardDescription>Demonstrating inset elements within cards</CardDescription>
245
+ <CardDescription>A well one plane below the card</CardDescription>
209
246
  </CardHeader>
210
247
  <CardContent>
211
- <CardInset elevation={-1} className="p-4">
212
- <Text className="text-text-secondary text-sm">
213
- Shallow inset element (elevation -1)
214
- </Text>
215
- </CardInset>
216
- </CardContent>
217
- </Card>
218
-
219
- <Card elevation={3} style={{ width: 320 }}>
220
- <CardHeader>
221
- <CardTitle>Deep Inset</CardTitle>
222
- </CardHeader>
223
- <CardContent>
224
- <CardInset elevation={-2} className="p-4">
225
- <Text className="text-text-secondary text-sm">
226
- Deep inset element (elevation -2)
227
- </Text>
248
+ <CardInset className="p-4">
249
+ <Text className="text-text-secondary text-sm">Inset element (card − 1)</Text>
228
250
  </CardInset>
229
251
  </CardContent>
230
252
  </Card>
231
-
232
- <Card elevation={2} style={{ width: 320 }}>
253
+
254
+ <Card style={{ width: 320 }}>
233
255
  <CardHeader>
234
256
  <CardTitle>Nested Insets</CardTitle>
235
257
  </CardHeader>
236
258
  <CardContent>
237
- <CardInset elevation={-1} className="p-4 mb-4">
238
- <Text className="text-text-secondary text-sm mb-2">
239
- Outer inset (elevation -1)
240
- </Text>
241
- <CardInset elevation={-2} className="p-3">
242
- <Text className="text-text-secondary text-xs">
243
- Inner inset (elevation -2)
244
- </Text>
259
+ <CardInset className="p-4 mb-4">
260
+ <Text className="text-text-secondary text-sm mb-2">Outer inset (card − 1)</Text>
261
+ <CardInset className="p-3">
262
+ <Text className="text-text-secondary text-xs">Inner inset (card − 2)</Text>
245
263
  </CardInset>
246
264
  </CardInset>
247
265
  </CardContent>
@@ -268,52 +286,44 @@ export const StatusOutlineCards: Story = {
268
286
  <Text className="text-lg font-semibold text-text-primary mb-2">
269
287
  Status Cards with Custom Border Colors
270
288
  </Text>
271
-
289
+
272
290
  <Card variant="outline" borderColor={statusColors.success} style={{ width: 320 }}>
273
291
  <CardHeader>
274
292
  <CardTitle>Success</CardTitle>
275
293
  <CardDescription>Operation completed successfully</CardDescription>
276
294
  </CardHeader>
277
295
  <CardContent>
278
- <Text className="text-text-secondary">
279
- Your changes have been saved.
280
- </Text>
296
+ <Text className="text-text-secondary">Your changes have been saved.</Text>
281
297
  </CardContent>
282
298
  </Card>
283
-
299
+
284
300
  <Card variant="outline" borderColor={statusColors.error} style={{ width: 320 }}>
285
301
  <CardHeader>
286
302
  <CardTitle>Error</CardTitle>
287
303
  <CardDescription>Something went wrong</CardDescription>
288
304
  </CardHeader>
289
305
  <CardContent>
290
- <Text className="text-text-secondary">
291
- Please try again or contact support.
292
- </Text>
306
+ <Text className="text-text-secondary">Please try again or contact support.</Text>
293
307
  </CardContent>
294
308
  </Card>
295
-
309
+
296
310
  <Card variant="outline" borderColor={statusColors.warning} style={{ width: 320 }}>
297
311
  <CardHeader>
298
312
  <CardTitle>Warning</CardTitle>
299
313
  <CardDescription>Proceed with caution</CardDescription>
300
314
  </CardHeader>
301
315
  <CardContent>
302
- <Text className="text-text-secondary">
303
- This action cannot be undone.
304
- </Text>
316
+ <Text className="text-text-secondary">This action cannot be undone.</Text>
305
317
  </CardContent>
306
318
  </Card>
307
-
319
+
308
320
  <Card variant="outline" borderColor={statusColors.info} style={{ width: 320 }}>
309
321
  <CardHeader>
310
322
  <CardTitle>Information</CardTitle>
311
323
  <CardDescription>Good to know</CardDescription>
312
324
  </CardHeader>
313
325
  <CardContent>
314
- <Text className="text-text-secondary">
315
- New features are available in this release.
316
- </Text>
326
+ <Text className="text-text-secondary">New features are available in this release.</Text>
317
327
  </CardContent>
318
328
  </Card>
319
329
  </View>
@@ -326,10 +336,10 @@ export const StatusFilledCards: Story = {
326
336
  <Text className="text-lg font-semibold text-text-primary mb-2">
327
337
  Status Cards with Custom Background Colors
328
338
  </Text>
329
-
330
- <Card
331
- variant="outline"
332
- borderColor={statusColors.success}
339
+
340
+ <Card
341
+ variant="outline"
342
+ borderColor={statusColors.success}
333
343
  bgColor={statusColors.successSubtle}
334
344
  style={{ width: 320 }}
335
345
  >
@@ -338,15 +348,13 @@ export const StatusFilledCards: Story = {
338
348
  <CardDescription>Operation completed successfully</CardDescription>
339
349
  </CardHeader>
340
350
  <CardContent>
341
- <Text className="text-text-secondary">
342
- Your changes have been saved.
343
- </Text>
351
+ <Text className="text-text-secondary">Your changes have been saved.</Text>
344
352
  </CardContent>
345
353
  </Card>
346
-
347
- <Card
348
- variant="outline"
349
- borderColor={statusColors.error}
354
+
355
+ <Card
356
+ variant="outline"
357
+ borderColor={statusColors.error}
350
358
  bgColor={statusColors.errorSubtle}
351
359
  style={{ width: 320 }}
352
360
  >
@@ -355,15 +363,13 @@ export const StatusFilledCards: Story = {
355
363
  <CardDescription>Something went wrong</CardDescription>
356
364
  </CardHeader>
357
365
  <CardContent>
358
- <Text className="text-text-secondary">
359
- Please try again or contact support.
360
- </Text>
366
+ <Text className="text-text-secondary">Please try again or contact support.</Text>
361
367
  </CardContent>
362
368
  </Card>
363
-
364
- <Card
365
- variant="outline"
366
- borderColor={statusColors.warning}
369
+
370
+ <Card
371
+ variant="outline"
372
+ borderColor={statusColors.warning}
367
373
  bgColor={statusColors.warningSubtle}
368
374
  style={{ width: 320 }}
369
375
  >
@@ -372,15 +378,13 @@ export const StatusFilledCards: Story = {
372
378
  <CardDescription>Proceed with caution</CardDescription>
373
379
  </CardHeader>
374
380
  <CardContent>
375
- <Text className="text-text-secondary">
376
- This action cannot be undone.
377
- </Text>
381
+ <Text className="text-text-secondary">This action cannot be undone.</Text>
378
382
  </CardContent>
379
383
  </Card>
380
-
381
- <Card
382
- variant="outline"
383
- borderColor={statusColors.info}
384
+
385
+ <Card
386
+ variant="outline"
387
+ borderColor={statusColors.info}
384
388
  bgColor={statusColors.infoSubtle}
385
389
  style={{ width: 320 }}
386
390
  >
@@ -389,9 +393,7 @@ export const StatusFilledCards: Story = {
389
393
  <CardDescription>Good to know</CardDescription>
390
394
  </CardHeader>
391
395
  <CardContent>
392
- <Text className="text-text-secondary">
393
- New features are available in this release.
394
- </Text>
396
+ <Text className="text-text-secondary">New features are available in this release.</Text>
395
397
  </CardContent>
396
398
  </Card>
397
399
  </View>
@@ -401,10 +403,8 @@ export const StatusFilledCards: Story = {
401
403
  export const BrandColoredCards: Story = {
402
404
  render: () => (
403
405
  <View style={{ gap: 16 }}>
404
- <Text className="text-lg font-semibold text-text-primary mb-2">
405
- Brand Colored Cards
406
- </Text>
407
-
406
+ <Text className="text-lg font-semibold text-text-primary mb-2">Brand Colored Cards</Text>
407
+
408
408
  <Card
409
409
  variant="outline"
410
410
  borderColor="var(--color-brand-primary)"
@@ -416,9 +416,7 @@ export const BrandColoredCards: Story = {
416
416
  <CardDescription>Orange brand color</CardDescription>
417
417
  </CardHeader>
418
418
  <CardContent>
419
- <Text className="text-text-secondary">
420
- Card with primary brand color styling.
421
- </Text>
419
+ <Text className="text-text-secondary">Card with primary brand color styling.</Text>
422
420
  </CardContent>
423
421
  </Card>
424
422
 
@@ -433,9 +431,7 @@ export const BrandColoredCards: Story = {
433
431
  <CardDescription>Steel brand color</CardDescription>
434
432
  </CardHeader>
435
433
  <CardContent>
436
- <Text className="text-text-secondary">
437
- Card with secondary brand color styling.
438
- </Text>
434
+ <Text className="text-text-secondary">Card with secondary brand color styling.</Text>
439
435
  </CardContent>
440
436
  </Card>
441
437
  </View>
@@ -11,6 +11,78 @@ import {
11
11
  CardSkeleton,
12
12
  CardInset,
13
13
  } from './Card'
14
+ import { greyRamp } from '../../../theme/tokens/primitives'
15
+
16
+ // Planes by RAMP STEP, never by literal bytes — see Surface.test.tsx.
17
+ const BASE = greyRamp[925]
18
+ const ELEVATED = greyRamp[900]
19
+ const RAISED = greyRamp[875]
20
+ const OVERLAY = greyRamp[850]
21
+
22
+ describe('Card depth', () => {
23
+ it('lifts two planes from the page onto the card plane with rim + shadow', () => {
24
+ render(<Card testID="card" />)
25
+ const el = screen.getByTestId('card')
26
+ expect(el).toHaveStyle({ backgroundColor: RAISED })
27
+ expect(el.style.boxShadow).toContain('inset 0 1px 0')
28
+ expect(el.style.boxShadow).toMatch(/0 \d+px \d+px rgba\(0,0,0/)
29
+ })
30
+
31
+ it('is relative: a card nested in a card steps up again and clamps at overlay', () => {
32
+ render(
33
+ <Card>
34
+ <Card testID="inner">
35
+ <Card testID="innermost" />
36
+ </Card>
37
+ </Card>
38
+ )
39
+ expect(screen.getByTestId('inner')).toHaveStyle({ backgroundColor: OVERLAY })
40
+ expect(screen.getByTestId('innermost')).toHaveStyle({ backgroundColor: OVERLAY })
41
+ })
42
+
43
+ it('outline and subtle stay on the host plane with an edge and no lift', () => {
44
+ render(
45
+ <>
46
+ <Card variant="outline" testID="outline" />
47
+ <Card variant="subtle" testID="subtle" />
48
+ </>
49
+ )
50
+ for (const id of ['outline', 'subtle']) {
51
+ const el = screen.getByTestId(id)
52
+ expect(el).toHaveStyle({ backgroundColor: BASE })
53
+ expect(el.style.boxShadow).toBe('')
54
+ }
55
+ })
56
+
57
+ it('filled lifts by tone only', () => {
58
+ render(<Card variant="filled" elevation={1} testID="filled" />)
59
+ const el = screen.getByTestId('filled')
60
+ expect(el).toHaveStyle({ backgroundColor: ELEVATED })
61
+ expect(el.style.boxShadow).toBe('')
62
+ })
63
+
64
+ it('bgColor is the override; a bg-* className is not', () => {
65
+ render(
66
+ <>
67
+ <Card bgColor="#00ff00" testID="bg" />
68
+ <Card className="bg-surface-overlay" testID="cls" />
69
+ </>
70
+ )
71
+ expect(screen.getByTestId('bg')).toHaveStyle({ backgroundColor: '#00ff00' })
72
+ expect(screen.getByTestId('cls')).toHaveStyle({ backgroundColor: RAISED })
73
+ })
74
+
75
+ it('CardInset presses one plane down from the card', () => {
76
+ render(
77
+ <Card>
78
+ <CardInset testID="well" />
79
+ </Card>
80
+ )
81
+ const el = screen.getByTestId('well')
82
+ expect(el).toHaveStyle({ backgroundColor: ELEVATED })
83
+ expect(el.style.boxShadow).toContain('inset')
84
+ })
85
+ })
14
86
 
15
87
  describe('Card', () => {
16
88
  it('renders children correctly', () => {
@@ -206,13 +278,15 @@ describe('Card', () => {
206
278
  expect(screen.getByText('Inset content')).toBeInTheDocument()
207
279
  })
208
280
 
209
- it('accepts elevation prop', () => {
210
- const { container } = render(
211
- <CardInset elevation={-2}>
212
- <span>Deep inset</span>
213
- </CardInset>
281
+ it('nests: a well inside a well steps down again', () => {
282
+ render(
283
+ <Card>
284
+ <CardInset>
285
+ <CardInset testID="deeper" />
286
+ </CardInset>
287
+ </Card>
214
288
  )
215
- expect(container).toBeInTheDocument()
289
+ expect(screen.getByTestId('deeper')).toHaveStyle({ backgroundColor: BASE })
216
290
  })
217
291
  })
218
292