@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
@@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'
2
2
  import { SessionStatePill } from './SessionStatePill'
3
3
 
4
4
  const meta: Meta<typeof SessionStatePill> = {
5
- title: 'Shell/TopBar/SessionStatePill',
5
+ title: 'Shell/SessionStatePill',
6
6
  component: SessionStatePill,
7
7
  tags: ['autodocs'],
8
8
  args: { state: 'live' },
@@ -15,8 +15,8 @@ const meta: Meta<typeof SessionStatePill> = {
15
15
  description: {
16
16
  component:
17
17
  '**Molecule** (= the ledger’s reusable StatusPill — also used by the Live-view header). Composes ' +
18
- '[Indicator](?path=/docs/components-indicator--docs) (pulse `ping` + vivid color for live) + ' +
19
- '[Typography](?path=/docs/custom-typography--docs) (`monoLabel`). Use the `state` control to switch.',
18
+ '[Indicator](?path=/docs/components-atoms-indicator--docs) (pulse `ping` + vivid color for live) + ' +
19
+ '[Typography](?path=/docs/foundations-typography--docs) (`monoLabel`). Use the `state` control to switch.',
20
20
  },
21
21
  },
22
22
  },
@@ -23,7 +23,7 @@ const stateConfig: Record<
23
23
  }
24
24
  > = {
25
25
  // live = vivid green with an expanding ring; rest = solid amber (no pulse — operator); idle is dim.
26
- live: { label: 'LIVE', color: 'success', pulse: 'ping', textColor: 'primary' },
26
+ live: { label: 'LIVE', color: 'live', pulse: 'ping', textColor: 'primary' },
27
27
  rest: { label: 'REST', color: 'warning', pulse: false, textColor: 'primary' },
28
28
  idle: { label: 'IDLE', color: 'default', pulse: false, textColor: 'secondary' },
29
29
  }
