@titan-design/react-ui 0.6.0 → 0.8.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 (258) hide show
  1. package/dist/bodymap.js +12 -7
  2. package/dist/bodymap.js.map +1 -1
  3. package/dist/bodymap.mjs +12 -7
  4. package/dist/bodymap.mjs.map +1 -1
  5. package/dist/index.d.mts +956 -128
  6. package/dist/index.d.ts +956 -128
  7. package/dist/index.js +2873 -981
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +2826 -982
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/{pages-MO0JCySL.d.mts → pages-DCFBqp79.d.mts} +289 -57
  12. package/dist/{pages-D7Jlssvp.d.ts → pages-_fI3-x7Z.d.ts} +289 -57
  13. package/dist/pages.d.mts +1 -1
  14. package/dist/pages.d.ts +1 -1
  15. package/dist/pages.js +1659 -799
  16. package/dist/pages.js.map +1 -1
  17. package/dist/pages.mjs +1660 -800
  18. package/dist/pages.mjs.map +1 -1
  19. package/dist/theme/index.d.mts +16 -82
  20. package/dist/theme/index.d.ts +16 -82
  21. package/dist/theme/index.js +13 -115
  22. package/dist/theme/index.js.map +1 -1
  23. package/dist/theme/index.mjs +13 -115
  24. package/dist/theme/index.mjs.map +1 -1
  25. package/dist/theme/tokens-css.js +14 -6
  26. package/dist/theme/tokens-css.js.map +1 -1
  27. package/dist/theme/tokens-css.mjs +14 -6
  28. package/dist/theme/tokens-css.mjs.map +1 -1
  29. package/package.json +1 -1
  30. package/src/arch/Architecture.stories.tsx +870 -0
  31. package/src/arch/annotations.json +48 -0
  32. package/src/arch/arch-graph.json +4301 -0
  33. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +90 -0
  34. package/src/components/custom/CircularTimer/CircularTimer.test.tsx +62 -0
  35. package/src/components/custom/CircularTimer/CircularTimer.tsx +112 -0
  36. package/src/components/custom/CircularTimer/index.ts +1 -0
  37. package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
  38. package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
  39. package/src/components/custom/Gauge/Gauge.stories.tsx +1 -1
  40. package/src/components/custom/Metric/Metric.stories.tsx +1 -1
  41. package/src/components/custom/Scatter/Scatter.stories.tsx +1 -1
  42. package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
  43. package/src/components/custom/Table/Table.stories.tsx +1 -1
  44. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +62 -0
  45. package/src/components/custom/TimerReadout/TimerReadout.test.tsx +72 -0
  46. package/src/components/custom/TimerReadout/TimerReadout.tsx +75 -0
  47. package/src/components/custom/TimerReadout/index.ts +1 -0
  48. package/src/components/custom/Treemap/Treemap.stories.tsx +1 -1
  49. package/src/components/custom/Typography/Typography.stories.tsx +1 -1
  50. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +21 -13
  51. package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +16 -13
  52. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +9 -15
  53. package/src/components/custom/Workout/BaseBadge.stories.tsx +1 -1
  54. package/src/components/custom/Workout/BodyMap.stories.tsx +1 -1
  55. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +1 -1
  56. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +1 -1
  57. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  58. package/src/components/custom/Workout/ExerciseCard.stories.tsx +51 -66
  59. package/src/components/custom/Workout/ExerciseCard.test.tsx +146 -143
  60. package/src/components/custom/Workout/ExerciseCard.tsx +176 -198
  61. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +99 -0
  62. package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +72 -0
  63. package/src/components/custom/Workout/ExerciseCardHeading.tsx +43 -0
  64. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +151 -0
  65. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +5 -3
  66. package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +4 -4
  67. package/src/components/custom/Workout/ExerciseDetailPage.tsx +4 -5
  68. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +81 -0
  69. package/src/components/custom/Workout/ExerciseHeading.test.tsx +77 -0
  70. package/src/components/custom/Workout/ExerciseHeading.tsx +85 -0
  71. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +110 -0
  72. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +93 -0
  73. package/src/components/custom/Workout/ExerciseIndicator.tsx +120 -0
  74. package/src/components/custom/Workout/FatigueMeter.stories.tsx +51 -0
  75. package/src/components/custom/Workout/FatigueMeter.test.tsx +85 -0
  76. package/src/components/custom/Workout/FatigueMeter.tsx +86 -0
  77. package/src/components/custom/Workout/InputBar.stories.tsx +1 -1
  78. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  79. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +153 -0
  80. package/src/components/custom/Workout/LiveAuraFrame.test.tsx +74 -0
  81. package/src/components/custom/Workout/LiveAuraFrame.tsx +105 -0
  82. package/src/components/custom/Workout/MesoCard.stories.tsx +1 -1
  83. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  84. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +1 -1
  85. package/src/components/custom/Workout/MetricTiles.stories.tsx +60 -0
  86. package/src/components/custom/Workout/MetricTiles.test.tsx +58 -0
  87. package/src/components/custom/Workout/MetricTiles.tsx +48 -0
  88. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +1 -1
  89. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
  90. package/src/components/custom/Workout/PrBadge.stories.tsx +1 -1
  91. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +1 -1
  92. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +4 -16
  93. package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -6
  94. package/src/components/custom/Workout/README.md +193 -4
  95. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +1 -1
  96. package/src/components/custom/Workout/RestTimer.stories.tsx +133 -3
  97. package/src/components/custom/Workout/RestTimer.test.tsx +73 -0
  98. package/src/components/custom/Workout/RestTimer.tsx +155 -59
  99. package/src/components/custom/Workout/RowInventory.stories.tsx +405 -0
  100. package/src/components/custom/Workout/S3FullRail.stories.tsx +34 -0
  101. package/src/components/custom/Workout/S3SessionPace.stories.tsx +95 -0
  102. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +61 -0
  103. package/src/components/custom/Workout/S3SetTypes.stories.tsx +176 -0
  104. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +240 -0
  105. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +40 -0
  106. package/src/components/custom/Workout/ScheduleTiles.test.tsx +34 -0
  107. package/src/components/custom/Workout/ScheduleTiles.tsx +70 -0
  108. package/src/components/custom/Workout/SegmentedBar.stories.tsx +99 -0
  109. package/src/components/custom/Workout/SegmentedBar.test.tsx +77 -0
  110. package/src/components/custom/Workout/SegmentedBar.tsx +172 -0
  111. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +50 -0
  112. package/src/components/custom/Workout/SegmentedProgressBar.test.tsx +80 -0
  113. package/src/components/custom/Workout/SegmentedProgressBar.tsx +67 -0
  114. package/src/components/custom/Workout/SessionHeader.stories.tsx +121 -0
  115. package/src/components/custom/Workout/SessionHeader.test.tsx +122 -0
  116. package/src/components/custom/Workout/SessionHeader.tsx +152 -0
  117. package/src/components/custom/Workout/SessionRail.stories.tsx +153 -0
  118. package/src/components/custom/Workout/SessionRail.test.tsx +86 -0
  119. package/src/components/custom/Workout/SessionRail.tsx +126 -0
  120. package/src/components/custom/Workout/SetBar.stories.tsx +124 -0
  121. package/src/components/custom/Workout/SetBar.test.tsx +123 -0
  122. package/src/components/custom/Workout/SetBar.tsx +171 -0
  123. package/src/components/custom/Workout/SetRow.stories.tsx +50 -100
  124. package/src/components/custom/Workout/SetRow.test.tsx +94 -166
  125. package/src/components/custom/Workout/SetRow.tsx +169 -232
  126. package/src/components/custom/Workout/SetStrip.stories.tsx +154 -0
  127. package/src/components/custom/Workout/SetStrip.test.tsx +109 -0
  128. package/src/components/custom/Workout/SetStrip.tsx +71 -0
  129. package/src/components/custom/Workout/SetTableHeader.stories.tsx +66 -0
  130. package/src/components/custom/Workout/SetTableHeader.test.tsx +47 -0
  131. package/src/components/custom/Workout/SetTableHeader.tsx +88 -0
  132. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +47 -0
  133. package/src/components/custom/Workout/SetsRepsLoad.test.tsx +44 -0
  134. package/src/components/custom/Workout/SetsRepsLoad.tsx +52 -0
  135. package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
  136. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  137. package/src/components/custom/Workout/StatusPill.stories.tsx +59 -0
  138. package/src/components/custom/Workout/StatusPill.test.tsx +63 -0
  139. package/src/components/custom/Workout/StatusPill.tsx +88 -0
  140. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +1 -1
  141. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +1 -1
  142. package/src/components/custom/Workout/TempoBar.stories.tsx +70 -1
  143. package/src/components/custom/Workout/TempoBar.test.tsx +119 -4
  144. package/src/components/custom/Workout/TempoBar.tsx +107 -22
  145. package/src/components/custom/Workout/TempoDisplay.stories.tsx +12 -1
  146. package/src/components/custom/Workout/TempoDisplay.tsx +23 -33
  147. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +1 -1
  148. package/src/components/custom/Workout/VelocityStrip.modalities.stories.tsx +254 -0
  149. package/src/components/custom/Workout/VelocityStrip.responsive.stories.tsx +145 -0
  150. package/src/components/custom/Workout/VelocityStrip.stories.tsx +262 -56
  151. package/src/components/custom/Workout/VelocityStrip.test.tsx +440 -141
  152. package/src/components/custom/Workout/VelocityStrip.tsx +776 -141
  153. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +73 -0
  154. package/src/components/custom/Workout/VolumeLandmarkBar.test.tsx +119 -0
  155. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +154 -0
  156. package/src/components/custom/Workout/WeekRow.stories.tsx +1 -1
  157. package/src/components/custom/Workout/WeightBadge.stories.tsx +1 -1
  158. package/src/components/custom/Workout/WorkoutCard.stories.tsx +2 -6
  159. package/src/components/custom/Workout/WorkoutCard.test.tsx +13 -46
  160. package/src/components/custom/Workout/WorkoutPill.stories.tsx +1 -1
  161. package/src/components/custom/Workout/ZoneTrack.stories.tsx +139 -0
  162. package/src/components/custom/Workout/ZoneTrack.test.tsx +234 -0
  163. package/src/components/custom/Workout/ZoneTrack.tsx +373 -0
  164. package/src/components/custom/Workout/index.ts +55 -2
  165. package/src/components/custom/Workout/metricText.stories.tsx +69 -0
  166. package/src/components/custom/Workout/metricText.tsx +34 -0
  167. package/src/components/custom/Workout/paceTone.test.ts +29 -0
  168. package/src/components/custom/Workout/paceTone.ts +27 -0
  169. package/src/components/custom/Workout/setHeadingKit.tsx +177 -0
  170. package/src/components/custom/index.ts +2 -0
  171. package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
  172. package/src/components/icons/icons.stories.tsx +67 -2
  173. package/src/components/icons/icons.test.tsx +32 -2
  174. package/src/components/icons/icons.tsx +108 -0
  175. package/src/components/shell/BrandLockup.stories.tsx +3 -3
  176. package/src/components/shell/DashboardShell.stories.tsx +65 -0
  177. package/src/components/shell/DashboardShell.test.tsx +42 -0
  178. package/src/components/shell/DashboardShell.tsx +74 -0
  179. package/src/components/shell/DeviceIndicator.stories.tsx +2 -2
  180. package/src/components/shell/DeviceMenu.stories.tsx +5 -5
  181. package/src/components/shell/DeviceRow.stories.tsx +3 -3
  182. package/src/components/shell/NavItem.stories.tsx +52 -0
  183. package/src/components/shell/NavItem.test.tsx +35 -0
  184. package/src/components/shell/NavItem.tsx +75 -0
  185. package/src/components/shell/README.md +30 -0
  186. package/src/components/shell/SessionRailSpecimen.stories.tsx +753 -0
  187. package/src/components/shell/SessionStatePill.stories.tsx +3 -3
  188. package/src/components/shell/SessionStatePill.tsx +1 -1
  189. package/src/components/shell/SideNav.stories.tsx +81 -0
  190. package/src/components/shell/SideNav.test.tsx +51 -0
  191. package/src/components/shell/SideNav.tsx +74 -0
  192. package/src/components/shell/TopBar.stories.tsx +5 -5
  193. package/src/components/shell/index.ts +5 -0
  194. package/src/components/ui/alert/Alert.stories.tsx +86 -3
  195. package/src/components/ui/alert/Alert.test.tsx +52 -0
  196. package/src/components/ui/alert/Alert.tsx +54 -20
  197. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
  198. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  199. package/src/components/ui/badge/Badge.stories.tsx +1 -1
  200. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  201. package/src/components/ui/button/Button.stories.tsx +1 -1
  202. package/src/components/ui/card/Card.stories.tsx +1 -1
  203. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  204. package/src/components/ui/chip/Chip.stories.tsx +1 -1
  205. package/src/components/ui/collapse/Collapse.stories.tsx +1 -1
  206. package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
  207. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  208. package/src/components/ui/drawer/Drawer.stories.tsx +1 -1
  209. package/src/components/ui/form-field/FormField.stories.tsx +1 -1
  210. package/src/components/ui/help-tip/HelpTip.stories.tsx +1 -1
  211. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  212. package/src/components/ui/index.ts +1 -0
  213. package/src/components/ui/indicator/Indicator.stories.tsx +2 -2
  214. package/src/components/ui/indicator/Indicator.test.tsx +1 -0
  215. package/src/components/ui/indicator/Indicator.tsx +6 -1
  216. package/src/components/ui/input/Input.stories.tsx +1 -1
  217. package/src/components/ui/link/Link.stories.tsx +1 -1
  218. package/src/components/ui/list-item/ListItem.stories.tsx +1 -1
  219. package/src/components/ui/menu/Menu.stories.tsx +1 -1
  220. package/src/components/ui/modal/Modal.stories.tsx +1 -1
  221. package/src/components/ui/pill/Pill.stories.tsx +1 -1
  222. package/src/components/ui/popover/Popover.stories.tsx +1 -1
  223. package/src/components/ui/progress/Progress.stories.tsx +1 -1
  224. package/src/components/ui/progress/Progress.tsx +47 -22
  225. package/src/components/ui/radio/Radio.stories.tsx +1 -1
  226. package/src/components/ui/section/Section.stories.tsx +1 -1
  227. package/src/components/ui/select/Select.stories.tsx +1 -1
  228. package/src/components/ui/skeleton/Skeleton.stories.tsx +1 -1
  229. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  230. package/src/components/ui/stack/Stack.stories.tsx +1 -1
  231. package/src/components/ui/surface/Surface.stories.tsx +1 -1
  232. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  233. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  234. package/src/components/ui/tile/Tile.stories.tsx +79 -0
  235. package/src/components/ui/tile/Tile.test.tsx +48 -0
  236. package/src/components/ui/tile/Tile.tsx +64 -0
  237. package/src/components/ui/tile/index.ts +2 -0
  238. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  239. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
  240. package/src/components/ui/tooltip/Tooltip.stories.tsx +1 -1
  241. package/src/examples/react-hook-form/ReactHookForm.stories.tsx +1 -1
  242. package/src/hooks/index.ts +2 -0
  243. package/src/hooks/useTimer.test.ts +150 -0
  244. package/src/hooks/useTimer.ts +77 -0
  245. package/src/index.ts +3 -0
  246. package/src/pages.ts +1 -1
  247. package/src/stories/PresetShowcase.stories.tsx +1 -1
  248. package/src/stories/ThemePresets.stories.tsx +1 -1
  249. package/src/theme/ColorSystem.stories.tsx +1 -1
  250. package/src/theme/Colors.stories.tsx +5 -8
  251. package/src/theme/config.ts +4 -0
  252. package/src/theme/elevation.stories.tsx +1 -1
  253. package/src/theme/global.css +5 -1
  254. package/src/theme/shadows.stories.tsx +1 -1
  255. package/src/theme/tokens/primitives.ts +11 -107
  256. package/src/theme/tokens/semantic.ts +8 -0
  257. package/src/theme/workout-tokens.ts +11 -7
  258. package/tailwind.config.js +5 -0
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Chip } from './Chip'
4
4
 
