@titan-design/react-ui 0.5.0 → 0.7.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.
- package/dist/bodymap.js +241 -189
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +241 -189
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +1017 -130
- package/dist/index.d.ts +1017 -130
- package/dist/index.js +3058 -1090
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2992 -1091
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-MO0JCySL.d.mts → pages-8u_4WbL-.d.mts} +280 -57
- package/dist/{pages-D7Jlssvp.d.ts → pages-DaWiBOGa.d.ts} +280 -57
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1797 -1292
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1797 -1292
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +464 -268
- package/dist/theme/index.d.ts +464 -268
- package/dist/theme/index.js +303 -191
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +295 -192
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +160 -143
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +160 -143
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +3 -1
- package/src/arch/Architecture.stories.tsx +870 -0
- package/src/arch/annotations.json +48 -0
- package/src/arch/arch-graph.json +4301 -0
- package/src/components/custom/DateTime/DateTime.stories.tsx +83 -7
- package/src/components/custom/DateTime/DateTime.test.tsx +29 -3
- package/src/components/custom/DateTime/DateTime.tsx +55 -15
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.stories.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.test.tsx +2 -2
- package/src/components/custom/Gauge/Gauge.tsx +6 -3
- package/src/components/custom/Metric/Metric.stories.tsx +1 -1
- package/src/components/custom/Scatter/Scatter.stories.tsx +1 -1
- package/src/components/custom/Scatter/Scatter.tsx +3 -5
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
- package/src/components/custom/Table/Table.stories.tsx +1 -1
- package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +62 -0
- package/src/components/custom/TimerReadout/TimerReadout.test.tsx +72 -0
- package/src/components/custom/TimerReadout/TimerReadout.tsx +75 -0
- package/src/components/custom/TimerReadout/index.ts +1 -0
- package/src/components/custom/Treemap/Treemap.stories.tsx +1 -1
- package/src/components/custom/Treemap/Treemap.tsx +3 -5
- package/src/components/custom/Typography/Typography.stories.tsx +46 -28
- package/src/components/custom/Typography/Typography.test.tsx +13 -3
- package/src/components/custom/Typography/Typography.tsx +5 -0
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +21 -13
- package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +16 -13
- package/src/components/custom/Workout/ActiveWorkoutPage.tsx +11 -16
- package/src/components/custom/Workout/BaseBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMap.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMap.tsx +6 -3
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +1 -1
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +6 -3
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +1 -1
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +2 -2
- package/src/components/custom/Workout/CapacityBandChart.tsx +9 -6
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.test.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.tsx +7 -4
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +51 -66
- package/src/components/custom/Workout/ExerciseCard.test.tsx +146 -143
- package/src/components/custom/Workout/ExerciseCard.tsx +176 -198
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +99 -0
- package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +72 -0
- package/src/components/custom/Workout/ExerciseCardHeading.tsx +43 -0
- package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +151 -0
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +5 -3
- package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +4 -4
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +6 -6
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +81 -0
- package/src/components/custom/Workout/ExerciseHeading.test.tsx +77 -0
- package/src/components/custom/Workout/ExerciseHeading.tsx +85 -0
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +110 -0
- package/src/components/custom/Workout/ExerciseIndicator.test.tsx +93 -0
- package/src/components/custom/Workout/ExerciseIndicator.tsx +120 -0
- package/src/components/custom/Workout/FatigueMeter.stories.tsx +51 -0
- package/src/components/custom/Workout/FatigueMeter.test.tsx +73 -0
- package/src/components/custom/Workout/FatigueMeter.tsx +82 -0
- package/src/components/custom/Workout/InputBar.stories.tsx +1 -1
- package/src/components/custom/Workout/InputBar.tsx +2 -1
- package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.test.tsx +8 -8
- package/src/components/custom/Workout/IntensityBar.tsx +10 -6
- package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +153 -0
- package/src/components/custom/Workout/LiveAuraFrame.test.tsx +74 -0
- package/src/components/custom/Workout/LiveAuraFrame.tsx +105 -0
- package/src/components/custom/Workout/MesoCard.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoCard.tsx +8 -3
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.test.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.tsx +3 -2
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoStatusCard.tsx +20 -13
- package/src/components/custom/Workout/MetricTiles.stories.tsx +60 -0
- package/src/components/custom/Workout/MetricTiles.test.tsx +58 -0
- package/src/components/custom/Workout/MetricTiles.tsx +48 -0
- package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +1 -1
- package/src/components/custom/Workout/MuscleGroupChip.tsx +7 -4
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
- package/src/components/custom/Workout/PrBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/PrBadge.tsx +5 -2
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +1 -1
- package/src/components/custom/Workout/PrHistoryModal.tsx +4 -3
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +4 -16
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +10 -7
- package/src/components/custom/Workout/README.md +146 -4
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +1 -1
- package/src/components/custom/Workout/ReadinessCheck.tsx +7 -4
- package/src/components/custom/Workout/RestTimer.stories.tsx +1 -1
- package/src/components/custom/Workout/RestTimer.tsx +17 -11
- package/src/components/custom/Workout/RowInventory.stories.tsx +405 -0
- package/src/components/custom/Workout/S3FullRail.stories.tsx +34 -0
- package/src/components/custom/Workout/S3SessionPace.stories.tsx +95 -0
- package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +61 -0
- package/src/components/custom/Workout/S3SetTypes.stories.tsx +176 -0
- package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +240 -0
- package/src/components/custom/Workout/ScheduleTiles.stories.tsx +40 -0
- package/src/components/custom/Workout/ScheduleTiles.test.tsx +34 -0
- package/src/components/custom/Workout/ScheduleTiles.tsx +70 -0
- package/src/components/custom/Workout/SegmentedBar.stories.tsx +99 -0
- package/src/components/custom/Workout/SegmentedBar.test.tsx +77 -0
- package/src/components/custom/Workout/SegmentedBar.tsx +172 -0
- package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +50 -0
- package/src/components/custom/Workout/SegmentedProgressBar.test.tsx +80 -0
- package/src/components/custom/Workout/SegmentedProgressBar.tsx +67 -0
- package/src/components/custom/Workout/SessionHeader.stories.tsx +121 -0
- package/src/components/custom/Workout/SessionHeader.test.tsx +122 -0
- package/src/components/custom/Workout/SessionHeader.tsx +152 -0
- package/src/components/custom/Workout/SessionRail.stories.tsx +153 -0
- package/src/components/custom/Workout/SessionRail.test.tsx +86 -0
- package/src/components/custom/Workout/SessionRail.tsx +126 -0
- package/src/components/custom/Workout/SetBar.stories.tsx +124 -0
- package/src/components/custom/Workout/SetBar.test.tsx +123 -0
- package/src/components/custom/Workout/SetBar.tsx +171 -0
- package/src/components/custom/Workout/SetRow.stories.tsx +50 -100
- package/src/components/custom/Workout/SetRow.test.tsx +94 -166
- package/src/components/custom/Workout/SetRow.tsx +170 -232
- package/src/components/custom/Workout/SetStrip.stories.tsx +154 -0
- package/src/components/custom/Workout/SetStrip.test.tsx +109 -0
- package/src/components/custom/Workout/SetStrip.tsx +71 -0
- package/src/components/custom/Workout/SetTableHeader.stories.tsx +66 -0
- package/src/components/custom/Workout/SetTableHeader.test.tsx +47 -0
- package/src/components/custom/Workout/SetTableHeader.tsx +88 -0
- package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +47 -0
- package/src/components/custom/Workout/SetsRepsLoad.test.tsx +44 -0
- package/src/components/custom/Workout/SetsRepsLoad.tsx +52 -0
- package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
- package/src/components/custom/Workout/Sparkline.tsx +2 -1
- package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusDot.test.tsx +2 -2
- package/src/components/custom/Workout/StatusDot.tsx +12 -9
- package/src/components/custom/Workout/StatusPill.stories.tsx +59 -0
- package/src/components/custom/Workout/StatusPill.test.tsx +63 -0
- package/src/components/custom/Workout/StatusPill.tsx +88 -0
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +1 -1
- package/src/components/custom/Workout/StrengthTrendChart.tsx +9 -6
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +1 -1
- package/src/components/custom/Workout/SupersetWrapper.tsx +2 -1
- package/src/components/custom/Workout/TempoBar.stories.tsx +1 -1
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +12 -1
- package/src/components/custom/Workout/TempoDisplay.tsx +29 -36
- package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +1 -1
- package/src/components/custom/Workout/VelocityStrip.modalities.stories.tsx +254 -0
- package/src/components/custom/Workout/VelocityStrip.responsive.stories.tsx +145 -0
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +129 -66
- package/src/components/custom/Workout/VelocityStrip.test.tsx +379 -144
- package/src/components/custom/Workout/VelocityStrip.tsx +508 -120
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +73 -0
- package/src/components/custom/Workout/VolumeLandmarkBar.test.tsx +119 -0
- package/src/components/custom/Workout/VolumeLandmarkBar.tsx +154 -0
- package/src/components/custom/Workout/WeekRow.stories.tsx +1 -1
- package/src/components/custom/Workout/WeekRow.tsx +3 -2
- package/src/components/custom/Workout/WeightBadge.stories.tsx +1 -1
- package/src/components/custom/Workout/WeightBadge.tsx +6 -2
- package/src/components/custom/Workout/WorkoutCard.stories.tsx +2 -6
- package/src/components/custom/Workout/WorkoutCard.test.tsx +13 -46
- package/src/components/custom/Workout/WorkoutCard.tsx +5 -2
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +1 -1
- package/src/components/custom/Workout/WorkoutPill.tsx +12 -8
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +140 -0
- package/src/components/custom/Workout/ZoneTrack.test.tsx +200 -0
- package/src/components/custom/Workout/ZoneTrack.tsx +315 -0
- package/src/components/custom/Workout/icons.tsx +6 -67
- package/src/components/custom/Workout/index.ts +55 -2
- package/src/components/custom/Workout/metricText.stories.tsx +69 -0
- package/src/components/custom/Workout/metricText.tsx +34 -0
- package/src/components/custom/Workout/paceTone.test.ts +29 -0
- package/src/components/custom/Workout/paceTone.ts +27 -0
- package/src/components/custom/Workout/setHeadingKit.tsx +177 -0
- package/src/components/custom/index.ts +1 -0
- package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
- package/src/components/icons/SvgIcon.tsx +50 -0
- package/src/components/icons/icons.stories.tsx +122 -0
- package/src/components/icons/icons.test.tsx +73 -0
- package/src/components/icons/icons.tsx +153 -0
- package/src/components/icons/index.ts +4 -0
- package/src/components/index.ts +6 -0
- package/src/components/shell/BrandLockup.stories.tsx +27 -0
- package/src/components/shell/BrandLockup.test.tsx +23 -0
- package/src/components/shell/BrandLockup.tsx +47 -0
- package/src/components/shell/DashboardShell.stories.tsx +65 -0
- package/src/components/shell/DashboardShell.test.tsx +42 -0
- package/src/components/shell/DashboardShell.tsx +74 -0
- package/src/components/shell/DeviceIndicator.stories.tsx +28 -0
- package/src/components/shell/DeviceIndicator.test.tsx +26 -0
- package/src/components/shell/DeviceIndicator.tsx +52 -0
- package/src/components/shell/DeviceMenu.stories.tsx +47 -0
- package/src/components/shell/DeviceMenu.test.tsx +40 -0
- package/src/components/shell/DeviceMenu.tsx +65 -0
- package/src/components/shell/DeviceRow.stories.tsx +38 -0
- package/src/components/shell/DeviceRow.test.tsx +37 -0
- package/src/components/shell/DeviceRow.tsx +58 -0
- package/src/components/shell/NavItem.stories.tsx +52 -0
- package/src/components/shell/NavItem.test.tsx +35 -0
- package/src/components/shell/NavItem.tsx +75 -0
- package/src/components/shell/README.md +116 -0
- package/src/components/shell/SessionRailSpecimen.stories.tsx +753 -0
- package/src/components/shell/SessionStatePill.stories.tsx +27 -0
- package/src/components/shell/SessionStatePill.test.tsx +25 -0
- package/src/components/shell/SessionStatePill.tsx +46 -0
- package/src/components/shell/SideNav.stories.tsx +81 -0
- package/src/components/shell/SideNav.test.tsx +51 -0
- package/src/components/shell/SideNav.tsx +74 -0
- package/src/components/shell/TopBar.stories.tsx +49 -0
- package/src/components/shell/TopBar.test.tsx +36 -0
- package/src/components/shell/TopBar.tsx +89 -0
- package/src/components/shell/index.ts +13 -0
- package/src/components/ui/alert/Alert.stories.tsx +1 -1
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
- package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
- package/src/components/ui/badge/Badge.stories.tsx +1 -1
- package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/components/ui/button/Button.stories.tsx +1 -1
- package/src/components/ui/card/Card.stories.tsx +1 -1
- package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
- package/src/components/ui/chip/Chip.stories.tsx +1 -1
- package/src/components/ui/collapse/Collapse.stories.tsx +1 -1
- package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
- package/src/components/ui/divider/Divider.stories.tsx +1 -1
- package/src/components/ui/drawer/Drawer.stories.tsx +1 -1
- package/src/components/ui/form-field/FormField.stories.tsx +1 -1
- package/src/components/ui/help-tip/HelpTip.stories.tsx +1 -1
- package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/indicator/Indicator.stories.tsx +38 -2
- package/src/components/ui/indicator/Indicator.test.tsx +20 -1
- package/src/components/ui/indicator/Indicator.tsx +50 -6
- package/src/components/ui/indicator/index.ts +1 -1
- package/src/components/ui/input/Input.stories.tsx +1 -1
- package/src/components/ui/link/Link.stories.tsx +1 -1
- package/src/components/ui/list-item/ListItem.stories.tsx +1 -1
- package/src/components/ui/menu/Menu.stories.tsx +1 -1
- package/src/components/ui/modal/Modal.stories.tsx +1 -1
- package/src/components/ui/pill/Pill.stories.tsx +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +1 -1
- package/src/components/ui/progress/Progress.stories.tsx +1 -1
- package/src/components/ui/radio/Radio.stories.tsx +1 -1
- package/src/components/ui/section/Section.stories.tsx +1 -1
- package/src/components/ui/select/Select.stories.tsx +1 -1
- package/src/components/ui/skeleton/Skeleton.stories.tsx +1 -1
- package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
- package/src/components/ui/spinner/Spinner.tsx +3 -2
- package/src/components/ui/stack/Stack.stories.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +1 -1
- package/src/components/ui/switch/Switch.stories.tsx +1 -1
- package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
- package/src/components/ui/tile/Tile.stories.tsx +79 -0
- package/src/components/ui/tile/Tile.test.tsx +48 -0
- package/src/components/ui/tile/Tile.tsx +64 -0
- package/src/components/ui/tile/index.ts +2 -0
- package/src/components/ui/toast/Toast.stories.tsx +1 -1
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
- package/src/components/ui/toolbar-button/ToolbarButton.tsx +2 -1
- package/src/components/ui/tooltip/Tooltip.stories.tsx +1 -1
- package/src/examples/react-hook-form/ReactHookForm.stories.tsx +1 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useTimer.test.ts +150 -0
- package/src/hooks/useTimer.ts +77 -0
- package/src/index.ts +3 -0
- package/src/pages.ts +1 -1
- package/src/stories/PresetShowcase.stories.tsx +1 -1
- package/src/stories/ThemePresets.stories.tsx +1 -1
- package/src/theme/ColorSystem.stories.tsx +323 -0
- package/src/theme/Colors.stories.tsx +74 -9
- package/src/theme/barrel.ts +1 -0
- package/src/theme/config.ts +20 -3
- package/src/theme/elevation.stories.tsx +1 -1
- package/src/theme/extracted-colors-dataviz.ts +21 -0
- package/src/theme/extracted-colors-ui.ts +20 -0
- package/src/theme/global.css +69 -53
- package/src/theme/gradients.test.ts +25 -0
- package/src/theme/gradients.ts +36 -0
- package/src/theme/shadows.stories.tsx +1 -1
- package/src/theme/tokens/primitives.test.ts +232 -0
- package/src/theme/tokens/primitives.ts +238 -87
- package/src/theme/tokens/semantic.ts +101 -81
- package/src/theme/workout-tokens.ts +26 -21
- package/src/utils/avatar-color.ts +3 -3
- package/tailwind.config.js +15 -3
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { View } from 'react-native'
|
|
3
|
+
import { StatusPill } from './StatusPill'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof StatusPill> = {
|
|
6
|
+
title: 'Workout/StatusPill',
|
|
7
|
+
component: StatusPill,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'Auto-regulation verdict pill — a glowing status dot plus colored verdict text in a ' +
|
|
14
|
+
'tinted capsule. Composes `StatusDot`; tint, border, text, and dot all derive from the ' +
|
|
15
|
+
'same semantic status token (success / warning / error).',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
status: {
|
|
21
|
+
control: 'select',
|
|
22
|
+
options: ['productive', 'threshold', 'stop'],
|
|
23
|
+
description: 'Auto-regulation verdict',
|
|
24
|
+
},
|
|
25
|
+
label: {
|
|
26
|
+
control: 'text',
|
|
27
|
+
description: 'Overrides the default verdict text',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default meta
|
|
33
|
+
type Story = StoryObj<typeof StatusPill>
|
|
34
|
+
|
|
35
|
+
export const Productive: Story = {
|
|
36
|
+
args: { status: 'productive' },
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const Threshold: Story = {
|
|
40
|
+
args: { status: 'threshold' },
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const Stop: Story = {
|
|
44
|
+
args: { status: 'stop' },
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const WithCustomLabel: Story = {
|
|
48
|
+
args: { status: 'stop', label: 'Stop · velocity loss 31%' },
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const AllStates: Story = {
|
|
52
|
+
render: () => (
|
|
53
|
+
<View style={{ gap: 10, alignItems: 'flex-start' }}>
|
|
54
|
+
<StatusPill status="productive" label="Productive · in the band" />
|
|
55
|
+
<StatusPill status="threshold" label="Threshold · VL20 reached" />
|
|
56
|
+
<StatusPill status="stop" label="Stop · velocity loss 31%" />
|
|
57
|
+
</View>
|
|
58
|
+
),
|
|
59
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import { axe } from 'jest-axe'
|
|
4
|
+
import { StatusPill, statusPillColor, type StatusPillStatus } from './StatusPill'
|
|
5
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
6
|
+
import { alpha } from '../../../utils/colors'
|
|
7
|
+
|
|
8
|
+
const t = getSemanticColors('dark')
|
|
9
|
+
|
|
10
|
+
const cases: Array<{
|
|
11
|
+
status: StatusPillStatus
|
|
12
|
+
token: 'status-success' | 'status-warning' | 'status-error'
|
|
13
|
+
label: string
|
|
14
|
+
}> = [
|
|
15
|
+
{ status: 'productive', token: 'status-success', label: 'Productive' },
|
|
16
|
+
{ status: 'threshold', token: 'status-warning', label: 'Threshold' },
|
|
17
|
+
{ status: 'stop', token: 'status-error', label: 'Stop' },
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
describe('StatusPill', () => {
|
|
21
|
+
it('renders the pill container', () => {
|
|
22
|
+
render(<StatusPill status="productive" />)
|
|
23
|
+
expect(screen.getByTestId('status-pill')).toBeInTheDocument()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('composes a status dot', () => {
|
|
27
|
+
render(<StatusPill status="productive" />)
|
|
28
|
+
expect(screen.getByTestId('status-dot')).toBeInTheDocument()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe('per-status mapping', () => {
|
|
32
|
+
cases.forEach(({ status, token, label }) => {
|
|
33
|
+
it(`maps ${status} to the ${token} color and default label`, () => {
|
|
34
|
+
render(<StatusPill status={status} />)
|
|
35
|
+
const text = screen.getByTestId('status-pill-label')
|
|
36
|
+
expect(text).toHaveTextContent(label)
|
|
37
|
+
expect(text).toHaveStyle({ color: t[token] })
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it(`tints the ${status} capsule from the ${token} token`, () => {
|
|
41
|
+
render(<StatusPill status={status} />)
|
|
42
|
+
expect(screen.getByTestId('status-pill')).toHaveStyle({
|
|
43
|
+
backgroundColor: alpha(t[token], 0.14),
|
|
44
|
+
borderTopColor: alpha(t[token], 0.4),
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('exposes the resolved color via statusPillColor', () => {
|
|
51
|
+
expect(statusPillColor('stop')).toBe(t['status-error'])
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('renders a custom label override', () => {
|
|
55
|
+
render(<StatusPill status="stop" label="Stop · velocity loss 31%" />)
|
|
56
|
+
expect(screen.getByText('Stop · velocity loss 31%')).toBeInTheDocument()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('has no a11y violations', async () => {
|
|
60
|
+
const { container } = render(<StatusPill status="threshold" />)
|
|
61
|
+
expect(await axe(container)).toHaveNoViolations()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
|
+
import { View, Text, type ViewProps } from 'react-native'
|
|
3
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
4
|
+
import { alpha } from '../../../utils/colors'
|
|
5
|
+
import { StatusDot, type StatusDotVariant } from './StatusDot'
|
|
6
|
+
|
|
7
|
+
const t = getSemanticColors('dark')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Auto-regulation verdict — the human-readable read-once summary of a set's
|
|
11
|
+
* velocity-loss state.
|
|
12
|
+
* - `productive` — in the band, keep going (success)
|
|
13
|
+
* - `threshold` — VL20 reached, approaching fatigue (warning)
|
|
14
|
+
* - `stop` — VL28+, terminate the set (error)
|
|
15
|
+
*/
|
|
16
|
+
export type StatusPillStatus = 'productive' | 'threshold' | 'stop'
|
|
17
|
+
|
|
18
|
+
export interface StatusPillProps extends ViewProps {
|
|
19
|
+
status: StatusPillStatus
|
|
20
|
+
/** Overrides the default verdict text for the status. */
|
|
21
|
+
label?: string
|
|
22
|
+
className?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const statusToken: Record<StatusPillStatus, 'status-success' | 'status-warning' | 'status-error'> =
|
|
26
|
+
{
|
|
27
|
+
productive: 'status-success',
|
|
28
|
+
threshold: 'status-warning',
|
|
29
|
+
stop: 'status-error',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const statusDotVariant: Record<StatusPillStatus, StatusDotVariant> = {
|
|
33
|
+
productive: 'success',
|
|
34
|
+
threshold: 'warning',
|
|
35
|
+
stop: 'error',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const defaultLabel: Record<StatusPillStatus, string> = {
|
|
39
|
+
productive: 'Productive',
|
|
40
|
+
threshold: 'Threshold',
|
|
41
|
+
stop: 'Stop',
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Resolved semantic color for a verdict status. */
|
|
45
|
+
export function statusPillColor(status: StatusPillStatus): string {
|
|
46
|
+
return t[statusToken[status]]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Verdict pill: a glowing status dot + colored verdict text, in a tinted,
|
|
51
|
+
* bordered capsule. Composes {@link StatusDot} for the dot so the glow/color
|
|
52
|
+
* stays consistent with the atom. Tint and border are derived from the same
|
|
53
|
+
* semantic token via `alpha()` — no per-status raw hex.
|
|
54
|
+
*/
|
|
55
|
+
export function StatusPill({ status, label, className, style, ...props }: StatusPillProps) {
|
|
56
|
+
const color = statusPillColor(status)
|
|
57
|
+
const text = label ?? defaultLabel[status]
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<View
|
|
61
|
+
testID="status-pill"
|
|
62
|
+
className={className}
|
|
63
|
+
style={[
|
|
64
|
+
{
|
|
65
|
+
flexDirection: 'row',
|
|
66
|
+
alignItems: 'center',
|
|
67
|
+
gap: 7,
|
|
68
|
+
alignSelf: 'flex-start',
|
|
69
|
+
paddingVertical: 7,
|
|
70
|
+
paddingHorizontal: 13,
|
|
71
|
+
borderRadius: 9,
|
|
72
|
+
backgroundColor: alpha(color, 0.14),
|
|
73
|
+
borderWidth: 1,
|
|
74
|
+
borderColor: alpha(color, 0.4),
|
|
75
|
+
},
|
|
76
|
+
style,
|
|
77
|
+
]}
|
|
78
|
+
{...props}
|
|
79
|
+
>
|
|
80
|
+
<View accessibilityElementsHidden>
|
|
81
|
+
<StatusDot variant={statusDotVariant[status]} glow />
|
|
82
|
+
</View>
|
|
83
|
+
<Text testID="status-pill-label" style={{ fontSize: 13, fontWeight: '800', color }}>
|
|
84
|
+
{text}
|
|
85
|
+
</Text>
|
|
86
|
+
</View>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
@@ -32,7 +32,7 @@ const decline: StrengthTrendDataPoint[] = [
|
|
|
32
32
|
]
|
|
33
33
|
|
|
34
34
|
const meta: Meta<typeof StrengthTrendChart> = {
|
|
35
|
-
title: '
|
|
35
|
+
title: 'Workout/DataViz/StrengthTrendChart',
|
|
36
36
|
component: StrengthTrendChart,
|
|
37
37
|
tags: ['autodocs'],
|
|
38
38
|
argTypes: {
|
|
@@ -3,17 +3,20 @@ import { useEffect, useMemo, useState } from 'react'
|
|
|
3
3
|
import { View, Text, Pressable, Animated, Easing, type ViewProps } from 'react-native'
|
|
4
4
|
import { cn } from '../../../utils/cn'
|
|
5
5
|
import { resolveColor } from '../../../theme/resolve-color'
|
|
6
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const sem = getSemanticColors('dark')
|
|
9
|
+
|
|
10
|
+
const BRAND_PRIMARY = sem['brand-primary']
|
|
8
11
|
// Line/border color for the dashed projection, used where a className cannot
|
|
9
12
|
// apply (passed as a prop into an inline style, and a per-edge borderTopColor).
|
|
10
13
|
const PROJECTION_LINE_COLOR = resolveColor('text-tertiary')
|
|
11
|
-
const STATUS_SUCCESS = '
|
|
12
|
-
const STATUS_ERROR = '
|
|
13
|
-
const STATUS_WARNING = '
|
|
14
|
+
const STATUS_SUCCESS = sem['status-success']
|
|
15
|
+
const STATUS_ERROR = sem['status-error']
|
|
16
|
+
const STATUS_WARNING = sem['status-warning']
|
|
14
17
|
const GRID_LINE = 'rgba(255,255,255,0.06)'
|
|
15
|
-
const SUCCESS_PILL_BG = 'rgba(
|
|
16
|
-
const SUCCESS_PILL_BORDER = 'rgba(
|
|
18
|
+
const SUCCESS_PILL_BG = 'rgba(46,213,115,0.10)'
|
|
19
|
+
const SUCCESS_PILL_BORDER = 'rgba(46,213,115,0.20)'
|
|
17
20
|
const ERROR_PILL_BG = 'rgba(209,67,67,0.10)'
|
|
18
21
|
const ERROR_PILL_BORDER = 'rgba(209,67,67,0.20)'
|
|
19
22
|
|
|
@@ -4,7 +4,7 @@ import { SupersetWrapper } from './SupersetWrapper'
|
|
|
4
4
|
import { ExerciseCard } from './ExerciseCard'
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof SupersetWrapper> = {
|
|
7
|
-
title: '
|
|
7
|
+
title: 'Workout/SupersetWrapper',
|
|
8
8
|
component: SupersetWrapper,
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
decorators: [
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { View, Text } from 'react-native'
|
|
4
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
4
5
|
|
|
5
6
|
export interface SupersetWrapperProps {
|
|
6
7
|
label?: string
|
|
@@ -10,7 +11,7 @@ export interface SupersetWrapperProps {
|
|
|
10
11
|
|
|
11
12
|
const DEFAULTS = {
|
|
12
13
|
label: 'SS',
|
|
13
|
-
color: '
|
|
14
|
+
color: getSemanticColors('dark')['brand-primary'],
|
|
14
15
|
bgBase: '#101010',
|
|
15
16
|
} as const
|
|
16
17
|
|
|
@@ -5,9 +5,20 @@ import { TempoDisplay, type TempoLivePhase, type TempoLiveState } from './TempoD
|
|
|
5
5
|
|
|
6
6
|
// tempo = [eccentric, pauseBottom, concentric, pauseTop]
|
|
7
7
|
const meta: Meta<typeof TempoDisplay> = {
|
|
8
|
-
title: '
|
|
8
|
+
title: 'Workout/TempoDisplay',
|
|
9
9
|
component: TempoDisplay,
|
|
10
10
|
tags: ['autodocs'],
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component:
|
|
15
|
+
'**Molecule.** The eccentric/pause/concentric/pause tempo display. Composes ' +
|
|
16
|
+
'[MetricCell](?path=/docs/workout-metriccell--docs) ' +
|
|
17
|
+
'(shared value/separator cell). Used-by ↑ ' +
|
|
18
|
+
'[ExerciseHeading](?path=/docs/workout-exerciseheading--docs) (`showLabel={false}`).',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
11
22
|
argTypes: {
|
|
12
23
|
tempo: {
|
|
13
24
|
control: 'object',
|
|
@@ -3,7 +3,11 @@ import { useState, useCallback } from 'react'
|
|
|
3
3
|
import { View, Text, Pressable, type ViewProps } from 'react-native'
|
|
4
4
|
import { roundTempo } from '../../../utils/workout-format'
|
|
5
5
|
import { alpha } from '../../../utils/colors'
|
|
6
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
6
7
|
import { getTempoFillPct, getTempoPacingState } from './TempoBar'
|
|
8
|
+
import { MetricCell } from './metricText'
|
|
9
|
+
|
|
10
|
+
const t = getSemanticColors('dark')
|
|
7
11
|
|
|
8
12
|
/** The four tempo phases, in the order the display renders them. */
|
|
9
13
|
export type TempoLivePhase = 'eccentric' | 'pauseBottom' | 'concentric' | 'pauseTop'
|
|
@@ -26,6 +30,8 @@ export interface TempoDisplayProps extends ViewProps {
|
|
|
26
30
|
size?: 'sm' | 'md'
|
|
27
31
|
/** Colored phases or mono (all gray) */
|
|
28
32
|
colored?: boolean
|
|
33
|
+
/** Show the "TEMPO" caption before the values. Default true. */
|
|
34
|
+
showLabel?: boolean
|
|
29
35
|
/** Show info tooltip on press */
|
|
30
36
|
showInfo?: boolean
|
|
31
37
|
/**
|
|
@@ -40,13 +46,13 @@ export interface TempoDisplayProps extends ViewProps {
|
|
|
40
46
|
|
|
41
47
|
const INTER = 'Inter, sans-serif'
|
|
42
48
|
const TEXT_TERTIARY = '#6B7280'
|
|
43
|
-
const STATUS_ERROR = '
|
|
49
|
+
const STATUS_ERROR = t['status-error'] // shown when a phase runs behind pace
|
|
44
50
|
|
|
45
51
|
// Phase colors: [eccentric, pauseBottom, concentric, pauseTop]
|
|
46
52
|
const phaseColors = {
|
|
47
|
-
eccentric: '
|
|
53
|
+
eccentric: t['status-warning'],
|
|
48
54
|
pauseBottom: TEXT_TERTIARY,
|
|
49
|
-
concentric: '
|
|
55
|
+
concentric: t['status-success'],
|
|
50
56
|
pauseTop: TEXT_TERTIARY,
|
|
51
57
|
dash: TEXT_TERTIARY,
|
|
52
58
|
}
|
|
@@ -61,33 +67,17 @@ function TempoValue({
|
|
|
61
67
|
fontSize: number
|
|
62
68
|
}) {
|
|
63
69
|
return (
|
|
64
|
-
<
|
|
65
|
-
style={{
|
|
66
|
-
fontFamily: INTER,
|
|
67
|
-
fontSize,
|
|
68
|
-
color,
|
|
69
|
-
fontWeight: '600',
|
|
70
|
-
letterSpacing: 1,
|
|
71
|
-
}}
|
|
72
|
-
>
|
|
70
|
+
<MetricCell color={color} fontSize={fontSize}>
|
|
73
71
|
{value}
|
|
74
|
-
</
|
|
72
|
+
</MetricCell>
|
|
75
73
|
)
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
function TempoSeparator({ color, fontSize }: { color: string; fontSize: number }) {
|
|
79
77
|
return (
|
|
80
|
-
<
|
|
81
|
-
style={{
|
|
82
|
-
fontFamily: INTER,
|
|
83
|
-
fontSize,
|
|
84
|
-
color,
|
|
85
|
-
fontWeight: '600',
|
|
86
|
-
letterSpacing: 1,
|
|
87
|
-
}}
|
|
88
|
-
>
|
|
78
|
+
<MetricCell color={color} fontSize={fontSize}>
|
|
89
79
|
-
|
|
90
|
-
</
|
|
80
|
+
</MetricCell>
|
|
91
81
|
)
|
|
92
82
|
}
|
|
93
83
|
|
|
@@ -167,6 +157,7 @@ export function TempoDisplay({
|
|
|
167
157
|
tempo,
|
|
168
158
|
size = 'md',
|
|
169
159
|
colored = true,
|
|
160
|
+
showLabel = true,
|
|
170
161
|
showInfo = true,
|
|
171
162
|
live,
|
|
172
163
|
onPress,
|
|
@@ -202,19 +193,21 @@ export function TempoDisplay({
|
|
|
202
193
|
}}
|
|
203
194
|
{...props}
|
|
204
195
|
>
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
196
|
+
{showLabel && (
|
|
197
|
+
<Text
|
|
198
|
+
style={{
|
|
199
|
+
fontFamily: INTER,
|
|
200
|
+
fontSize: 9,
|
|
201
|
+
fontWeight: '500',
|
|
202
|
+
color: TEXT_TERTIARY,
|
|
203
|
+
letterSpacing: 0.5,
|
|
204
|
+
textTransform: 'uppercase',
|
|
205
|
+
marginRight: 6,
|
|
206
|
+
}}
|
|
207
|
+
>
|
|
208
|
+
TEMPO
|
|
209
|
+
</Text>
|
|
210
|
+
)}
|
|
218
211
|
<View style={{ flexDirection: 'row' }} testID="tempo-value">
|
|
219
212
|
{live ? (
|
|
220
213
|
<LiveTempoRow
|
|
@@ -181,7 +181,7 @@ const muscles: TrainingStatusMuscle[] = [
|
|
|
181
181
|
]
|
|
182
182
|
|
|
183
183
|
const meta: Meta<typeof TrainingStatusPage> = {
|
|
184
|
-
title: '
|
|
184
|
+
title: 'Pages/Training Status',
|
|
185
185
|
component: TrainingStatusPage,
|
|
186
186
|
parameters: { layout: 'fullscreen' },
|
|
187
187
|
tags: ['autodocs'],
|