@@ -0,0 +1,81 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import { useArgs } from 'storybook/preview-api'
3
+ import { View } from 'react-native'
4
+ import { SideNav } from './SideNav'
5
+ import { Typography } from '../custom/Typography'
6
+
7
+ const meta: Meta<typeof SideNav> = {
8
+ title: 'Shell/SideNav',
9
+ component: SideNav,
10
+ tags: ['autodocs'],
11
+ args: { activeKey: 'live', liveKey: null },
12
+ argTypes: {
13
+ activeKey: { control: 'select', options: ['live', 'review', 'program', 'body'] },
14
+ liveKey: { control: 'select', options: [null, 'live', 'review', 'program', 'body'] },
15
+ onNavigate: { action: 'navigate' },
16
+ },
17
+ // Interactive AND Controls-synced: clicking a category writes `activeKey` back to the
18
+ // story args (canvas + Controls stay in lock-step) and still fires the `onNavigate`
19
+ // action. `useArgs` must be called directly in the story/render fn (not a child
20
+ // component), so the rules-of-hooks lint is disabled here — the idiomatic SB pattern.
21
+ render: (args) => {
22
+ // eslint-disable-next-line react-hooks/rules-of-hooks
23
+ const [, updateArgs] = useArgs()
24
+ return (
25
+ <SideNav
26
+ {...args}
27
+ onNavigate={(key) => {
28
+ updateArgs({ activeKey: key })
29
+ args.onNavigate?.(key)
30
+ }}
31
+ />
32
+ )
33
+ },
34
+ // Render in-context: full-height shell frame so the rail snaps to the left edge and
35
+ // stretches with the viewport (resize the canvas height to see it hold).
36
+ decorators: [
37
+ (Story) => (
38
+ <View className="min-h-screen flex-row bg-background-default">
39
+ <Story />
40
+ <View className="flex-1 items-center justify-center">
41
+ <Typography variant="body2" color="tertiary">
42
+ main viewport
43
+ </Typography>
44
+ </View>
45
+ </View>
46
+ ),
47
+ ],
48
+ parameters: {
49
+ layout: 'fullscreen',
50
+ docs: {
51
+ description: {
52
+ component:
53
+ '**Organism** (shell region). The persistent 60px left rail switching Live · Review · Plan · ' +
54
+ 'Body. Composes [NavItem](?path=/docs/shell-navitem--docs) × the four categories + the ' +
55
+ 'shared [icon set](?path=/docs/foundations-icons--docs). Presentational — drive it with `activeKey` / ' +
56
+ '`onNavigate` / `liveKey`. Active = left accent bar; `liveKey` (when not active) tints that ' +
57
+ 'label a muted green.\n\n' +
58
+ '**Try it:** stories render in a full-height shell frame — the rail pins to the left edge and ' +
59
+ 'stretches to the viewport, items staying top-aligned. **Resize the canvas** to see it hold at ' +
60
+ 'any height. Use the **Controls** to move `activeKey` / `liveKey`.',
61
+ },
62
+ },
63
+ },
64
+ }
65
+ export default meta
66
+ type Story = StoryObj<typeof SideNav>
67
+
68
+ export const Default: Story = {}
69
+
70
+ export const LiveElsewhere: Story = {
71
+ args: { activeKey: 'program', liveKey: 'live' },
72
+ parameters: {
73
+ docs: {
74
+ description: {
75
+ story:
76
+ 'A set runs on Live while the operator is on Plan → the Live item carries a quiet green label cue. ' +
77
+ '(Still clickable — try switching away and back.)',
78
+ },
79
+ },
80
+ },
81
+ }
@@ -0,0 +1,51 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { render, screen, fireEvent, within } from '@testing-library/react'
3
+ import { axe } from 'jest-axe'
4
+ import { SideNav } from './SideNav'
5
+
6
+ describe('SideNav', () => {
7
+ it('renders the four default categories as tabs in a tablist', () => {
8
+ render(<SideNav activeKey="live" />)
9
+ expect(screen.getByRole('tablist')).toBeInTheDocument()
10
+ ;['Live', 'Review', 'Plan', 'Body'].forEach((name) => {
11
+ expect(screen.getByRole('tab', { name })).toBeInTheDocument()
12
+ })
13
+ })
14
+
15
+ it('shows the accent bar only on the active category', () => {
16
+ render(<SideNav activeKey="program" />)
17
+ expect(screen.getAllByTestId('nav-item-accent')).toHaveLength(1)
18
+ expect(
19
+ within(screen.getByRole('tab', { name: 'Plan' })).getByTestId('nav-item-accent')
20
+ ).toBeInTheDocument()
21
+ expect(
22
+ within(screen.getByRole('tab', { name: 'Live' })).queryByTestId('nav-item-accent')
23
+ ).toBeNull()
24
+ })
25
+
26
+ it('reports the tapped key via onNavigate', () => {
27
+ const onNavigate = vi.fn()
28
+ render(<SideNav activeKey="live" onNavigate={onNavigate} />)
29
+ fireEvent.click(screen.getByRole('tab', { name: 'Body' }))
30
+ expect(onNavigate).toHaveBeenCalledWith('body')
31
+ })
32
+
33
+ it('keeps the active item as active even when it is also the liveKey (no double-state)', () => {
34
+ render(<SideNav activeKey="live" liveKey="live" />)
35
+ // active wins: exactly one accent bar, on Live (the live cue never applies to the active view)
36
+ expect(screen.getAllByTestId('nav-item-accent')).toHaveLength(1)
37
+ expect(
38
+ within(screen.getByRole('tab', { name: 'Live' })).getByTestId('nav-item-accent')
39
+ ).toBeInTheDocument()
40
+ })
41
+
42
+ it('accepts custom items', () => {
43
+ render(<SideNav activeKey="a" items={[{ key: 'a', label: 'Alpha', icon: null }]} />)
44
+ expect(screen.getByRole('tab', { name: 'Alpha' })).toBeInTheDocument()
45
+ })
46
+
47
+ it('has no accessibility violations', async () => {
48
+ const { container } = render(<SideNav activeKey="live" />)
49
+ expect(await axe(container)).toHaveNoViolations()
50
+ })
51
+ })
@@ -0,0 +1,74 @@
1
+ import type { ReactNode } from 'react'
2
+ import { View } from 'react-native'
3
+ import { cn } from '../../utils/cn'
4
+ import { ActivityIcon, HistoryIcon, LayersIcon, PersonStandingIcon } from '../icons'
5
+ import { NavItem } from './NavItem'
6
+
7
+ export interface SideNavItem {
8
+ /** Stable category key — matches `activeKey` / `liveKey`. */
9
+ key: string
10
+ /** Micro-label shown under the glyph. */
11
+ label: string
12
+ /** The glyph node (rendered ~20px via `currentColor`). */
13
+ icon: ReactNode
14
+ }
15
+
16
+ export interface SideNavProps {
17
+ /** Category items, top → bottom. Defaults to the four dashboard categories. */
18
+ items?: SideNavItem[]
19
+ /** Key of the active category. */
20
+ activeKey: string
21
+ /** Called with the tapped item's key. */
22
+ onNavigate?: (key: string) => void
23
+ /**
24
+ * Key of a category with live activity while it is NOT active (e.g. a set
25
+ * running off its view) → a quiet green cue on that item's label.
26
+ */
27
+ liveKey?: string | null
28
+ className?: string
29
+ }
30
+
31
+ /** The four dashboard categories with their locked S2 glyphs (activity · history · layers · figure). */
32
+ export const defaultNavItems: SideNavItem[] = [
33
+ { key: 'live', label: 'Live', icon: <ActivityIcon size={20} color="currentColor" /> },
34
+ { key: 'review', label: 'Review', icon: <HistoryIcon size={20} color="currentColor" /> },
35
+ { key: 'program', label: 'Plan', icon: <LayersIcon size={20} color="currentColor" /> },
36
+ { key: 'body', label: 'Body', icon: <PersonStandingIcon size={20} color="currentColor" /> },
37
+ ]
38
+
39
+ /**
40
+ * Shell S2 · SideNav — the persistent 60px left rail that switches the main
41
+ * viewport between categories (Live · Review · Program · Body). Presentational:
42
+ * it renders `items` and reports taps via `onNavigate`; the app owns routing and
43
+ * which key is `live`. Active item shows a left accent bar; `liveKey` (when not
44
+ * the active view) tints that item's label a muted green. Fixed 60px at every
45
+ * width — labels sit under the glyph, so they never change the rail width.
46
+ */
47
+ export function SideNav({
48
+ items = defaultNavItems,
49
+ activeKey,
50
+ onNavigate,
51
+ liveKey = null,
52
+ className,
53
+ }: SideNavProps) {
54
+ return (
55
+ <View
56
+ accessibilityRole="tablist"
57
+ className={cn(
58
+ 'w-[60px] items-center gap-[6px] border-r border-border bg-background-base py-3',
59
+ className
60
+ )}
61
+ >
62
+ {items.map((item) => (
63
+ <NavItem
64
+ key={item.key}
65
+ icon={item.icon}
66
+ label={item.label}
67
+ active={item.key === activeKey}
68
+ live={item.key === liveKey && item.key !== activeKey}
69
+ onPress={() => onNavigate?.(item.key)}
70
+ />
71
+ ))}
72
+ </View>
73
+ )
74
+ }
@@ -29,11 +29,11 @@ const meta: Meta<typeof TopBar> = {
29
29
  component:
30
30
  '**Organism** — the persistent shell chrome band, and the root of the top-bar family ' +
31
31
  '(see `shell/README.md` for the full dependency map). Composes ' +
32
- '[BrandLockup](?path=/docs/shell-topbar-brandlockup--docs) + ' +
33
- '[SessionStatePill](?path=/docs/shell-topbar-sessionstatepill--docs) + ' +
34
- '[Divider](?path=/docs/components-divider--docs) (`bg-border-prominent`) + ' +
35
- '[DeviceMenu](?path=/docs/shell-topbar-devicemenu--docs) + ' +
36
- '[DateTime](?path=/docs/custom-datetime--docs) (`variant="mono"` live clock). ' +
32
+ '[BrandLockup](?path=/docs/shell-brandlockup--docs) + ' +
33
+ '[SessionStatePill](?path=/docs/shell-sessionstatepill--docs) + ' +
34
+ '[Divider](?path=/docs/components-atoms-divider--docs) (`bg-border-prominent`) + ' +
35
+ '[DeviceMenu](?path=/docs/shell-devicemenu--docs) + ' +
36
+ '[DateTime](?path=/docs/components-molecules-datetime--docs) (`variant="mono"` live clock). ' +
37
37
  'Background = the shared `surfaceGradient.chrome` primitive.\n\n' +
38
38
  '**Try it:** use the **Controls** to change `state`, edit `devices` (set one to `lost` to see the ' +
39
39
  'fault), or toggle `showSubtitle` / `showClock`. **Resize the canvas** to watch the ' +
@@ -6,3 +6,8 @@ export * from './DeviceIndicator'
6
6
  export * from './DeviceRow'
7
7
  export * from './DeviceMenu'
8
8
  export * from './TopBar'
9
+ // S2 · Side nav family.
10
+ export * from './NavItem'
11
+ export * from './SideNav'
12
+ // S3 · Dashboard shell — composes the nav + top-bar chrome over a content slot.
13
+ export * from './DashboardShell'
@@ -1,11 +1,25 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
- import { View } from 'react-native'
1
+ import type { Decorator, Meta, StoryObj } from '@storybook/react-vite'
2
+ import { View, Text } from 'react-native'
3
3
  import { Alert, AlertTitle, AlertDescription } from './Alert'
4
4
 
5
5
  const meta: Meta<typeof Alert> = {
6
- title: 'Components/Alert',
6
+ title: 'Components/Molecules/Alert',
7
7
  component: Alert,
8
8
  tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ 'Status callout across 4 statuses (success/info/warning/error) × 3 variants ' +
14
+ '(subtle/outline/solid). Two densities via `size`: `default` — the padded ' +
15
+ 'icon + title/description block; `compact` — a single-line **cue pill** (tighter, ' +
16
+ 'center-aligned, hairline status border on `subtle`) that absorbs the R2 `CueFlag` ' +
17
+ 'live-coaching cue. Pass `size="compact"` + `message="…"` for the batteries-included ' +
18
+ "status-colored one-liner (RN doesn't cascade text color, so the `message` prop " +
19
+ 'colors it for you). Use `<AlertTitle>` / `<AlertDescription>` children for richer content.',
20
+ },
21
+ },
22
+ },
9
23
  argTypes: {
10
24
  status: {
11
25
  control: 'select',
@@ -15,6 +29,11 @@ const meta: Meta<typeof Alert> = {
15
29
  control: 'select',
16
30
  options: ['subtle', 'outline', 'solid'],
17
31
  },
32
+ size: {
33
+ control: 'inline-radio',
34
+ options: ['default', 'compact'],
35
+ },
36
+ message: { control: 'text' },
18
37
  showIcon: { control: 'boolean' },
19
38
  },
20
39
  }
@@ -152,3 +171,67 @@ export const DescriptionOnly: Story = {
152
171
  </Alert>
153
172
  ),
154
173
  }
174
+
175
+ // --- Compact cue pill (absorbs CueFlag) --------------------------------------
176
+ // The across-the-room live coaching cue. Rendered on the north-star wall background
177
+ // so the tinted + bordered pill reads the way it will live.
178
+
179
+ /** Wall-background frame for the compact cue stories. */
180
+ const wall: Decorator = (Story) => (
181
+ <View style={{ width: 460, padding: 28, backgroundColor: '#0E0E0E' }}>
182
+ <Story />
183
+ </View>
184
+ )
185
+
186
+ /** Compact warning cue — the VL20 approach-threshold flag (batteries-included `message`). */
187
+ export const CompactWarningCue: Story = {
188
+ args: {
189
+ status: 'warning',
190
+ variant: 'subtle',
191
+ size: 'compact',
192
+ message: 'VL20 · target reps met — final rep or end the set.',
193
+ },
194
+ decorators: [wall],
195
+ }
196
+
197
+ /** Compact error cue — the stop-now flag. */
198
+ export const CompactErrorCue: Story = {
199
+ args: {
200
+ status: 'error',
201
+ variant: 'subtle',
202
+ size: 'compact',
203
+ message: 'Velocity loss 31% — end the set now.',
204
+ },
205
+ decorators: [wall],
206
+ }
207
+
208
+ /** The consumption target: the north-star live cue (interpolated loss). */
209
+ export const CompactLiveCue: Story = {
210
+ args: {
211
+ status: 'warning',
212
+ variant: 'subtle',
213
+ size: 'compact',
214
+ message: 'Approaching threshold · 18% velocity loss — one or two reps left.',
215
+ },
216
+ decorators: [wall],
217
+ }
218
+
219
+ /** Default vs compact, side by side, for the density comparison. */
220
+ export const DefaultVsCompact: Story = {
221
+ render: () => (
222
+ <View style={{ gap: 16, width: 460, padding: 28, backgroundColor: '#0E0E0E' }}>
223
+ <Text style={{ color: '#5A5A5A', fontSize: 10, fontWeight: '700' }}>DEFAULT</Text>
224
+ <Alert status="warning" variant="subtle">
225
+ <AlertTitle>Approaching threshold</AlertTitle>
226
+ <AlertDescription>18% velocity loss — one or two reps left in the band.</AlertDescription>
227
+ </Alert>
228
+ <Text style={{ color: '#5A5A5A', fontSize: 10, fontWeight: '700' }}>COMPACT (cue pill)</Text>
229
+ <Alert
230
+ status="warning"
231
+ variant="subtle"
232
+ size="compact"
233
+ message="Approaching threshold · 18% velocity loss — reps left in band."
234
+ />
235
+ </View>
236
+ ),
237
+ }
@@ -200,3 +200,55 @@ describe('Alert', () => {
200
200
  })