5
5
  const meta: Meta<typeof Chip> = {
6
- title: 'Components/Chip',
6
+ title: 'Components/Atoms/Chip',
7
7
  component: Chip,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -12,7 +12,7 @@ import {
12
12
  } from './Collapse'
13
13
 
14
14
  const meta: Meta<typeof Accordion> = {
15
- title: 'Components/Accordion',
15
+ title: 'Components/Organisms/Accordion',
16
16
  component: Accordion,
17
17
  tags: ['autodocs'],
18
18
  argTypes: {
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { DataRow } from './DataRow'
4
4
 
5
5
  const meta: Meta<typeof DataRow> = {
6
- title: 'Components/DataRow',
6
+ title: 'Components/Molecules/DataRow',
7
7
  component: DataRow,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { Divider } from './Divider'
4
4
 
5
5
  const meta: Meta<typeof Divider> = {
6
- title: 'Components/Divider',
6
+ title: 'Components/Atoms/Divider',
7
7
  component: Divider,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -5,7 +5,7 @@ import { Drawer, DrawerBody, DrawerFooter } from './Drawer'
5
5
  import { Button, ButtonText } from '../button'
6
6
 
7
7
  const meta: Meta<typeof Drawer> = {
8
- title: 'Components/Drawer',
8
+ title: 'Components/Organisms/Drawer',
9
9
  component: Drawer,
10
10
  tags: ['autodocs'],
11
11
  argTypes: {
@@ -5,7 +5,7 @@ import { Button, ButtonText } from '../button'
5
5
  import { Input } from '../input'
6
6
 
7
7
  const meta: Meta<typeof FormField> = {
8
- title: 'Components/FormField',
8
+ title: 'Components/Molecules/FormField',
9
9
  component: FormField,
10
10
  tags: ['autodocs'],
11
11
  argTypes: {
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { HelpTip, LabelWithHelp } from './HelpTip'
4
4
 
5
5
  const meta: Meta<typeof HelpTip> = {
6
- title: 'Components/HelpTip',
6
+ title: 'Components/Molecules/HelpTip',
7
7
  component: HelpTip,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -53,7 +53,7 @@ function BoltIcon({ size = 20, className }: { size?: number; className?: string
53
53
  }
54
54
 
55
55
  const meta: Meta<typeof IconBox> = {
56
- title: 'Components/IconBox',
56
+ title: 'Components/Atoms/IconBox',
57
57
  component: IconBox,
58
58
  tags: ['autodocs'],
59
59
  argTypes: {
@@ -36,3 +36,4 @@ export * from './surface'
36
36
  export * from './list-item'
37
37
  export * from './indicator'
38
38
  export * from './pill'
39
+ export * from './tile'
@@ -3,14 +3,14 @@ import { View } from 'react-native'
3
3
  import { Indicator } from './Indicator'
4
4
 
5
5
  const meta: Meta<typeof Indicator> = {
6
- title: 'Components/Indicator',
6
+ title: 'Components/Atoms/Indicator',
7
7
  component: Indicator,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
10
10
  size: { control: 'select', options: ['xs', 'sm', 'md', 'lg'] },
11
11
  color: {
12
12
  control: 'select',
13
- options: ['default', 'primary', 'success', 'error', 'warning', 'info'],
13
+ options: ['default', 'primary', 'success', 'live', 'error', 'warning', 'info'],
14
14
  },
15
15
  glow: { control: 'boolean' },
16
16
  ring: { control: 'boolean' },
@@ -22,6 +22,7 @@ describe('Indicator', () => {
22
22
  'default',
23
23
  'primary',
24
24
  'success',
25
+ 'live',
25
26
  'error',
26
27
  'warning',
27
28
  'info',
@@ -6,6 +6,7 @@ export type IndicatorColor =
6
6
  | 'default'
7
7
  | 'primary'
8
8
  | 'success'
9
+ | 'live'
9
10
  | 'error'
10
11
  | 'warning'
11
12
  | 'info'
@@ -42,6 +43,7 @@ const colorStyles: Record<IndicatorColor, string> = {
42
43
  default: 'bg-text-tertiary',
43
44
  primary: 'bg-brand-primary',
44
45
  success: 'bg-status-success',
46
+ live: 'bg-status-live',
45
47
  error: 'bg-status-error',
46
48
  warning: 'bg-status-warning',
47
49
  info: 'bg-status-info',
@@ -98,7 +100,10 @@ export function Indicator({
98
100
  colorClass,
99
101
  pulseMode === 'opacity' && 'animate-pulse',
100
102
  ring && 'border-2 border-background-base',
101
- glow && !customColor && color === 'success' && 'shadow-[0_0_6px_rgba(46,213,115,0.6)]',
103
+ glow &&
104
+ !customColor &&
105
+ (color === 'success' || color === 'live') &&
106
+ 'shadow-[0_0_6px_rgba(46,213,115,0.6)]',
102
107
  glow && !customColor && color === 'error' && 'shadow-[0_0_6px_rgba(239,68,68,0.6)]',
103
108
  glow && !customColor && color === 'warning' && 'shadow-[0_0_6px_rgba(245,158,11,0.6)]',
104
109
  glow && !customColor && color === 'primary' && 'shadow-[0_0_6px_rgba(255,121,0,0.6)]',
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { Input, InputGroup, PasswordInput } from './Input'
4
4
 
5
5
  const meta: Meta<typeof Input> = {
6
- title: 'Components/Input',
6
+ title: 'Components/Molecules/Input',
7
7
  component: Input,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Link } from './Link'
4
4
 
5
5
  const meta: Meta<typeof Link> = {
6
- title: 'Components/Link',
6
+ title: 'Components/Atoms/Link',
7
7
  component: Link,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -45,7 +45,7 @@ function ChevronRight({ size = 16 }: { size?: number }) {
45
45
  }
46
46
 
47
47
  const meta: Meta<typeof ListItem> = {
48
- title: 'Components/ListItem',
48
+ title: 'Components/Molecules/ListItem',
49
49
  component: ListItem,
50
50
  tags: ['autodocs'],
51
51
  }
@@ -4,7 +4,7 @@ import { Menu, MenuTrigger, MenuList, MenuItem, MenuDivider, MenuGroup } from '.
4
4
  import { Button, ButtonText } from '../button/Button'
5
5
 
6
6
  const meta: Meta<typeof Menu> = {
7
- title: 'Components/Menu',
7
+ title: 'Components/Molecules/Menu',
8
8
  component: Menu,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -13,7 +13,7 @@ import {
13
13
  import { Button, ButtonText } from '../button/Button'
14
14
 
15
15
  const meta: Meta<typeof Modal> = {
16
- title: 'Components/Modal',
16
+ title: 'Components/Organisms/Modal',
17
17
  component: Modal,
18
18
  tags: ['autodocs'],
19
19
  argTypes: {
@@ -4,7 +4,7 @@ import { Pill } from './Pill'
4
4
  import { Indicator } from '../indicator'
5
5
 
6
6
  const meta: Meta<typeof Pill> = {
7
- title: 'Components/Pill',
7
+ title: 'Components/Atoms/Pill',
8
8
  component: Pill,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -4,7 +4,7 @@ import { Popover, PopoverTrigger, PopoverContent, PopoverCloseButton } from './P
4
4
  import { Button, ButtonText } from '../button/Button'
5
5
 
6
6
  const meta: Meta<typeof Popover> = {
7
- title: 'Components/Popover',
7
+ title: 'Components/Molecules/Popover',
8
8
  component: Popover,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { Progress, CircularProgress, ProgressSteps } from './Progress'
4
4
 
5
5
  const meta: Meta<typeof Progress> = {
6
- title: 'Components/Progress',
6
+ title: 'Components/Molecules/Progress',
7
7
  component: Progress,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -7,7 +7,7 @@ export type ProgressColor = 'primary' | 'secondary' | 'success' | 'error' | 'war
7
7
  export type ProgressVariant = 'linear' | 'circular'
8
8
 
9
9
  /** Maps the color prop to a CSS variable reference for inline styles */
10
- const colorVarMap: Record<ProgressColor, string> = {
10
+ export const colorVarMap: Record<ProgressColor, string> = {
11
11
  primary: 'var(--color-brand-primary)',
12
12
  secondary: 'var(--color-brand-secondary)',
13
13
  success: 'var(--color-status-success)',
@@ -101,13 +101,9 @@ export function Progress({
101
101
  {/* Label and Value Row */}
102
102
  {(label || showValue) && (
103
103
  <View className="flex-row justify-between items-center mb-1">
104
- {label && (
105
- <Text className="text-sm text-text-secondary">{label}</Text>
106
- )}
104
+ {label && <Text className="text-sm text-text-secondary">{label}</Text>}
107
105
  {showValue && !isIndeterminate && (
108
- <Text className="text-sm font-medium text-text-primary">
109
- {formatValue(value, max)}
110
- </Text>
106
+ <Text className="text-sm font-medium text-text-primary">{formatValue(value, max)}</Text>
111
107
  )}
112
108
  </View>
113
109
  )}
@@ -162,6 +158,19 @@ export interface CircularProgressProps extends ViewProps {
162
158
  showValue?: boolean
163
159
  /** Custom value format function */
164
160
  formatValue?: (value: number, max: number) => string
161
+ /**
162
+ * Custom center content (a numeral, a timer readout, an icon). When provided it
163
+ * replaces the {@link showValue} text — the ring becomes a generic container for
164
+ * any centered element. See {@link CircularTimer} for the batteries-included timer.
165
+ */
166
+ children?: React.ReactNode
167
+ /**
168
+ * Fill the parent container (responsive) instead of drawing a fixed `size` box.
169
+ * The SVG uses a `0 0 size size` viewBox scaled to the container, so `size` still
170
+ * sets the geometry proportions (radius, stroke) while the ring grows/shrinks with
171
+ * its parent — e.g. a wall column. Default false (fixed `size` px).
172
+ */
173
+ fill?: boolean
165
174
  /** Additional className */
166
175
  className?: string
167
176
  }
@@ -181,6 +190,8 @@ export function CircularProgress({
181
190
  color = 'primary',
182
191
  showValue = false,
183
192
  formatValue = (v, m) => `${Math.round((v / m) * 100)}%`,
193
+ children,
194
+ fill = false,
184
195
  className,
185
196
  ...props
186
197
  }: CircularProgressProps) {
@@ -189,11 +200,14 @@ export function CircularProgress({
189
200
  const circumference = 2 * Math.PI * radius
190
201
  const strokeDashoffset = circumference - (percentage / 100) * circumference
191
202
  const center = size / 2
203
+ // Fixed: a `size × size` px box. Fill: fill the parent, staying square, and let
204
+ // the `0 0 size size` viewBox scale the geometry to fit (a responsive ring).
205
+ const boxStyle = fill ? { width: '100%' as const, aspectRatio: 1 } : { width: size, height: size }
192
206
 
193
207
  return (
194
208
  <View
195
209
  className={cn('items-center justify-center', className)}
196
- style={{ width: size, height: size }}
210
+ style={boxStyle}
197
211
  accessibilityRole="progressbar"
198
212
  accessibilityValue={{
199
213
  min: 0,
@@ -202,14 +216,11 @@ export function CircularProgress({
202
216
  }}
203
217
  {...props}
204
218
  >
205
- {/* SVG implementation for web */}
206
- <View
207
- className={cn(isIndeterminate && 'animate-spin')}
208
- style={{ width: size, height: size }}
209
- >
219
+ {/* SVG implementation for web — width/height 100% so it scales with `boxStyle`. */}
220
+ <View className={cn(isIndeterminate && 'animate-spin')} style={boxStyle}>
210
221
  <svg
211
- width={size}
212
- height={size}
222
+ width="100%"
223
+ height="100%"
213
224
  viewBox={`0 0 ${size} ${size}`}
214
225
  style={{ position: 'absolute' }}
215
226
  >
@@ -239,14 +250,28 @@ export function CircularProgress({
239
250
  </svg>
240
251
  </View>
241
252
 
242
- {/* Center value */}
243
- {showValue && !isIndeterminate && (
244
- <Text
245
- className="text-xs font-semibold text-text-primary absolute"
246
- style={{ fontSize: Math.max(size * 0.22, 10) }}
253
+ {/* Center: custom children take precedence over the showValue readout. */}
254
+ {children != null ? (
255
+ <View
256
+ style={{
257
+ position: 'absolute',
258
+ alignItems: 'center',
259
+ justifyContent: 'center',
260
+ pointerEvents: 'none',
261
+ }}
247
262
  >
248
- {formatValue(value, max)}
249
- </Text>
263
+ {children}
264
+ </View>
265
+ ) : (
266
+ showValue &&
267
+ !isIndeterminate && (
268
+ <Text
269
+ className="text-xs font-semibold text-text-primary absolute"
270
+ style={{ fontSize: Math.max(size * 0.22, 10) }}
271
+ >
272
+ {formatValue(value, max)}
273
+ </Text>
274
+ )
250
275
  )}
251
276
  </View>
252
277
  )
@@ -4,7 +4,7 @@ import { View, Text } from 'react-native'
4
4
  import { Radio, RadioGroup } from './Radio'
5
5
 
6
6
  const meta: Meta<typeof RadioGroup> = {
7
- title: 'Components/Radio',
7
+ title: 'Components/Molecules/Radio',
8
8
  component: RadioGroup,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { Section, SectionHeader, SectionContent } from './Section'
4
4
 
5
5
  const meta: Meta<typeof Section> = {
6
- title: 'Components/Section',
6
+ title: 'Components/Atoms/Section',
7
7
  component: Section,
8
8
  tags: ['autodocs'],
9
9
  }
@@ -12,7 +12,7 @@ const basicOptions: SelectOption[] = [
12
12
  ]
13
13
 
14
14
  const meta: Meta<typeof Select> = {
15
- title: 'Components/Select',
15
+ title: 'Components/Molecules/Select',
16
16
  component: Select,
17
17
  tags: ['autodocs'],
18
18
  argTypes: {
@@ -9,7 +9,7 @@ import {
9
9
  } from './Skeleton'
10
10
 
11
11
  const meta: Meta<typeof Skeleton> = {
12
- title: 'Components/Skeleton',
12
+ title: 'Components/Atoms/Skeleton',
13
13
  component: Skeleton,
14
14
  tags: ['autodocs'],
15
15
  argTypes: {
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Spinner } from './Spinner'
4
4
 
5
5
  const meta: Meta<typeof Spinner> = {
6
- title: 'Components/Spinner',
6
+ title: 'Components/Atoms/Spinner',
7
7
  component: Spinner,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { Stack, HStack, VStack } from './Stack'
4
4
 
5
5
  const meta: Meta<typeof Stack> = {
6
- title: 'Components/Stack',
6
+ title: 'Components/Atoms/Stack',
7
7
  component: Stack,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -4,7 +4,7 @@ import { Surface } from './Surface'
4
4
  import type { ElevationLevel } from '../../../theme/elevation'
5
5
 
6
6
  const meta: Meta<typeof Surface> = {
7
- title: 'Components/Surface',
7
+ title: 'Components/Atoms/Surface',
8
8
  component: Surface,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Switch } from './Switch'
4
4
 
5
5
  const meta: Meta<typeof Switch> = {
6
- title: 'Components/Switch',
6
+ title: 'Components/Molecules/Switch',
7
7
  component: Switch,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native'
3
3
  import { Tabs, TabList, Tab, TabPanels, TabPanel } from './Tabs'
4
4
 
5
5
  const meta: Meta<typeof Tabs> = {
6
- title: 'Components/Tabs',
6
+ title: 'Components/Molecules/Tabs',
7
7
  component: Tabs,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -0,0 +1,79 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import { View } from 'react-native'
3
+ import { Tile } from './Tile'
4
+ import { getSemanticColors } from '../../../theme'
5
+
6
+ const ACCENT = getSemanticColors('dark')['status-warning']
7
+ const SUCCESS = getSemanticColors('dark')['status-success']
8
+
9
+ const meta: Meta<typeof Tile> = {
10
+ title: 'Components/Atoms/Tile',
11
+ component: Tile,
12
+ tags: ['autodocs'],
13
+ parameters: {
14
+ docs: {
15
+ description: {
16
+ component: '**Atom.** A compact card preset; grouped by SessionMetrics / ScheduleTiles.',
17
+ },
18
+ },
19
+ },
20
+ argTypes: {
21
+ label: { control: 'text', description: 'Uppercase micro-label' },
22
+ value: { control: 'text', description: 'Primary mono value' },
23
+ valueColor: { control: 'color', description: 'Tints the value' },
24
+ align: {
25
+ control: 'radio',
26
+ options: ['center', 'start'],
27
+ description: 'Content alignment',
28
+ },
29
+ },
30
+ }
31
+
32
+ export default meta
33
+ type Story = StoryObj<typeof Tile>
34
+
35
+ export const Default: Story = {
36
+ args: {
37
+ label: 'Volume',
38
+ value: '76%',
39
+ align: 'center',
40
+ },
41
+ }
42
+
43
+ export const Row: Story = {
44
+ render: () => (
45
+ <View style={{ flexDirection: 'row', gap: 4, width: 246 }}>
46
+ <Tile label="Volume" value="76%" />
47
+ <Tile label="Load" value="7.3k" />
48
+ <Tile label="Fatigue" value="MOD" valueColor={ACCENT} />
49
+ </View>
50
+ ),
51
+ }
52
+
53
+ export const ScheduleTiles: Story = {
54
+ render: () => (
55
+ <View style={{ flexDirection: 'row', gap: 4, width: 246 }}>
56
+ <Tile label="Date" value="Jul 10" />
57
+ <Tile label="Time" value="6:30 PM" />
58
+ <Tile label="Until" value="5h" valueColor={ACCENT} />
59
+ </View>
60
+ ),
61
+ }
62
+
63
+ export const ValueColors: Story = {
64
+ render: () => (
65
+ <View style={{ flexDirection: 'row', gap: 4, width: 246 }}>
66
+ <Tile label="Default" value="12" />
67
+ <Tile label="Success" value="OK" valueColor={SUCCESS} />
68
+ <Tile label="Warning" value="MOD" valueColor={ACCENT} />
69
+ </View>
70
+ ),
71
+ }
72
+
73
+ export const StartAligned: Story = {
74
+ args: {
75
+ label: 'Program',
76
+ value: 'Pull A',
77
+ align: 'start',
78
+ },
79
+ }
@@ -0,0 +1,48 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { render, screen } from '@testing-library/react'
3
+ import { axe } from 'jest-axe'
4
+ import { Tile } from './Tile'
5
+
6
+ describe('Tile', () => {
7
+ it('renders label and value', () => {
8
+ render(<Tile label="Volume" value="76%" />)
9
+ expect(screen.getByText('Volume')).toBeInTheDocument()
10
+ expect(screen.getByText('76%')).toBeInTheDocument()
11
+ })
12
+
13
+ it('applies valueColor to the value text', () => {
14
+ render(<Tile label="Fatigue" value="MOD" valueColor="#F5A623" />)
15
+ const value = screen.getByText('MOD')
16
+ expect(value).toHaveStyle({ color: '#F5A623' })
17
+ })
18
+
19
+ it('does not set an inline color when valueColor is omitted', () => {
20
+ render(<Tile label="Volume" value="76%" />)
21
+ const value = screen.getByText('76%')
22
+ expect(value.style.color).toBe('')
23
+ })
24
+
25
+ it('renders with start alignment', () => {
26
+ render(<Tile label="Program" value="Pull A" align="start" />)
27
+ expect(screen.getByText('Program')).toBeInTheDocument()
28
+ expect(screen.getByText('Pull A')).toBeInTheDocument()
29
+ })
30
+
31
+ it('applies custom className', () => {
32
+ const { container } = render(<Tile label="Load" value="7.3k" className="custom-class" />)
33
+ expect(container.firstChild).toBeInTheDocument()
34
+ })
35
+
36
+ it('passes additional props through', () => {
37
+ render(<Tile label="Load" value="7.3k" testID="tile-test" />)
38
+ expect(screen.getByText('7.3k')).toBeInTheDocument()
39
+ })
40
+
41
+ describe('accessibility', () => {
42
+ it('has no accessibility violations', async () => {
43
+ const { container } = render(<Tile label="Volume" value="76%" />)
44
+ const results = await axe(container)
45
+ expect(results).toHaveNoViolations()
46
+ })
47
+ })
48
+ })
@@ -0,0 +1,64 @@
1
+ import { View, Text, type ViewProps } from 'react-native'
2
+ import { cn } from '../../../utils/cn'
3
+
4
+ export interface TileProps extends ViewProps {
5
+ /** Uppercase micro-label shown above the value */
6
+ label: string
7
+ /** Primary value, rendered in a bold mono face */
8
+ value: string
9
+ /** Tints the value (status/accent hex or CSS color); defaults to primary text */
10
+ valueColor?: string
11
+ /** Content alignment within the tile (default: 'center') */
12
+ align?: 'center' | 'start'
13
+ /** Additional className */
14
+ className?: string
15
+ }
16
+
17
+ /**
18
+ * Tile — a compact label-over-value stat card.
19
+ *
20
+ * A rounded raised box with an uppercase micro-label stacked over a bold mono
21
+ * value. Fills its flex slot so a row of Tiles reads as an even HStack.
22
+ *
23
+ * @example
24
+ * <Tile label="Volume" value="76%" />
25
+ * <Tile label="Fatigue" value="MOD" valueColor="#F5A623" />
26
+ */
27
+ export function Tile({
28
+ label,
29
+ value,
30
+ valueColor,
31
+ align = 'center',
32
+ className,
33
+ ...props
34
+ }: TileProps) {
35
+ const isCenter = align === 'center'
36
+ return (
37
+ <View
38
+ className={cn(
39
+ 'flex-1 rounded-md bg-surface-raised px-1.5 py-2',
40
+ isCenter ? 'items-center' : 'items-start',
41
+ className
42
+ )}
43
+ {...props}
44
+ >
45
+ <Text
46
+ className={cn(
47
+ 'text-[10px] font-bold uppercase tracking-wider text-text-tertiary',
48
+ isCenter ? 'text-center' : 'text-left'
49
+ )}
50
+ >
51
+ {label}
52
+ </Text>
53
+ <Text
54
+ className={cn(
55
+ 'mt-0.5 font-mono text-sm font-bold text-text-primary',
56
+ isCenter ? 'text-center' : 'text-left'
57
+ )}
58
+ style={valueColor ? { color: valueColor } : undefined}
59
+ >
60
+ {value}
61
+ </Text>
62
+ </View>
63
+ )
64
+ }
@@ -0,0 +1,2 @@
1
+ export { Tile } from './Tile'
2
+ export type { TileProps } from './Tile'
@@ -4,7 +4,7 @@ import { Toast, ToastProvider, useToast } from './Toast'
4
4
  import { Button, ButtonText } from '../button'
5
5
 
6
6
  const meta: Meta<typeof Toast> = {
7
- title: 'Components/Toast',
7
+ title: 'Components/Molecules/Toast',
8
8
  component: Toast,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -4,7 +4,7 @@ import { View, Text } from 'react-native'
4
4
  import { ToolbarButton, ToolbarButtonGroup } from './ToolbarButton'
5
5
 
6
6
  const meta: Meta<typeof ToolbarButton> = {
7
- title: 'Components/ToolbarButton',
7
+ title: 'Components/Molecules/ToolbarButton',
8
8
  component: ToolbarButton,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {