@titan-design/react-ui 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -47
- package/dist/bodymap.js +856 -736
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +858 -738
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +1431 -237
- package/dist/index.d.ts +1431 -237
- package/dist/index.js +6506 -4781
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6280 -4642
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-B1hqnGIC.d.ts → pages-CsjsUn0G.d.ts} +51 -16
- package/dist/{pages-CvsFqNtx.d.mts → pages-ZbT_pD_U.d.mts} +51 -16
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1919 -1937
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1927 -1945
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +225 -140
- package/dist/theme/index.d.ts +225 -140
- package/dist/theme/index.js +298 -319
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +283 -315
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +145 -24
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +145 -24
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/dist/theme/tokens.d.mts +128 -11
- package/dist/theme/tokens.d.ts +128 -11
- package/dist/theme/tokens.js +126 -26
- package/dist/theme/tokens.js.map +1 -1
- package/dist/theme/tokens.mjs +124 -27
- package/dist/theme/tokens.mjs.map +1 -1
- package/docs/audits/2026-09-08-critique-addenda.md +51 -0
- package/docs/audits/2026-09-08-library-critique.md +212 -0
- package/docs/library-roadmap.md +99 -0
- package/docs/render-testing-pattern.md +130 -0
- package/package.json +1 -1
- package/src/arch/Architecture.stories.tsx +3 -1
- package/src/arch/arch-graph.freshness.test.ts +52 -0
- package/src/arch/arch-graph.json +4989 -1583
- package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
- package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
- package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
- package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
- package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
- package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
- package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
- package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
- package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
- package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
- package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
- package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.tsx +182 -0
- package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
- package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
- package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
- package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
- package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
- package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
- package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
- package/src/components/custom/ActiveWork/README.md +305 -0
- package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
- package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
- package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
- package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
- package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
- package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
- package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
- package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
- package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
- package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
- package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
- package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
- package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
- package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
- package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
- package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
- package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
- package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
- package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
- package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
- package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
- package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
- package/src/components/custom/ActiveWork/format-time.ts +32 -0
- package/src/components/custom/ActiveWork/index.ts +19 -0
- package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
- package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
- package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
- package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
- package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +12 -6
- package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
- package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
- package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
- package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
- package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
- package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
- package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
- package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
- package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
- package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
- package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
- package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
- package/src/components/custom/Fatigue/README.md +40 -3
- package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
- package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
- package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
- package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
- package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
- package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
- package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
- package/src/components/custom/Fatigue/index.ts +17 -5
- package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
- package/src/components/custom/Fatigue/panel-layout.ts +185 -0
- package/src/components/custom/Gauge/Gauge.stories.tsx +6 -3
- package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.tsx +7 -2
- package/src/components/custom/Metric/Metric.stories.tsx +10 -1
- package/src/components/custom/Metric/Metric.test.tsx +1 -3
- package/src/components/custom/Metric/Metric.tsx +5 -20
- package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
- package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
- package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
- package/src/components/custom/Prose/README.md +58 -0
- package/src/components/custom/Prose/index.ts +1 -0
- package/src/components/custom/Scatter/Scatter.stories.tsx +55 -14
- package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
- package/src/components/custom/Scatter/Scatter.tsx +122 -18
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +41 -8
- package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
- package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
- package/src/components/custom/Table/Table.stories.tsx +99 -16
- package/src/components/custom/Table/Table.test.tsx +273 -86
- package/src/components/custom/Table/Table.tsx +159 -67
- package/src/components/custom/Table/column-fit.test.ts +75 -0
- package/src/components/custom/Table/column-fit.ts +116 -0
- package/src/components/custom/Table/index.ts +9 -0
- package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
- package/src/components/custom/Treemap/Treemap.stories.tsx +15 -12
- package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
- package/src/components/custom/Treemap/Treemap.tsx +11 -3
- package/src/components/custom/Typography/Typography.stories.tsx +28 -1
- package/src/components/custom/Typography/Typography.test.tsx +34 -0
- package/src/components/custom/Typography/Typography.tsx +6 -0
- package/src/components/custom/Typography/index.ts +1 -8
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +11 -2
- package/src/components/custom/Workout/BaseBadge.stories.tsx +27 -11
- package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
- package/src/components/custom/Workout/BaseBadge.tsx +6 -2
- package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
- package/src/components/custom/Workout/BodyMap.tsx +8 -4
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +28 -6
- package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +50 -12
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +12 -9
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
- package/src/components/custom/Workout/CapacityBandChart.tsx +144 -111
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.test.tsx +10 -4
- package/src/components/custom/Workout/DeviationBar.tsx +24 -16
- package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +183 -0
- package/src/components/custom/Workout/DualVelocityStrip.test.tsx +32 -18
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +12 -11
- package/src/components/custom/Workout/ExerciseCard.test.tsx +52 -22
- package/src/components/custom/Workout/ExerciseCard.tsx +99 -183
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +95 -12
- package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +189 -1
- package/src/components/custom/Workout/ExerciseCardHeading.tsx +167 -18
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +3 -2
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
- package/src/components/custom/Workout/ExerciseHeading.tsx +194 -46
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +12 -9
- package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
- package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
- package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
- package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
- package/src/components/custom/Workout/InputBar.tsx +4 -2
- package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
- package/src/components/custom/Workout/IntensityBar.tsx +8 -3
- package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
- package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
- package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
- package/src/components/custom/Workout/MesoCard.tsx +14 -10
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
- package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
- package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
- package/src/components/custom/Workout/MesoStatusCard.tsx +20 -33
- package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
- package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
- package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
- package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +9 -4
- package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
- package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
- package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
- package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
- package/src/components/custom/Workout/PrBadge.tsx +13 -17
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +16 -3
- package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
- package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
- package/src/components/custom/Workout/README.md +68 -17
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
- package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
- package/src/components/custom/Workout/ReadinessCheck.tsx +22 -4
- package/src/components/custom/Workout/RestTimer.stories.tsx +16 -4
- package/src/components/custom/Workout/RestTimer.tsx +4 -2
- package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
- package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
- package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
- package/src/components/custom/Workout/SegmentedBar.stories.tsx +21 -17
- package/src/components/custom/Workout/SegmentedBar.tsx +10 -5
- package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
- package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
- package/src/components/custom/Workout/SessionHeader.tsx +12 -12
- package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
- package/src/components/custom/Workout/SessionRail.tsx +7 -9
- package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
- package/src/components/custom/Workout/SetBar.test.tsx +49 -4
- package/src/components/custom/Workout/SetBar.tsx +38 -12
- package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
- package/src/components/custom/Workout/SetRow.test.tsx +16 -2
- package/src/components/custom/Workout/SetRow.tsx +61 -23
- package/src/components/custom/Workout/SetStrip.stories.tsx +63 -7
- package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
- package/src/components/custom/Workout/SetStrip.tsx +24 -4
- package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
- package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
- package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
- package/src/components/custom/Workout/SetsRepsLoad.tsx +24 -12
- package/src/components/custom/Workout/Sparkline.stories.tsx +14 -11
- package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
- package/src/components/custom/Workout/Sparkline.tsx +14 -18
- package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
- package/src/components/custom/Workout/StatusDot.tsx +93 -63
- package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
- package/src/components/custom/Workout/StatusPill.tsx +27 -38
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +11 -4
- package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
- package/src/components/custom/Workout/StrengthTrendChart.tsx +39 -36
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
- package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
- package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +26 -10
- package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
- package/src/components/custom/Workout/TempoDisplay.tsx +2 -0
- package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
- package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
- package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +10 -6
- package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +5 -2
- package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +44 -1
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
- package/src/components/custom/Workout/VelocityStrip.test.tsx +48 -6
- package/src/components/custom/Workout/VelocityStrip.tsx +26 -14
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
- package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
- package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
- package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
- package/src/components/custom/Workout/WeekRow.tsx +23 -16
- package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
- package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
- package/src/components/custom/Workout/WeightBadge.tsx +28 -27
- package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
- package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
- package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
- package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
- package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +10 -7
- package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
- package/src/components/custom/Workout/exerciseRowState.ts +29 -0
- package/src/components/custom/Workout/index.ts +17 -2
- package/src/components/custom/Workout/metricText.stories.tsx +15 -13
- package/src/components/custom/Workout/metricText.tsx +8 -2
- package/src/components/custom/Workout/setHeadingKit.tsx +219 -36
- package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
- package/src/components/custom/charts/README.md +66 -0
- package/src/components/custom/charts/SetBarChart.test.tsx +46 -1
- package/src/components/custom/charts/SetBarChart.tsx +56 -9
- package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
- package/src/components/custom/charts/SparkBars.test.tsx +69 -0
- package/src/components/custom/charts/SparkBars.tsx +85 -0
- package/src/components/custom/charts/flatBarGeometry.test.ts +41 -0
- package/src/components/custom/charts/flatBarGeometry.ts +32 -0
- package/src/components/custom/charts/index.ts +3 -0
- package/src/components/custom/index.ts +3 -0
- package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
- package/src/components/custom/stepper/Stepper.test.tsx +1 -7
- package/src/components/custom/stepper/Stepper.tsx +21 -34
- package/src/components/icons/icons.stories.tsx +1 -1
- package/src/components/icons/icons.tsx +51 -0
- package/src/components/shell/AppShell.stories.tsx +150 -0
- package/src/components/shell/AppShell.test.tsx +70 -0
- package/src/components/shell/AppShell.tsx +90 -0
- package/src/components/shell/BrandLockup.stories.tsx +66 -5
- package/src/components/shell/BrandLockup.test.tsx +34 -1
- package/src/components/shell/BrandLockup.tsx +27 -11
- package/src/components/shell/NavItem.stories.tsx +4 -4
- package/src/components/shell/NavItem.test.tsx +17 -0
- package/src/components/shell/NavItem.tsx +17 -5
- package/src/components/shell/README.md +89 -26
- package/src/components/shell/SideNav.stories.tsx +38 -7
- package/src/components/shell/SideNav.test.tsx +16 -8
- package/src/components/shell/SideNav.tsx +17 -17
- package/src/components/shell/TopBar.stories.tsx +44 -19
- package/src/components/shell/TopBar.test.tsx +34 -12
- package/src/components/shell/TopBar.tsx +61 -40
- package/src/components/shell/brands.tsx +66 -0
- package/src/components/shell/index.ts +9 -8
- package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
- package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
- package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
- package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
- package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
- package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
- package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
- package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
- package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
- package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
- package/src/components/shell/workout/WorkoutShell.tsx +77 -0
- package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
- package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
- package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
- package/src/components/shell/workout/index.ts +9 -0
- package/src/components/shell/workout/workoutNavItems.tsx +16 -0
- package/src/components/ui/README.md +110 -0
- package/src/components/ui/alert/Alert.stories.tsx +15 -5
- package/src/components/ui/alert/Alert.tsx +24 -3
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
- package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
- package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
- package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
- package/src/components/ui/avatar/Avatar.tsx +2 -10
- package/src/components/ui/badge/Badge.stories.tsx +83 -28
- package/src/components/ui/badge/Badge.test.tsx +19 -3
- package/src/components/ui/badge/Badge.tsx +48 -55
- package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
- package/src/components/ui/button/Button.stories.tsx +46 -12
- package/src/components/ui/button/Button.tsx +44 -37
- package/src/components/ui/card/Card.stories.tsx +90 -94
- package/src/components/ui/card/Card.test.tsx +80 -6
- package/src/components/ui/card/Card.tsx +150 -203
- package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
- package/src/components/ui/checkbox/Checkbox.tsx +7 -27
- package/src/components/ui/chip/Chip.stories.tsx +37 -13
- package/src/components/ui/chip/Chip.test.tsx +10 -6
- package/src/components/ui/chip/Chip.tsx +76 -91
- package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
- package/src/components/ui/collapse/Collapse.tsx +6 -11
- package/src/components/ui/data-row/DataRow.stories.tsx +14 -3
- package/src/components/ui/data-row/DataRow.test.tsx +5 -15
- package/src/components/ui/data-row/DataRow.tsx +18 -7
- package/src/components/ui/divider/Divider.stories.tsx +1 -1
- package/src/components/ui/divider/Divider.tsx +1 -5
- package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
- package/src/components/ui/drawer/Drawer.tsx +13 -27
- package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
- package/src/components/ui/form-field/FormField.stories.tsx +6 -20
- package/src/components/ui/form-field/FormField.test.tsx +1 -5
- package/src/components/ui/form-field/FormField.tsx +10 -46
- package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
- package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
- package/src/components/ui/help-tip/HelpTip.tsx +21 -22
- package/src/components/ui/help-tip/index.ts +7 -1
- package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
- package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
- package/src/components/ui/icon-box/IconBox.tsx +10 -18
- package/src/components/ui/indicator/Indicator.stories.tsx +5 -4
- package/src/components/ui/indicator/Indicator.tsx +20 -14
- package/src/components/ui/input/Input.stories.tsx +3 -11
- package/src/components/ui/input/Input.test.tsx +2 -10
- package/src/components/ui/input/Input.tsx +10 -25
- package/src/components/ui/input/index.ts +7 -1
- package/src/components/ui/link/Link.stories.tsx +19 -7
- package/src/components/ui/list-item/ListItem.stories.tsx +17 -5
- package/src/components/ui/list-item/ListItem.tsx +2 -9
- package/src/components/ui/menu/Menu.stories.tsx +21 -15
- package/src/components/ui/menu/Menu.test.tsx +2 -11
- package/src/components/ui/menu/Menu.tsx +12 -14
- package/src/components/ui/menu/index.ts +8 -1
- package/src/components/ui/modal/Modal.stories.tsx +2 -2
- package/src/components/ui/modal/Modal.tsx +31 -19
- package/src/components/ui/pill/Pill.stories.tsx +111 -23
- package/src/components/ui/pill/Pill.test.tsx +101 -3
- package/src/components/ui/pill/Pill.tsx +168 -49
- package/src/components/ui/pill/index.ts +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +6 -8
- package/src/components/ui/popover/Popover.test.tsx +1 -6
- package/src/components/ui/popover/Popover.tsx +20 -15
- package/src/components/ui/popover/index.ts +7 -1
- package/src/components/ui/progress/Progress.stories.tsx +3 -12
- package/src/components/ui/progress/Progress.test.tsx +1 -5
- package/src/components/ui/progress/Progress.tsx +9 -6
- package/src/components/ui/radio/Radio.stories.tsx +42 -21
- package/src/components/ui/radio/Radio.test.tsx +6 -2
- package/src/components/ui/radio/Radio.tsx +23 -22
- package/src/components/ui/section/Section.stories.tsx +12 -21
- package/src/components/ui/section/Section.test.tsx +1 -6
- package/src/components/ui/section/Section.tsx +1 -3
- package/src/components/ui/section/index.ts +1 -5
- package/src/components/ui/select/Select.stories.tsx +3 -13
- package/src/components/ui/select/Select.test.tsx +2 -11
- package/src/components/ui/select/Select.tsx +16 -15
- package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
- package/src/components/ui/skeleton/Skeleton.tsx +3 -14
- package/src/components/ui/skeleton/index.ts +1 -7
- package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
- package/src/components/ui/spinner/Spinner.tsx +4 -5
- package/src/components/ui/stack/Stack.stories.tsx +8 -8
- package/src/components/ui/stack/Stack.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +92 -33
- package/src/components/ui/surface/Surface.test.tsx +88 -28
- package/src/components/ui/surface/Surface.tsx +37 -87
- package/src/components/ui/surface/SurfaceContext.ts +22 -62
- package/src/components/ui/surface/index.ts +8 -0
- package/src/components/ui/surface/resolveSurface.ts +98 -0
- package/src/components/ui/surface/surface.contract.test.ts +6 -1
- package/src/components/ui/switch/Switch.stories.tsx +1 -1
- package/src/components/ui/switch/Switch.tsx +7 -6
- package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
- package/src/components/ui/tabs/Tabs.tsx +8 -21
- package/src/components/ui/tabs/index.ts +1 -7
- package/src/components/ui/tile/Tile.stories.tsx +1 -1
- package/src/components/ui/tile/Tile.tsx +3 -0
- package/src/components/ui/toast/Toast.stories.tsx +1 -1
- package/src/components/ui/toast/Toast.test.tsx +2 -8
- package/src/components/ui/toast/Toast.tsx +49 -57
- package/src/components/ui/toast/index.ts +0 -1
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
- package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
- package/src/components/ui/toolbar-button/ToolbarButton.tsx +38 -49
- package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
- package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
- package/src/components/ui/tooltip/Tooltip.tsx +55 -36
- package/src/components/ui/tooltip/index.ts +1 -1
- package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
- package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
- package/src/components/ui/trigger/index.ts +2 -0
- package/src/stories/PresetShowcase.stories.tsx +101 -48
- package/src/test/no-device-internals.test.ts +3 -3
- package/src/test/no-raw-color.test.ts +39 -0
- package/src/theme/Alpha.stories.tsx +103 -0
- package/src/theme/ChoosingTokens.stories.tsx +48 -0
- package/src/theme/ColorPalettes.stories.tsx +62 -45
- package/src/theme/ColorPrimitives.stories.tsx +35 -35
- package/src/theme/Depth.stories.tsx +132 -65
- package/src/theme/DepthCalibration.stories.tsx +23 -21
- package/src/theme/ProposedTokensVW82.stories.tsx +414 -0
- package/src/theme/ThemeProvider.test.tsx +4 -4
- package/src/theme/barrel.ts +7 -6
- package/src/theme/color-stories.coverage.test.ts +1 -1
- package/src/theme/color-utils.ts +41 -29
- package/src/theme/config.completeness.test.ts +1 -1
- package/src/theme/config.ts +40 -0
- package/src/theme/elevation.test.ts +82 -56
- package/src/theme/elevation.ts +77 -561
- package/src/theme/global.css +45 -5
- package/src/theme/grey-ramp.test.ts +24 -8
- package/src/theme/lift.test.ts +39 -0
- package/src/theme/lift.ts +102 -0
- package/src/theme/materials.test.ts +5 -2
- package/src/theme/materials.ts +38 -4
- package/src/theme/native-theming-guard.test.ts +5 -5
- package/src/theme/presets/apply.ts +4 -0
- package/src/theme/presets/audiobook.ts +5 -2
- package/src/theme/presets/default.ts +4 -0
- package/src/theme/presets/index.ts +14 -1
- package/src/theme/presets/types.ts +1 -1
- package/src/theme/semantic-contrast.test.ts +13 -4
- package/src/theme/status-distinctness.test.ts +66 -0
- package/src/theme/subtle-tone-weight.test.ts +163 -0
- package/src/theme/surface-planes.test.ts +37 -0
- package/src/theme/surface-planes.ts +68 -0
- package/src/theme/tailwind-var-opacity.test.ts +163 -0
- package/src/theme/token-export-guard.test.ts +1 -3
- package/src/theme/tokens/primitives.test.ts +15 -7
- package/src/theme/tokens/primitives.ts +98 -33
- package/src/theme/tokens/semantic-hex-guard.test.ts +322 -0
- package/src/theme/tokens/semantic.ts +124 -54
- package/src/theme/wash-ladder.test.ts +58 -0
- package/src/theme/workout-tokens.ts +1 -7
- package/src/types/jest-axe.d.ts +2 -6
- package/src/types/raw-md.d.ts +5 -0
- package/src/utils/colors.alpha-adoption.test.ts +408 -0
- package/src/utils/colors.ts +4 -4
- package/src/utils/form.ts +1 -3
- package/src/utils/index.ts +2 -7
- package/src/utils/number-format.ts +17 -0
- package/src/utils/workout-format.ts +15 -6
- package/src/web-jsx/jsx-runtime.ts +1 -5
- package/tailwind.config.js +55 -9
- package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
- package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
- package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
- package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
- package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
- package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
- package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
- package/src/components/shell/DashboardShell.stories.tsx +0 -65
- package/src/components/shell/DashboardShell.tsx +0 -75
- package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
- package/src/theme/elevation.stories.tsx +0 -346
- package/src/utils/useTheme.ts +0 -72
- /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
- /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
- /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
- /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
|
@@ -53,6 +53,8 @@ export interface TempoDisplayProps extends ViewProps {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const INTER = 'Inter, sans-serif'
|
|
56
|
+
// VW-82: Tailwind gray-500, not titan's text-tertiary (#888684) despite the name.
|
|
57
|
+
// Left raw — re-pointing it at the ramp is a visual change awaiting sign-off.
|
|
56
58
|
const TEXT_TERTIARY = '#6B7280'
|
|
57
59
|
const STATUS_ERROR = t['status-error'] // slow — over the target time
|
|
58
60
|
const STATUS_SUCCESS = t['status-success'] // on target (within the band of 0.0)
|
|
@@ -183,7 +183,15 @@ const muscles: TrainingStatusMuscle[] = [
|
|
|
183
183
|
const meta: Meta<typeof TrainingStatusPage> = {
|
|
184
184
|
title: 'Pages/Training Status',
|
|
185
185
|
component: TrainingStatusPage,
|
|
186
|
-
parameters: {
|
|
186
|
+
parameters: {
|
|
187
|
+
layout: 'fullscreen',
|
|
188
|
+
docs: {
|
|
189
|
+
description: {
|
|
190
|
+
component:
|
|
191
|
+
'Composes **BodyMap** · **BodyMapDetailPanel** · **MesoStatusCard** · **MuscleGroup**.',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
},
|
|
187
195
|
tags: ['autodocs'],
|
|
188
196
|
args: { title: 'Training Status', meso, muscles },
|
|
189
197
|
}
|
|
@@ -23,8 +23,11 @@ import {
|
|
|
23
23
|
* vertical space as a single — 2x is only forced for the value-height expanded.
|
|
24
24
|
*/
|
|
25
25
|
const meta: Meta<typeof VelocityStrip> = {
|
|
26
|
-
title: 'Workout/DataViz/VelocityStrip/Compact',
|
|
26
|
+
title: 'Custom/Workout/DataViz/VelocityStrip/Compact',
|
|
27
27
|
component: VelocityStrip,
|
|
28
|
+
parameters: {
|
|
29
|
+
docs: { description: { component: 'Composes **SetBarChart** · **ChartSideRail**.' } },
|
|
30
|
+
},
|
|
28
31
|
tags: ['autodocs'],
|
|
29
32
|
}
|
|
30
33
|
export default meta
|
|
@@ -17,9 +17,9 @@ import {
|
|
|
17
17
|
* Dual is **not a fourth view**, so its scenario coverage lives in the
|
|
18
18
|
* per-view groups, where every scenario renders single ABOVE dual on one
|
|
19
19
|
* dataset:
|
|
20
|
-
* [Compact](?path=/docs/workout-dataviz-velocitystrip-compact--docs) ·
|
|
21
|
-
* [Expanded](?path=/docs/workout-dataviz-velocitystrip-expanded--docs) ·
|
|
22
|
-
* [Hero](?path=/docs/workout-dataviz-velocitystrip-hero--docs).
|
|
20
|
+
* [Compact](?path=/docs/custom-workout-dataviz-velocitystrip-compact--docs) ·
|
|
21
|
+
* [Expanded](?path=/docs/custom-workout-dataviz-velocitystrip-expanded--docs) ·
|
|
22
|
+
* [Hero](?path=/docs/custom-workout-dataviz-velocitystrip-hero--docs).
|
|
23
23
|
*
|
|
24
24
|
* This group exists for the two things a pairing cannot carry: the exported
|
|
25
25
|
* **API** (`DualVelocityStripProps`, in the args table below) and the layout
|
|
@@ -37,8 +37,11 @@ import {
|
|
|
37
37
|
* not a hardcoded side. Single-slot sets keep using `VelocityStrip`.
|
|
38
38
|
*/
|
|
39
39
|
const meta: Meta<typeof DualVelocityStrip> = {
|
|
40
|
-
title: 'Workout/DataViz/VelocityStrip/Dual',
|
|
40
|
+
title: 'Custom/Workout/DataViz/VelocityStrip/Dual',
|
|
41
41
|
component: DualVelocityStrip,
|
|
42
|
+
parameters: {
|
|
43
|
+
docs: { description: { component: 'Composes **SetBarChart** · **ChartSideRail**.' } },
|
|
44
|
+
},
|
|
42
45
|
tags: ['autodocs'],
|
|
43
46
|
decorators: [wallDecorator],
|
|
44
47
|
argTypes: {
|
|
@@ -54,9 +57,10 @@ const meta: Meta<typeof DualVelocityStrip> = {
|
|
|
54
57
|
},
|
|
55
58
|
variant: {
|
|
56
59
|
control: 'inline-radio',
|
|
57
|
-
options: ['hero', 'compact', '
|
|
60
|
+
options: ['hero', 'compact', 'dual-expanded'],
|
|
58
61
|
description:
|
|
59
|
-
'hero (wall: labels + reference lines), compact (flat resting fold), or
|
|
62
|
+
'hero (wall: labels + reference lines), compact (flat resting fold), or dual-expanded ' +
|
|
63
|
+
'(lean, neither — `"rail"` is a deprecated alias for the same renderer)',
|
|
60
64
|
},
|
|
61
65
|
scale: {
|
|
62
66
|
control: 'inline-radio',
|
|
@@ -32,8 +32,11 @@ import {
|
|
|
32
32
|
* meaning.
|
|
33
33
|
*/
|
|
34
34
|
const meta: Meta<typeof VelocityStrip> = {
|
|
35
|
-
title: 'Workout/DataViz/VelocityStrip/Expanded',
|
|
35
|
+
title: 'Custom/Workout/DataViz/VelocityStrip/Expanded',
|
|
36
36
|
component: VelocityStrip,
|
|
37
|
+
parameters: {
|
|
38
|
+
docs: { description: { component: 'Composes **SetBarChart** · **ChartSideRail**.' } },
|
|
39
|
+
},
|
|
37
40
|
tags: ['autodocs'],
|
|
38
41
|
}
|
|
39
42
|
export default meta
|
|
@@ -196,7 +199,7 @@ export const Responsive: Story = {
|
|
|
196
199
|
<DualVelocityStrip
|
|
197
200
|
left={{ velocities: REP_SET, label: 'Left' }}
|
|
198
201
|
right={{ velocities: REP_SET_LAGGING, label: 'Right' }}
|
|
199
|
-
variant="
|
|
202
|
+
variant="dual-expanded"
|
|
200
203
|
height={h}
|
|
201
204
|
scale="fixed"
|
|
202
205
|
/>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import { View } from 'react-native'
|
|
3
3
|
import { VelocityStrip, DualVelocityStrip } from './VelocityStrip'
|
|
4
|
+
import { FIXED_MAX_VALUE, PEAK_HEADROOM } from '../charts/SetBarChart'
|
|
4
5
|
import {
|
|
5
6
|
Sheet,
|
|
6
7
|
Note,
|
|
@@ -31,8 +32,11 @@ import {
|
|
|
31
32
|
* sets and do not reflow as each rep lands.
|
|
32
33
|
*/
|
|
33
34
|
const meta: Meta<typeof VelocityStrip> = {
|
|
34
|
-
title: 'Workout/DataViz/VelocityStrip/Hero',
|
|
35
|
+
title: 'Custom/Workout/DataViz/VelocityStrip/Hero',
|
|
35
36
|
component: VelocityStrip,
|
|
37
|
+
parameters: {
|
|
38
|
+
docs: { description: { component: 'Composes **SetBarChart** · **ChartSideRail**.' } },
|
|
39
|
+
},
|
|
36
40
|
tags: ['autodocs'],
|
|
37
41
|
}
|
|
38
42
|
export default meta
|
|
@@ -213,6 +217,45 @@ export const RepTypes: Story = {
|
|
|
213
217
|
),
|
|
214
218
|
}
|
|
215
219
|
|
|
220
|
+
/**
|
|
221
|
+
* VW-97: `scale="fixed"` used the bare `FIXED_MAX_VALUE` ceiling with no headroom multiplier, so a
|
|
222
|
+
* rep AT the ceiling filled the plot to its very top with no room for its own label — unlike an
|
|
223
|
+
* equally-tall `peak` bar, which always kept `PEAK_HEADROOM`'s margin. `scaleDenominator` now
|
|
224
|
+
* applies the same headroom to both scales.
|
|
225
|
+
*
|
|
226
|
+
* "Before" reproduces the old denominator through the public `scaleMax` prop (`scaleMax *
|
|
227
|
+
* PEAK_HEADROOM` cancels back down to the bare ceiling) rather than a hand-rolled duplicate, so
|
|
228
|
+
* this story exercises the real component on both sides.
|
|
229
|
+
*/
|
|
230
|
+
export const FixedScaleHeadroom: Story = {
|
|
231
|
+
name: 'Fixed Scale Headroom (VW-97)',
|
|
232
|
+
decorators: [wallDecorator],
|
|
233
|
+
render: () => (
|
|
234
|
+
<View style={{ flexDirection: 'row', gap: 24 }}>
|
|
235
|
+
<View style={{ gap: 8, flex: 1 }}>
|
|
236
|
+
<ViewLabel text="before · ceiling bar touches the plot top" />
|
|
237
|
+
<VelocityStrip
|
|
238
|
+
velocities={[FIXED_MAX_VALUE, FIXED_MAX_VALUE * 0.6]}
|
|
239
|
+
variant="hero"
|
|
240
|
+
label="Set"
|
|
241
|
+
height={140}
|
|
242
|
+
scaleMax={FIXED_MAX_VALUE / PEAK_HEADROOM}
|
|
243
|
+
/>
|
|
244
|
+
</View>
|
|
245
|
+
<View style={{ gap: 8, flex: 1 }}>
|
|
246
|
+
<ViewLabel text="after · fixed reserves the same headroom peak does" />
|
|
247
|
+
<VelocityStrip
|
|
248
|
+
velocities={[FIXED_MAX_VALUE, FIXED_MAX_VALUE * 0.6]}
|
|
249
|
+
variant="hero"
|
|
250
|
+
label="Set"
|
|
251
|
+
height={140}
|
|
252
|
+
scale="fixed"
|
|
253
|
+
/>
|
|
254
|
+
</View>
|
|
255
|
+
</View>
|
|
256
|
+
),
|
|
257
|
+
}
|
|
258
|
+
|
|
216
259
|
export const EdgeCases: Story = {
|
|
217
260
|
name: 'Edge Cases',
|
|
218
261
|
decorators: [wallDecorator],
|
|
@@ -16,14 +16,15 @@ import {
|
|
|
16
16
|
REP_SET_LAGGING,
|
|
17
17
|
type StripView,
|
|
18
18
|
} from './velocity-story-kit'
|
|
19
|
+
import { Surface } from '../../ui/surface'
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Per-rep velocity strip.
|
|
22
23
|
*
|
|
23
24
|
* Three views, each with its own story group:
|
|
24
|
-
* - **[Compact](?path=/docs/workout-dataviz-velocitystrip-compact--docs)** — the flat resting strip
|
|
25
|
-
* - **[Expanded](?path=/docs/workout-dataviz-velocitystrip-expanded--docs)** — the value-height chart
|
|
26
|
-
* - **[Hero](?path=/docs/workout-dataviz-velocitystrip-hero--docs)** — the across-the-room wall treatment
|
|
25
|
+
* - **[Compact](?path=/docs/custom-workout-dataviz-velocitystrip-compact--docs)** — the flat resting strip
|
|
26
|
+
* - **[Expanded](?path=/docs/custom-workout-dataviz-velocitystrip-expanded--docs)** — the value-height chart
|
|
27
|
+
* - **[Hero](?path=/docs/custom-workout-dataviz-velocitystrip-hero--docs)** — the across-the-room wall treatment
|
|
27
28
|
*
|
|
28
29
|
* Dual is NOT a fourth view. It is the same strip when the exercise used two
|
|
29
30
|
* Voltras, so every group pairs single above dual on one dataset.
|
|
@@ -39,8 +40,13 @@ import {
|
|
|
39
40
|
* live in the three group files above.
|
|
40
41
|
*/
|
|
41
42
|
const meta: Meta<typeof VelocityStrip> = {
|
|
42
|
-
title: 'Workout/DataViz/VelocityStrip',
|
|
43
|
+
title: 'Custom/Workout/DataViz/VelocityStrip',
|
|
43
44
|
component: VelocityStrip,
|
|
45
|
+
parameters: {
|
|
46
|
+
docs: {
|
|
47
|
+
description: { component: 'Composes **SetBarChart** · **ChartSideRail** · **SessionRail**.' },
|
|
48
|
+
},
|
|
49
|
+
},
|
|
44
50
|
tags: ['autodocs'],
|
|
45
51
|
argTypes: {
|
|
46
52
|
variant: {
|
|
@@ -98,9 +104,9 @@ export const Playground: Story = {
|
|
|
98
104
|
},
|
|
99
105
|
decorators: [
|
|
100
106
|
(Story) => (
|
|
101
|
-
<
|
|
107
|
+
<Surface level="base" style={{ width: 300, padding: 16 }}>
|
|
102
108
|
<Story />
|
|
103
|
-
</
|
|
109
|
+
</Surface>
|
|
104
110
|
),
|
|
105
111
|
],
|
|
106
112
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
calculateMeanVelocity,
|
|
10
10
|
getVelocityLossColor,
|
|
11
11
|
} from './VelocityStrip'
|
|
12
|
+
import { FIXED_MAX_VALUE } from '../charts/SetBarChart'
|
|
12
13
|
|
|
13
14
|
const sampleVelocities = [1.1, 0.95, 0.82, 0.68, 0.45]
|
|
14
15
|
|
|
@@ -583,28 +584,69 @@ describe('VelocityStrip expanded bare strip (spotlight: numbers + info off)', ()
|
|
|
583
584
|
})
|
|
584
585
|
|
|
585
586
|
it('scales bar height to velocity against the fixed ceiling at the given height', () => {
|
|
587
|
+
const barPx = (id: string) => parseFloat(getComputedStyle(screen.getByTestId(id)).height)
|
|
586
588
|
render(
|
|
587
589
|
<VelocityStrip
|
|
588
590
|
{...bareProps}
|
|
589
591
|
scale="fixed"
|
|
590
592
|
height={24}
|
|
591
|
-
set={{ type: 'straight', velocities: [
|
|
593
|
+
set={{ type: 'straight', velocities: [0.6, 0.3], planned: 2 }}
|
|
592
594
|
/>
|
|
593
595
|
)
|
|
594
|
-
|
|
595
|
-
|
|
596
|
+
// Proportional to velocity against the fixed ceiling, not the performed max — a 2:1 velocity
|
|
597
|
+
// ratio reads as a 2:1 bar-height ratio.
|
|
598
|
+
expect(barPx('velocity-bar-0')).toBeCloseTo(2 * barPx('velocity-bar-1'), 5)
|
|
596
599
|
})
|
|
597
600
|
|
|
598
601
|
it('honors height for the scaling', () => {
|
|
599
|
-
|
|
602
|
+
const barPx = (id: string) => parseFloat(getComputedStyle(screen.getByTestId(id)).height)
|
|
603
|
+
const { unmount } = render(
|
|
600
604
|
<VelocityStrip
|
|
601
605
|
{...bareProps}
|
|
602
606
|
scale="fixed"
|
|
603
607
|
height={40}
|
|
604
|
-
set={{ type: 'straight', velocities: [
|
|
608
|
+
set={{ type: 'straight', velocities: [0.6], planned: 1 }}
|
|
609
|
+
/>
|
|
610
|
+
)
|
|
611
|
+
const at40 = barPx('velocity-bar-0')
|
|
612
|
+
unmount()
|
|
613
|
+
render(
|
|
614
|
+
<VelocityStrip
|
|
615
|
+
{...bareProps}
|
|
616
|
+
scale="fixed"
|
|
617
|
+
height={80}
|
|
618
|
+
set={{ type: 'straight', velocities: [0.6], planned: 1 }}
|
|
619
|
+
/>
|
|
620
|
+
)
|
|
621
|
+
expect(barPx('velocity-bar-0')).toBeCloseTo(2 * at40, 5)
|
|
622
|
+
})
|
|
623
|
+
|
|
624
|
+
it('reserves the same headroom above the fixed ceiling that `peak` reserves above its own max (VW-97)', () => {
|
|
625
|
+
// A rep AT the fixed ceiling must NOT fill the plot — it needs the identical margin an
|
|
626
|
+
// equally-tall `peak` bar always keeps for its own value label.
|
|
627
|
+
const { unmount } = render(
|
|
628
|
+
<VelocityStrip
|
|
629
|
+
{...bareProps}
|
|
630
|
+
scale="fixed"
|
|
631
|
+
height={100}
|
|
632
|
+
set={{ type: 'straight', velocities: [FIXED_MAX_VALUE], planned: 1 }}
|
|
633
|
+
/>
|
|
634
|
+
)
|
|
635
|
+
const fixedAtCeilingPx = parseFloat(
|
|
636
|
+
getComputedStyle(screen.getByTestId('velocity-bar-0')).height
|
|
637
|
+
)
|
|
638
|
+
unmount()
|
|
639
|
+
render(
|
|
640
|
+
<VelocityStrip
|
|
641
|
+
{...bareProps}
|
|
642
|
+
scale="peak"
|
|
643
|
+
height={100}
|
|
644
|
+
set={{ type: 'straight', velocities: [1], planned: 1 }}
|
|
605
645
|
/>
|
|
606
646
|
)
|
|
607
|
-
|
|
647
|
+
const peakAtMaxPx = parseFloat(getComputedStyle(screen.getByTestId('velocity-bar-0')).height)
|
|
648
|
+
expect(fixedAtCeilingPx).toBeLessThan(100)
|
|
649
|
+
expect(fixedAtCeilingPx).toBeCloseTo(peakAtMaxPx, 5)
|
|
608
650
|
})
|
|
609
651
|
|
|
610
652
|
it('draws planned-but-undone reps as short grey todo stubs (set-type aware)', () => {
|
|
@@ -702,9 +702,14 @@ export interface DualVelocityStripProps extends ViewProps {
|
|
|
702
702
|
* `hero` — the across-the-room wall scale: tall wings, per-rep m/s value labels, and a dashed
|
|
703
703
|
* running-best reference line per side. `compact` — the flat resting form: dual-hero but flat +
|
|
704
704
|
* no labels (both wings are the `compact` VelocityStrip variant), same aligned structure + shared
|
|
705
|
-
* gutter + axis. `
|
|
705
|
+
* gutter + axis. `dual-expanded` — the compact rail-expanded lean renderer, no labels / reference
|
|
706
|
+
* lines (VW-97: `rail` was a verified misnomer — this variant is the value-height strip a session
|
|
707
|
+
* rail row expands into, not the rail itself).
|
|
708
|
+
*
|
|
709
|
+
* `rail` is a **deprecated alias** for `dual-expanded` (same renderer, same output) — kept for one
|
|
710
|
+
* release so existing call sites keep working; see the Workout README.
|
|
706
711
|
*/
|
|
707
|
-
variant?: 'hero' | 'compact' | 'rail'
|
|
712
|
+
variant?: 'hero' | 'compact' | 'dual-expanded' | 'rail'
|
|
708
713
|
/**
|
|
709
714
|
* Bar-height scaling, shared across BOTH wings so the L/R asymmetry reads as bar
|
|
710
715
|
* length against one scale. `peak` (default) = the pair's max +headroom; `fixed` =
|
|
@@ -926,12 +931,12 @@ function DualVelocityHero({
|
|
|
926
931
|
}
|
|
927
932
|
|
|
928
933
|
/**
|
|
929
|
-
* The `
|
|
930
|
-
* drag in its value labels, reference lines, paper, and label
|
|
931
|
-
*
|
|
932
|
-
* height scale + per-side loss coloring + mirrored radius + shared
|
|
933
|
-
* / reference lines / paper. (Set-type slot windows are a
|
|
934
|
-
* takes plain velocities.)
|
|
934
|
+
* The `dual-expanded` diverging chart (formerly `rail`) — a lean, compact dedicated renderer.
|
|
935
|
+
* Composing the hero here would drag in its value labels, reference lines, paper, and label
|
|
936
|
+
* headroom, none of which belong at this scale; instead it draws mirrored per-side bars at the
|
|
937
|
+
* compact metrics. Same shared height scale + per-side loss coloring + mirrored radius + shared
|
|
938
|
+
* axis as the hero, but no labels / reference lines / paper. (Set-type slot windows are a
|
|
939
|
+
* hero-composition concern; this renderer only ever takes plain velocities.)
|
|
935
940
|
*/
|
|
936
941
|
function DualVelocityRail({
|
|
937
942
|
leftDone,
|
|
@@ -1090,11 +1095,14 @@ export function DualVelocityStrip({
|
|
|
1090
1095
|
className,
|
|
1091
1096
|
...props
|
|
1092
1097
|
}: DualVelocityStripProps) {
|
|
1098
|
+
// `rail` is the deprecated alias for `dual-expanded` — normalize once so every branch below
|
|
1099
|
+
// reads one canonical value instead of re-checking both spellings.
|
|
1100
|
+
const resolvedVariant = variant === 'rail' ? 'dual-expanded' : variant
|
|
1093
1101
|
const resolvedHeight =
|
|
1094
1102
|
height ??
|
|
1095
|
-
(
|
|
1103
|
+
(resolvedVariant === 'hero'
|
|
1096
1104
|
? DUAL_HERO_HEIGHT
|
|
1097
|
-
:
|
|
1105
|
+
: resolvedVariant === 'compact'
|
|
1098
1106
|
? DUAL_COMPACT_HEIGHT
|
|
1099
1107
|
: DUAL_RAIL_HEIGHT)
|
|
1100
1108
|
// The done arrays drive the shared max + per-side best + the summary counts; the raw streams
|
|
@@ -1123,10 +1131,11 @@ export function DualVelocityStrip({
|
|
|
1123
1131
|
viewProps: props,
|
|
1124
1132
|
}
|
|
1125
1133
|
|
|
1126
|
-
// `liveRepIndex` reaches
|
|
1127
|
-
// from the midline on BOTH sides. Compact is flat, so a grow animation has nothing to animate.
|
|
1128
|
-
if (
|
|
1129
|
-
|
|
1134
|
+
// `liveRepIndex` reaches dual-expanded too: its wings are composed strips, so the newest rep
|
|
1135
|
+
// grows from the midline on BOTH sides. Compact is flat, so a grow animation has nothing to animate.
|
|
1136
|
+
if (resolvedVariant === 'dual-expanded')
|
|
1137
|
+
return <DualVelocityRail {...shared} liveRepIndex={liveRepIndex} />
|
|
1138
|
+
if (resolvedVariant === 'compact') return <DualVelocityCompactStrip {...shared} />
|
|
1130
1139
|
return <DualVelocityHero {...shared} liveRepIndex={liveRepIndex} />
|
|
1131
1140
|
}
|
|
1132
1141
|
|
|
@@ -1252,6 +1261,9 @@ export function VelocityStrip({
|
|
|
1252
1261
|
label={label}
|
|
1253
1262
|
showValueLabels
|
|
1254
1263
|
formatValue={formatVelocity}
|
|
1264
|
+
// Only the diverging dual's composed wings opt in (TD-07.10) — the standalone single
|
|
1265
|
+
// hero is unchanged, per columnSlots being the dual-only signal (see the comment above).
|
|
1266
|
+
flipEdgeLabel={columnSlots != null}
|
|
1255
1267
|
renderReference={(g) => velocityReferenceOverlay(g, lossBandsOn)}
|
|
1256
1268
|
hideBaseline
|
|
1257
1269
|
testID="velocity-strip-hero"
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import { View } from 'react-native'
|
|
3
3
|
import { VolumeLandmarkBar } from './VolumeLandmarkBar'
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
const t = getSemanticColors('dark')
|
|
4
|
+
import { Surface } from '../../ui/surface'
|
|
7
5
|
|
|
8
6
|
const meta: Meta<typeof VolumeLandmarkBar> = {
|
|
9
|
-
title: 'Workout/DataViz/VolumeLandmarkBar',
|
|
7
|
+
title: 'Custom/Workout/DataViz/VolumeLandmarkBar',
|
|
10
8
|
component: VolumeLandmarkBar,
|
|
11
9
|
tags: ['autodocs'],
|
|
12
10
|
parameters: {
|
|
@@ -15,7 +13,8 @@ const meta: Meta<typeof VolumeLandmarkBar> = {
|
|
|
15
13
|
component:
|
|
16
14
|
'Horizontal weekly-volume bar with MEV / MAV / MRV landmark ticks, a HEAT-scale ' +
|
|
17
15
|
'fill positioned against the MAV target, and a % readout. Reuses the canonical ' +
|
|
18
|
-
'BodyMap volume heat scale (under → maintenance → productive → approaching → over).'
|
|
16
|
+
'BodyMap volume heat scale (under → maintenance → productive → approaching → over).' +
|
|
17
|
+
' Composes **ZoneTrack** · **DataRow**.',
|
|
19
18
|
},
|
|
20
19
|
},
|
|
21
20
|
},
|
|
@@ -31,9 +30,9 @@ const meta: Meta<typeof VolumeLandmarkBar> = {
|
|
|
31
30
|
},
|
|
32
31
|
decorators: [
|
|
33
32
|
(Story) => (
|
|
34
|
-
<
|
|
33
|
+
<Surface level="background" style={{ padding: 24, paddingBottom: 40 }}>
|
|
35
34
|
<Story />
|
|
36
|
-
</
|
|
35
|
+
</Surface>
|
|
37
36
|
),
|
|
38
37
|
],
|
|
39
38
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, type ViewProps } from 'react-native'
|
|
3
3
|
import { WORKOUT_TOKENS } from '../../../theme/workout-tokens'
|
|
4
4
|
import { greyRamp } from '../../../theme/tokens/primitives'
|
|
5
5
|
import { ZoneTrack } from './ZoneTrack'
|
|
6
6
|
import { DataRow } from '../../ui/data-row/DataRow'
|
|
7
|
+
import { Typography } from '../Typography'
|
|
7
8
|
import type { VolumeLandmarks } from './muscleTaxonomy'
|
|
8
9
|
|
|
9
10
|
// Reuse the canonical BodyMap volume HEAT scale (the `divergingScale` under →
|
|
@@ -12,9 +13,11 @@ import type { VolumeLandmarks } from './muscleTaxonomy'
|
|
|
12
13
|
const HEAT = WORKOUT_TOKENS.heatmap
|
|
13
14
|
|
|
14
15
|
// The muted, un-reached track colour — the same grey step ZoneTrack defaults
|
|
15
|
-
// to, so the bar sits on the shared gauge-track surface.
|
|
16
|
+
// to, so the bar sits on the shared gauge-track surface. Kept as a ramp step
|
|
17
|
+
// rather than `resolveColor('border-prominent')`: ZoneTrack takes literal hex
|
|
18
|
+
// only, never a `var()` ref. FINDING for E3: the gauge-track grey has no
|
|
19
|
+
// semantic token, and ZoneTrack (B5) cannot consume one until it can.
|
|
16
20
|
const NEUTRAL_TRACK = greyRamp[800]
|
|
17
|
-
const MONO = 'monospace'
|
|
18
21
|
|
|
19
22
|
export type VolumeZone = 'under' | 'maintenance' | 'productive' | 'approaching' | 'over'
|
|
20
23
|
|
|
@@ -113,12 +116,18 @@ export function VolumeLandmarkBar({
|
|
|
113
116
|
<DataRow
|
|
114
117
|
label={muscle}
|
|
115
118
|
value={
|
|
116
|
-
|
|
119
|
+
// `mono` at `sm` matches DataRow's own 14px label, so the header lockup
|
|
120
|
+
// stays at one type height. The face moves from bare `monospace` to the
|
|
121
|
+
// `font-mono` token stack.
|
|
122
|
+
<Typography
|
|
123
|
+
variant="mono"
|
|
124
|
+
color="inherit"
|
|
125
|
+
className="text-sm font-bold"
|
|
126
|
+
style={{ color: fillColor }}
|
|
117
127
|
testID="volume-landmark-pct"
|
|
118
|
-
style={{ fontSize: 14, fontWeight: '700', fontFamily: MONO, color: fillColor }}
|
|
119
128
|
>
|
|
120
129
|
{pct}%
|
|
121
|
-
</
|
|
130
|
+
</Typography>
|
|
122
131
|
}
|
|
123
132
|
className="py-0"
|
|
124
133
|
testID="volume-landmark-header"
|
|
@@ -3,8 +3,11 @@ import { View } from 'react-native'
|
|
|
3
3
|
import { WeekRow } from './WeekRow'
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof WeekRow> = {
|
|
6
|
-
title: 'Workout/WeekRow',
|
|
6
|
+
title: 'Custom/Workout/WeekRow',
|
|
7
7
|
component: WeekRow,
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: { description: { component: 'Composes **WorkoutPill** · **IntensityBar**.' } },
|
|
10
|
+
},
|
|
8
11
|
tags: ['autodocs'],
|
|
9
12
|
argTypes: {
|
|
10
13
|
weekNumber: { control: 'number', description: 'Week index (1-based)' },
|
|
@@ -3,6 +3,9 @@ import { render, screen, fireEvent } from '@testing-library/react'
|
|
|
3
3
|
import { axe } from 'jest-axe'
|
|
4
4
|
import { WeekRow } from './WeekRow'
|
|
5
5
|
import type { WeekRowWorkout } from './WeekRow'
|
|
6
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
7
|
+
import { WORKOUT_PILL_DELOAD } from '../../../theme/extracted-colors-dataviz'
|
|
8
|
+
import { alpha } from '../../../utils/colors'
|
|
6
9
|
|
|
7
10
|
const workouts: WeekRowWorkout[] = [
|
|
8
11
|
{ name: 'Upper', status: 'completed' },
|
|
@@ -57,11 +60,11 @@ describe('WeekRow', () => {
|
|
|
57
60
|
expect(screen.queryByTestId('week-row-current-dot')).not.toBeInTheDocument()
|
|
58
61
|
})
|
|
59
62
|
|
|
60
|
-
it('applies the current-week tint and left border', () => {
|
|
63
|
+
it('applies the current-week tint and left border from the brand tokens', () => {
|
|
61
64
|
render(<WeekRow {...baseProps} isCurrent />)
|
|
62
65
|
const style = screen.getByTestId('week-row').getAttribute('style') ?? ''
|
|
63
|
-
expect(style).toContain(
|
|
64
|
-
expect(style).toContain(
|
|
66
|
+
expect(style).toContain(`background-color: ${resolveColor('brand-primary-subtle')}`)
|
|
67
|
+
expect(style).toContain(`border-left-color: ${resolveColor('brand-primary')}`)
|
|
65
68
|
})
|
|
66
69
|
})
|
|
67
70
|
|
|
@@ -71,22 +74,24 @@ describe('WeekRow', () => {
|
|
|
71
74
|
expect(screen.getAllByLabelText(/workout, deload/)).toHaveLength(3)
|
|
72
75
|
})
|
|
73
76
|
|
|
74
|
-
it('
|
|
77
|
+
it('washes the row with the same deload pin WorkoutPill uses', () => {
|
|
75
78
|
render(<WeekRow {...baseProps} isDeload />)
|
|
76
79
|
const style = screen.getByTestId('week-row').getAttribute('style') ?? ''
|
|
77
|
-
expect(style).toContain(
|
|
80
|
+
expect(style).toContain(`background-color: ${alpha(WORKOUT_PILL_DELOAD, 0.06)}`)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('lets a current deload week keep the brand rail over the deload wash', () => {
|
|
84
|
+
render(<WeekRow {...baseProps} isDeload isCurrent />)
|
|
85
|
+
const style = screen.getByTestId('week-row').getAttribute('style') ?? ''
|
|
86
|
+
expect(style).toContain(`background-color: ${resolveColor('brand-primary-subtle')}`)
|
|
87
|
+
expect(style).toContain(`border-left-color: ${resolveColor('brand-primary')}`)
|
|
78
88
|
})
|
|
79
89
|
})
|
|
80
90
|
|
|
81
91
|
describe('interaction', () => {
|
|
82
92
|
it('invokes onPress for a pressable workout', () => {
|
|
83
93
|
const onPress = vi.fn()
|
|
84
|
-
render(
|
|
85
|
-
<WeekRow
|
|
86
|
-
{...baseProps}
|
|
87
|
-
workouts={[{ name: 'Upper', status: 'current', onPress }]}
|
|
88
|
-
/>,
|
|
89
|
-
)
|
|
94
|
+
render(<WeekRow {...baseProps} workouts={[{ name: 'Upper', status: 'current', onPress }]} />)
|
|
90
95
|
fireEvent.click(screen.getByTestId('workout-pill-pressable'))
|
|
91
96
|
expect(onPress).toHaveBeenCalledOnce()
|
|
92
97
|
})
|
|
@@ -95,9 +100,7 @@ describe('WeekRow', () => {
|
|
|
95
100
|
describe('accessibility', () => {
|
|
96
101
|
it('has a descriptive accessibility label', () => {
|
|
97
102
|
render(<WeekRow {...baseProps} />)
|
|
98
|
-
expect(
|
|
99
|
-
screen.getByLabelText('Week 1 of 4, 3 workouts'),
|
|
100
|
-
).toBeInTheDocument()
|
|
103
|
+
expect(screen.getByLabelText('Week 1 of 4, 3 workouts')).toBeInTheDocument()
|
|
101
104
|
})
|
|
102
105
|
|
|
103
106
|
it('has no accessibility violations', async () => {
|
|
@@ -108,7 +111,7 @@ describe('WeekRow', () => {
|
|
|
108
111
|
|
|
109
112
|
it('has no accessibility violations as a current deload week', async () => {
|
|
110
113
|
const { container } = render(
|
|
111
|
-
<WeekRow {...baseProps} isCurrent isDeload intensityThreshold={0.8}
|
|
114
|
+
<WeekRow {...baseProps} isCurrent isDeload intensityThreshold={0.8} />
|
|
112
115
|
)
|
|
113
116
|
const results = await axe(container)
|
|
114
117
|
expect(results).toHaveNoViolations()
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, type ViewProps } from 'react-native'
|
|
3
3
|
import { WorkoutPill, type WorkoutPillStatus } from './WorkoutPill'
|
|
4
4
|
import { IntensityBar } from './IntensityBar'
|
|
5
|
-
import {
|
|
5
|
+
import { Typography } from '../Typography'
|
|
6
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
7
|
+
import { WORKOUT_PILL_DELOAD } from '../../../theme/extracted-colors-dataviz'
|
|
8
|
+
import { alpha } from '../../../utils/colors'
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
// Deload magenta has no semantic token — it is a ramp pin shared with WorkoutPill
|
|
11
|
+
// (`extracted-colors-dataviz`). The row wash must track the pill exactly, so it
|
|
12
|
+
// is derived from the same pin rather than mixed independently. FINDING for E3:
|
|
13
|
+
// the deload role needs a `-subtle` token like every other status.
|
|
14
|
+
const DELOAD_ROW_WASH = alpha(WORKOUT_PILL_DELOAD, 0.06)
|
|
8
15
|
|
|
9
16
|
export interface WeekRowWorkout {
|
|
10
17
|
name: string
|
|
@@ -58,6 +65,7 @@ export function WeekRow({
|
|
|
58
65
|
className,
|
|
59
66
|
...props
|
|
60
67
|
}: WeekRowProps) {
|
|
68
|
+
const brandPrimary = resolveColor('brand-primary')
|
|
61
69
|
const rowStyle: Record<string, unknown> = {
|
|
62
70
|
flexDirection: 'row' as const,
|
|
63
71
|
alignItems: 'center' as const,
|
|
@@ -67,13 +75,14 @@ export function WeekRow({
|
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
if (isDeload) {
|
|
70
|
-
rowStyle.backgroundColor =
|
|
78
|
+
rowStyle.backgroundColor = DELOAD_ROW_WASH
|
|
71
79
|
}
|
|
72
80
|
|
|
81
|
+
// Current wins over deload: the active week keeps the brand rail and wash.
|
|
73
82
|
if (isCurrent) {
|
|
74
|
-
rowStyle.backgroundColor = '
|
|
83
|
+
rowStyle.backgroundColor = resolveColor('brand-primary-subtle')
|
|
75
84
|
rowStyle.borderLeftWidth = 2
|
|
76
|
-
rowStyle.borderLeftColor =
|
|
85
|
+
rowStyle.borderLeftColor = brandPrimary
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
return (
|
|
@@ -94,24 +103,22 @@ export function WeekRow({
|
|
|
94
103
|
width: 6,
|
|
95
104
|
height: 6,
|
|
96
105
|
borderRadius: 3,
|
|
97
|
-
backgroundColor:
|
|
106
|
+
backgroundColor: brandPrimary,
|
|
98
107
|
}}
|
|
99
108
|
accessibilityElementsHidden
|
|
100
109
|
testID="week-row-current-dot"
|
|
101
110
|
/>
|
|
102
111
|
)}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
color: isCurrent ? BRAND_PRIMARY : undefined,
|
|
110
|
-
}}
|
|
112
|
+
{/* `boldLabel` is 12px/700 Inter — the row-label form. The week number was
|
|
113
|
+
13px, which is off the type scale (TOKENS.md §4). */}
|
|
114
|
+
<Typography
|
|
115
|
+
variant="boldLabel"
|
|
116
|
+
color={isCurrent ? 'inherit' : 'primary'}
|
|
117
|
+
className={isCurrent ? 'text-brand-primary' : undefined}
|
|
111
118
|
accessibilityElementsHidden
|
|
112
119
|
>
|
|
113
120
|
{`W${weekNumber}`}
|
|
114
|
-
</
|
|
121
|
+
</Typography>
|
|
115
122
|
</View>
|
|
116
123
|
|
|
117
124
|
<View
|
|
@@ -3,8 +3,9 @@ import { View } from 'react-native'
|
|
|
3
3
|
import { WeightBadge } from './WeightBadge'
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof WeightBadge> = {
|
|
6
|
-
title: '
|
|
6
|
+
title: 'Custom/Workout/WeightBadge',
|
|
7
7
|
component: WeightBadge,
|
|
8
|
+
parameters: { docs: { description: { component: 'Composes **Icons** · **BaseBadge**.' } } },
|
|
8
9
|
tags: ['autodocs'],
|
|
9
10
|
argTypes: {
|
|
10
11
|
value: { control: 'number', description: 'Weight value' },
|