201
201
  })
202
202
  })
203
+
204
+ describe('Alert compact cue (absorbs CueFlag)', () => {
205
+ it('renders the message as content (batteries-included cue)', () => {
206
+ render(<Alert status="warning" size="compact" message="VL20 · end the set" />)
207
+ expect(screen.getByTestId('alert-message')).toHaveTextContent('VL20 · end the set')
208
+ })
209
+
210
+ it('renders the message alongside a status glyph and the alert role', () => {
211
+ render(<Alert status="error" size="compact" message="Stop now" />)
212
+ expect(screen.getByRole('alert')).toBeInTheDocument()
213
+ expect(screen.getByText('✕')).toBeInTheDocument()
214
+ expect(screen.getByText('Stop now')).toBeInTheDocument()
215
+ })
216
+
217
+ it('renders message in the default size too', () => {
218
+ render(<Alert status="info" message="Heads up" />)
219
+ expect(screen.getByTestId('alert-message')).toHaveTextContent('Heads up')
220
+ })
221
+
222
+ it('renders children after the message when both are given', () => {
223
+ render(
224
+ <Alert status="warning" size="compact" message="Cue line">
225
+ <AlertDescription>Extra detail</AlertDescription>
226
+ </Alert>
227
+ )
228
+ expect(screen.getByTestId('alert-message')).toHaveTextContent('Cue line')
229
+ expect(screen.getByText('Extra detail')).toBeInTheDocument()
230
+ })
231
+
232
+ it('omits the message node when no message is passed', () => {
233
+ render(
234
+ <Alert status="warning" size="compact">
235
+ <AlertDescription>Just children</AlertDescription>
236
+ </Alert>
237
+ )
238
+ expect(screen.queryByTestId('alert-message')).not.toBeInTheDocument()
239
+ expect(screen.getByText('Just children')).toBeInTheDocument()
240
+ })
241
+
242
+ it('still respects showIcon=false in compact', () => {
243
+ render(<Alert status="warning" size="compact" message="No icon cue" showIcon={false} />)
244
+ expect(screen.queryByText('⚠')).not.toBeInTheDocument()
245
+ expect(screen.getByText('No icon cue')).toBeInTheDocument()
246
+ })
247
+
248
+ it('has no accessibility violations as a compact cue', async () => {
249
+ const { container } = render(
250
+ <Alert status="warning" size="compact" message="VL20 · target reps met — end the set." />
251
+ )
252
+ expect(await axe(container)).toHaveNoViolations()
253
+ })
254
+ })
@@ -4,12 +4,29 @@ import { cn } from '../../../utils/cn'
4
4
 
5
5
  export type AlertStatus = 'success' | 'info' | 'warning' | 'error'
6
6
  export type AlertVariant = 'subtle' | 'outline' | 'solid'
7
+ export type AlertSize = 'default' | 'compact'
7
8
 
8
9
  export interface AlertProps extends ViewProps {
9
10
  /** Alert status type */
10
11
  status?: AlertStatus
11
12
  /** Visual variant */
12
13
  variant?: AlertVariant
14
+ /**
15
+ * Density. `default` — the padded callout (icon + title/description block).
16
+ * `compact` — a single-line **cue pill** (tighter padding, center-aligned, and a
17
+ * hairline status border on the `subtle` variant): the across-the-room live coaching
18
+ * cue (absorbs the R2 `CueFlag` — e.g. a velocity-loss threshold warning). Pair with
19
+ * the {@link message} prop for the batteries-included colored one-liner.
20
+ */
21
+ size?: AlertSize
22
+ /**
23
+ * Convenience single-line content: renders as **status-colored, bold** text (white on
24
+ * `solid`) — the batteries-included cue message, so a `compact` cue is just
25
+ * `<Alert status="warning" size="compact" message="VL20 · …" />` with no need to
26
+ * hand-color the text (RN doesn't cascade color). Renders before {@link children},
27
+ * which stay available for richer content.
28
+ */
29
+ message?: string
13
30
  /** Custom icon element */
14
31
  icon?: React.ReactNode
15
32
  /** Whether to show the default icon */
@@ -21,17 +38,22 @@ export interface AlertProps extends ViewProps {
21
38
  children?: React.ReactNode
22
39
  }
23
40
 
24
- const statusColors: Record<AlertStatus, {
25
- subtle: string
26
- outline: string
27
- solid: string
28
- icon: string
29
- text: string
30
- }> = {
41
+ const statusColors: Record<
42
+ AlertStatus,
43
+ {
44
+ subtle: string
45
+ outline: string
46
+ solid: string
47
+ border: string
48
+ icon: string
49
+ text: string
50
+ }
51
+ > = {
31
52
  success: {
32
53
  subtle: 'bg-status-success-subtle',
33
54
  outline: 'border-2 border-status-success bg-transparent',
34
55
  solid: 'bg-status-success',
56
+ border: 'border-status-success',
35
57
  icon: 'text-status-success',
36
58
  text: 'text-status-success',
37
59
  },
@@ -39,6 +61,7 @@ const statusColors: Record<AlertStatus, {
39
61
  subtle: 'bg-status-info-subtle',
40
62
  outline: 'border-2 border-status-info bg-transparent',
41
63
  solid: 'bg-status-info',
64
+ border: 'border-status-info',
42
65
  icon: 'text-status-info',
43
66
  text: 'text-status-info',
44
67
  },
@@ -46,6 +69,7 @@ const statusColors: Record<AlertStatus, {
46
69
  subtle: 'bg-status-warning-subtle',
47
70
  outline: 'border-2 border-status-warning bg-transparent',
48
71
  solid: 'bg-status-warning',
72
+ border: 'border-status-warning',
49
73
  icon: 'text-status-warning',
50
74
  text: 'text-status-warning',
51
75
  },
@@ -53,6 +77,7 @@ const statusColors: Record<AlertStatus, {
53
77
  subtle: 'bg-status-error-subtle',
54
78
  outline: 'border-2 border-status-error bg-transparent',
55
79
  solid: 'bg-status-error',
80
+ border: 'border-status-error',
56
81
  icon: 'text-status-error',
57
82
  text: 'text-status-error',
58
83
  },
@@ -82,6 +107,8 @@ const defaultIcons: Record<AlertStatus, string> = {
82
107
  export function Alert({
83
108
  status = 'info',
84
109
  variant = 'subtle',
110
+ size = 'default',
111
+ message,
85
112
  icon,
86
113
  showIcon = true,
87
114
  onClose,
@@ -91,23 +118,30 @@ export function Alert({
91
118
  }: AlertProps) {
92
119
  const colors = statusColors[status]
93
120
  const isSolid = variant === 'solid'
121
+ const isCompact = size === 'compact'
94
122
 
95
123
  return (
96
124
  <View
97
125
  accessibilityRole="alert"
98
126
  className={cn(
99
- 'flex-row items-start p-4 rounded-lg',
127
+ isCompact
128
+ ? 'flex-row items-center px-3 py-2 rounded-lg'
129
+ : 'flex-row items-start p-4 rounded-lg',
100
130
  colors[variant],
131
+ // A compact `subtle` pill gets a hairline status border so it reads as a
132
+ // defined cue on a dark wall (the CueFlag look); other variants carry their own.
133
+ isCompact && variant === 'subtle' && cn('border', colors.border),
101
134
  className
102
135
  )}
103
136
  {...props}
104
137
  >
105
138
  {showIcon && (
106
- <View className="mr-3 mt-0.5">
139
+ <View className={isCompact ? 'mr-2' : 'mr-3 mt-0.5'}>
107
140
  {icon || (
108
141
  <Text
109
142
  className={cn(
110
- 'text-lg font-bold',
143
+ 'font-bold',
144
+ isCompact ? 'text-base' : 'text-lg',
111
145
  isSolid ? 'text-white' : colors.icon
112
146
  )}
113
147
  >
@@ -118,6 +152,14 @@ export function Alert({
118
152
  )}
119
153
 
120
154
  <View className="flex-1">
155
+ {message != null && (
156
+ <Text
157
+ className={cn('text-sm font-semibold', isSolid ? 'text-white' : colors.text)}
158
+ testID="alert-message"
159
+ >
160
+ {message}
161
+ </Text>
162
+ )}
121
163
  {children}
122
164
  </View>
123
165
 
@@ -146,11 +188,7 @@ export interface AlertTitleProps {
146
188
  * Title for Alert component.
147
189
  */
148
190
  export function AlertTitle({ children, className }: AlertTitleProps) {
149
- return (
150
- <Text className={cn('font-semibold text-text-primary mb-1', className)}>
151
- {children}
152
- </Text>
153
- )
191
+ return <Text className={cn('font-semibold text-text-primary mb-1', className)}>{children}</Text>
154
192
  }
155
193
 
156
194
  export interface AlertDescriptionProps {
@@ -162,9 +200,5 @@ export interface AlertDescriptionProps {
162
200
  * Description for Alert component.
163
201
  */
164
202
  export function AlertDescription({ children, className }: AlertDescriptionProps) {
165
- return (
166
- <Text className={cn('text-sm text-text-secondary', className)}>
167
- {children}
168
- </Text>
169
- )
203
+ return <Text className={cn('text-sm text-text-secondary', className)}>{children}</Text>
170
204
  }
@@ -4,7 +4,7 @@ import { View, Text } from 'react-native'
4
4
  import { Autocomplete, AutocompleteOption } from './Autocomplete'
5
5
 
6
6
  const meta: Meta<typeof Autocomplete> = {
7
- title: 'Components/Autocomplete',
7
+ title: 'Components/Molecules/Autocomplete',
8
8
  component: Autocomplete,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Avatar, AvatarBadge, AvatarGroup } from './Avatar'
4
4
 
5
5
  const meta: Meta<typeof Avatar> = {
6
- title: 'Components/Avatar',
6
+ title: 'Components/Atoms/Avatar',
7
7
  component: Avatar,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Badge, BadgeText } from './Badge'
4
4
 
5
5
  const meta: Meta<typeof Badge> = {
6
- title: 'Components/Badge',
6
+ title: 'Components/Atoms/Badge',
7
7
  component: Badge,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -3,7 +3,7 @@ import { Text } from 'react-native'
3
3
  import { Breadcrumbs, BreadcrumbItem } from './Breadcrumbs'
4
4
 
5
5
  const meta: Meta<typeof Breadcrumbs> = {
6
- title: 'Components/Breadcrumbs',
6
+ title: 'Components/Molecules/Breadcrumbs',
7
7
  component: Breadcrumbs,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Button, ButtonText, ButtonIcon } from './Button'
4
4
 
5
5
  const meta: Meta<typeof Button> = {
6
- title: 'Components/Button',
6
+ title: 'Components/Molecules/Button',
7
7
  component: Button,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -13,7 +13,7 @@ import {
13
13
  import { Button, ButtonText } from '../button'
14
14
 
15
15
  const meta: Meta<typeof Card> = {
16
- title: 'Components/Card',
16
+ title: 'Components/Molecules/Card',
17
17
  component: Card,
18
18
  tags: ['autodocs'],
19
19
  argTypes: {
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { Checkbox, CheckboxGroup } from './Checkbox'
4
4
 
5
5
  const meta: Meta<typeof Checkbox> = {
6
- title: 'Components/Checkbox',
6
+ title: 'Components/Molecules/Checkbox',
7
7
  component: Checkbox,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {