@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
|
@@ -86,11 +86,50 @@ type props without pulling the dependency.
|
|
|
86
86
|
└─ SetStrip
|
|
87
87
|
└─ SetBar × N (one set's per-rep colour bar)
|
|
88
88
|
|
|
89
|
-
ExerciseCard
|
|
89
|
+
ExerciseCard (all three representations) ──delegates to──▶ ExerciseCardHeading
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
`ExerciseCardHeading`
|
|
92
|
+
**TD-03.55 / TD-03.56 — one row, three densities, and interaction states.**
|
|
93
|
+
`ExerciseCardHeading` IS the exercise row. Its `density` prop carries the only
|
|
94
|
+
axis that ever separated the three call sites:
|
|
95
|
+
|
|
96
|
+
| `density` | shape | was |
|
|
97
|
+
| ---------- | ------------------------------------------------------- | ---------------------------- |
|
|
98
|
+
| `rail` | two lines: name, then prescription beside the tempo | `ExerciseCardHeading` |
|
|
99
|
+
| `compact` | one line: name + prescription, strip below | `ExerciseCard`'s CollapsedCard |
|
|
100
|
+
| `upcoming` | `compact`, dimmed, previous best pinned right | `ExerciseCard`'s UpcomingCard |
|
|
101
|
+
|
|
102
|
+
`CollapsedCard` and `UpcomingCard` are deleted; `ExerciseCard` maps its props onto
|
|
103
|
+
the row, so **its own prop shape is unchanged** and no consumer migrates. Three
|
|
104
|
+
things converged in the process, each a consistency gain rather than a new idea:
|
|
105
|
+
the collapsed row's freeform `3×6 @ 175 lbs` caption became the shared
|
|
106
|
+
`SetsRepsLoad` line; its hand-rolled `VelocityStrip` + `PlaceholderStrip` row
|
|
107
|
+
became one `SetStrip` (so `velocityZones` no longer tints the collapsed glance —
|
|
108
|
+
the expanded header already ignored it); and `isPR` surfaces through the
|
|
109
|
+
`ExerciseIndicator` chip, which is what the expanded header already did.
|
|
110
|
+
|
|
111
|
+
The prescription is a **discriminated union**: either the structured
|
|
112
|
+
`sets`/`reps`/`load` triple, or a free-text `prescription` string for an exercise
|
|
113
|
+
whose numbers aren't loaded, or neither. Mixing them is a type error rather than a
|
|
114
|
+
half-rendered line.
|
|
115
|
+
|
|
116
|
+
Interaction states are `interactive-*` token washes on the row —
|
|
117
|
+
**press > selection > hover** — plus an `isLive` name tone (`status-live`). Every
|
|
118
|
+
one is static: this row renders on the wall during a set, where titan's "the grain
|
|
119
|
+
never animates" rule applies. Hover is web-only; RN Pressable's `onHoverIn` never
|
|
120
|
+
fires on a touch surface, so a touch consumer simply gets no hover state and
|
|
121
|
+
`isSelected` carries the same "this one" meaning. Selection has **no ARIA**:
|
|
122
|
+
`aria-selected` is not allowed on `role="button"`, so the wash is the whole signal
|
|
123
|
+
and list semantics stay the rail's job.
|
|
124
|
+
|
|
125
|
+
Two follow-ups are deliberately NOT taken here. The dim depths still differ by
|
|
126
|
+
density (rail 0.55, card 0.60) because they came from two specimens and converging
|
|
127
|
+
them needs an **opacity token the set does not have** — a foundations decision.
|
|
128
|
+
And `exerciseRowState.ts` (the `interactive-*` → literal-hex map, written in the
|
|
129
|
+
shape of `onSurfaceColors`) should be **promoted into the surface module** the
|
|
130
|
+
moment a second family needs row washes.
|
|
131
|
+
|
|
132
|
+
`SetBar`
|
|
94
133
|
owns the per-set colour/pulse logic; `SetStrip` lays several side by side.
|
|
95
134
|
Beyond the flat `done`/`active`/`todo` sets, `SetStripSet` models set-type
|
|
96
135
|
prescriptions: `range` (variable rep-range — range-max segments, committed-todo grey
|
|
@@ -102,9 +141,13 @@ type props without pulling the dependency.
|
|
|
102
141
|
(`SET_STRIP_VARIABLE_COLOR`) is the shared "variable / unknown / opportunity" pin.
|
|
103
142
|
`SegmentedBar` carries these via additive `leadingGap` (per-segment left margin) and
|
|
104
143
|
static `opacity` props — the flat sets stay byte-identical.
|
|
144
|
+
`active`/`todo` sets optionally carry the plan's prescribed rep RANGE (`repsLow`/
|
|
145
|
+
`repsHigh`, VMCP-03.04), rendered as a small label above the bar (`8–12`, or `8` when
|
|
146
|
+
equal/only one is given) via the shared `formatRepsRange` helper — independent of
|
|
147
|
+
`range`'s `floor`/`max` value range.
|
|
105
148
|
`SetStrip`/`SetBar` colors are the real titan ramp pins (`primitiveRamps` red-600 /
|
|
106
|
-
orange-400 / amber-300 / green-300); the rail surfaces bind to the
|
|
107
|
-
a
|
|
149
|
+
orange-400 / amber-300 / green-300); the rail surfaces bind to the grey ramp and the
|
|
150
|
+
list is a well cut with the shared `insetWell` material. The heading
|
|
108
151
|
design is locked in `sources/design/shell/S3-sessionrail/DECISIONS-ExerciseRow.md`; the
|
|
109
152
|
exploration specimens live under `Custom/Workout/Explorations/*` (do not repoint yet).
|
|
110
153
|
In Storybook the family nests by composition under **`Shell/SessionRail/…`**
|
|
@@ -126,7 +169,7 @@ type props without pulling the dependency.
|
|
|
126
169
|
array (unchanged, still the source of truth for `SetRow` / `ExerciseCard`), the
|
|
127
170
|
strip accepts an optional structured `VelocitySet` descriptor and renders the
|
|
128
171
|
strength set-type vocabulary as a typed slot list. Slots are
|
|
129
|
-
`rep` (velocity-coloured) · `todo` (
|
|
172
|
+
`rep` (velocity-coloured) · `todo` (`border-prominent` grey) · `variable` /
|
|
130
173
|
`continue` (`SET_STRIP_VARIABLE_COLOR` cyan-900; `continue` adds a cyan-800
|
|
131
174
|
outline to read as "keep going"). Types: `straight` (done + grey todo to
|
|
132
175
|
`planned`), `range` (committed grey + a cyan variable window `floor..max`),
|
|
@@ -178,14 +221,22 @@ Modalities`** (each card carries a `Collapse` accordion; promoted from the
|
|
|
178
221
|
when neither side carries one the gutter is omitted entirely. The label keeps the prior
|
|
179
222
|
vertical (rotated) orientation so it never overlaps the bars. Two scales: `hero` (tall
|
|
180
223
|
wings, per-rep m/s velocity labels, a dashed running-best reference line per side) and
|
|
181
|
-
`
|
|
182
|
-
|
|
183
|
-
|
|
224
|
+
`dual-expanded` (compact — no velocity labels / reference lines, slot names in a narrow
|
|
225
|
+
gutter).
|
|
226
|
+
**Rep-index alignment is the invariant:** column _i_ is rep _i_ on
|
|
227
|
+
both sides, so the set-type slot _kinds_ carry through (rep / todo / variable / continue,
|
|
184
228
|
coloured as in the single strip) but the wide-notch chunk **gaps** (drop / myo / cluster
|
|
185
229
|
boundaries) are intentionally NOT rendered — per-side horizontal gaps would break the
|
|
186
230
|
mirrored L↔R column alignment. Single-voltra sets keep using `VelocityStrip`
|
|
187
|
-
`variant="hero"`. Documented by the `Playground` / `Hero*` / `
|
|
188
|
-
background (`Workout/DataViz/DualVelocityStrip`).
|
|
231
|
+
`variant="hero"`. Documented by the `Playground` / `Hero*` / `DualExpanded` stories on the
|
|
232
|
+
wall background (`Custom/Workout/DataViz/DualVelocityStrip`).
|
|
233
|
+
|
|
234
|
+
**`variant="rail"` → `variant="dual-expanded"` (VW-97).** `rail` was a verified misnomer —
|
|
235
|
+
this variant is the value-height strip a session-rail row _expands into_, not the rail
|
|
236
|
+
itself (the rail stays 246px and never changes width; expansion lives in a separate detail
|
|
237
|
+
pane, per the VW-97 rail-width decision). `rail` is kept as a **deprecated alias** for one
|
|
238
|
+
release (same renderer, same output) so existing call sites keep working; migrate to
|
|
239
|
+
`dual-expanded` and expect `rail` to be removed in a future release.
|
|
189
240
|
|
|
190
241
|
**Reuse audit — `DashedReferenceLine` (in-file today, top-level follow-up).** The dashed
|
|
191
242
|
running-best line was hand-rolled three times inside `VelocityStrip.tsx` (the single
|
|
@@ -199,6 +250,7 @@ Modalities`** (each card carries a `Collapse` accordion; promoted from the
|
|
|
199
250
|
a follow-up so the hero PR stays focused (the cross-file migration touches `Sparkline`'s
|
|
200
251
|
test surface and the Lab specimens, which are out of this branch's scope). Proposed API:
|
|
201
252
|
`<ReferenceLine anchor offset color dashed opacity? label? testID />`.
|
|
253
|
+
|
|
202
254
|
- **RestTimer `ring` variant** — the across-the-room **wall** rest treatment (the
|
|
203
255
|
north-star rest page). Built as a **three-tier decomposition** (not a one-off):
|
|
204
256
|
`CircularProgress` (atom, gained a **`children`** center slot + a **`fill`**
|
|
@@ -215,7 +267,7 @@ Modalities`** (each card carries a `Collapse` accordion; promoted from the
|
|
|
215
267
|
hides the shared `RestActions` (+30s/Skip, extracted, used by both variants);
|
|
216
268
|
`size` (default 180) sets the diameter; the eyebrow/section title is organism
|
|
217
269
|
chrome. Web/RNW-only (like `CircularProgress`) — the wall variant; mobile keeps
|
|
218
|
-
`bar`. `Ring*` (RestTimer) + `
|
|
270
|
+
`bar`. `Ring*` (RestTimer) + `Components/Molecules/CircularTimer` stories on the wall background.
|
|
219
271
|
- **`size="wall"` density (FatigueMeter · ZoneTrack)** — the across-the-room
|
|
220
272
|
dashboard scale, added as the idiomatic titan `size` union (a JS number-map per
|
|
221
273
|
component; **`default` values are byte-identical** to before, so existing consumers are
|
|
@@ -298,8 +350,7 @@ responsive level views land (removal is out of scope for this scaffold ticket):
|
|
|
298
350
|
(Workout Expansion), `S3SetTypes` (Set Types), `S3SessionPace` (Session Pace).
|
|
299
351
|
Each is superseded by a real Shell/SessionRail component + its Storybook stories;
|
|
300
352
|
`S3SessionPace` in particular is superseded by the `SessionHeader` pace glance.
|
|
301
|
-
- **`ExerciseCard`'s `collapsed` / `upcoming` state representations** —
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
`ExerciseCard` are the superseded representations to retire.
|
|
353
|
+
- **`ExerciseCard`'s `collapsed` / `upcoming` state representations** — DONE
|
|
354
|
+
(TD-03.56). Both hand-rolled sub-cards are deleted; `ExerciseCard` now delegates
|
|
355
|
+
all three representations to `ExerciseCardHeading` and its `density` prop. What
|
|
356
|
+
remains to retire is the expanded view, which is moving to `ExpandedDrawer`.
|
|
@@ -16,8 +16,9 @@ const staticFactors: ReadinessFactor[] = FACTOR_SEED.map((f) => ({
|
|
|
16
16
|
}))
|
|
17
17
|
|
|
18
18
|
const meta: Meta<typeof ReadinessCheck> = {
|
|
19
|
-
title: 'Workout/ReadinessCheck',
|
|
19
|
+
title: 'Custom/Workout/ReadinessCheck',
|
|
20
20
|
component: ReadinessCheck,
|
|
21
|
+
parameters: { docs: { description: { component: 'Composes **Card** · **Badge**.' } } },
|
|
21
22
|
tags: ['autodocs'],
|
|
22
23
|
argTypes: {
|
|
23
24
|
score: {
|
|
@@ -89,7 +90,7 @@ export const WithWarmUpCaution: Story = {
|
|
|
89
90
|
|
|
90
91
|
function InteractiveReadinessCheck() {
|
|
91
92
|
const [values, setValues] = useState<Record<string, number>>(
|
|
92
|
-
Object.fromEntries(FACTOR_SEED.map((f) => [f.id, f.value]))
|
|
93
|
+
Object.fromEntries(FACTOR_SEED.map((f) => [f.id, f.value]))
|
|
93
94
|
)
|
|
94
95
|
|
|
95
96
|
const factors: ReadinessFactor[] = FACTOR_SEED.map((f) => ({
|
|
@@ -22,9 +22,7 @@ describe('ReadinessCheck', () => {
|
|
|
22
22
|
describe('rendering', () => {
|
|
23
23
|
it('renders the title and one row per factor', () => {
|
|
24
24
|
render(<ReadinessCheck {...baseProps} factors={makeFactors()} />)
|
|
25
|
-
expect(screen.getByTestId('readiness-check-title')).toHaveTextContent(
|
|
26
|
-
'How are you feeling?',
|
|
27
|
-
)
|
|
25
|
+
expect(screen.getByTestId('readiness-check-title')).toHaveTextContent('How are you feeling?')
|
|
28
26
|
expect(screen.getByTestId('readiness-check-factor-sleep')).toBeInTheDocument()
|
|
29
27
|
expect(screen.getByTestId('readiness-check-factor-stress')).toBeInTheDocument()
|
|
30
28
|
})
|
|
@@ -78,7 +76,7 @@ describe('ReadinessCheck', () => {
|
|
|
78
76
|
{...baseProps}
|
|
79
77
|
factors={makeFactors()}
|
|
80
78
|
warmUpValidation={{ velocityDeficit: 5, recommendation: 'OK', status: 'good' }}
|
|
81
|
-
|
|
79
|
+
/>
|
|
82
80
|
)
|
|
83
81
|
expect(screen.queryByTestId('readiness-check-warmup')).not.toBeInTheDocument()
|
|
84
82
|
})
|
|
@@ -94,13 +92,13 @@ describe('ReadinessCheck', () => {
|
|
|
94
92
|
recommendation: 'Reduce load today.',
|
|
95
93
|
status: 'caution',
|
|
96
94
|
}}
|
|
97
|
-
|
|
95
|
+
/>
|
|
98
96
|
)
|
|
99
97
|
expect(screen.getByTestId('readiness-check-warmup-deficit')).toHaveTextContent(
|
|
100
|
-
'18% below 14-day average'
|
|
98
|
+
'18% below 14-day average'
|
|
101
99
|
)
|
|
102
100
|
expect(screen.getByTestId('readiness-check-warmup-recommendation')).toHaveTextContent(
|
|
103
|
-
'Reduce load today.'
|
|
101
|
+
'Reduce load today.'
|
|
104
102
|
)
|
|
105
103
|
expect(screen.getByTestId('readiness-check-warmup-badge')).toHaveTextContent('Caution')
|
|
106
104
|
})
|
|
@@ -112,10 +110,10 @@ describe('ReadinessCheck', () => {
|
|
|
112
110
|
factors={makeFactors()}
|
|
113
111
|
warmUpCompleted
|
|
114
112
|
warmUpValidation={{ velocityDeficit: 0, recommendation: 'Proceed.', status: 'good' }}
|
|
115
|
-
|
|
113
|
+
/>
|
|
116
114
|
)
|
|
117
115
|
expect(screen.getByTestId('readiness-check-warmup-deficit')).toHaveTextContent(
|
|
118
|
-
'Velocity on 14-day average'
|
|
116
|
+
'Velocity on 14-day average'
|
|
119
117
|
)
|
|
120
118
|
})
|
|
121
119
|
|
|
@@ -126,10 +124,10 @@ describe('ReadinessCheck', () => {
|
|
|
126
124
|
factors={makeFactors()}
|
|
127
125
|
warmUpCompleted
|
|
128
126
|
warmUpValidation={{ velocityDeficit: -6, recommendation: 'Proceed.', status: 'good' }}
|
|
129
|
-
|
|
127
|
+
/>
|
|
130
128
|
)
|
|
131
129
|
expect(screen.getByTestId('readiness-check-warmup-deficit')).toHaveTextContent(
|
|
132
|
-
'Velocity 6% above 14-day average'
|
|
130
|
+
'Velocity 6% above 14-day average'
|
|
133
131
|
)
|
|
134
132
|
})
|
|
135
133
|
})
|
|
@@ -149,15 +147,11 @@ describe('ReadinessCheck', () => {
|
|
|
149
147
|
|
|
150
148
|
it('exposes the readiness score on the gauge', () => {
|
|
151
149
|
render(<ReadinessCheck {...baseProps} factors={makeFactors()} score={78} />)
|
|
152
|
-
expect(
|
|
153
|
-
screen.getByLabelText('Readiness score: 78 out of 100'),
|
|
154
|
-
).toBeInTheDocument()
|
|
150
|
+
expect(screen.getByLabelText('Readiness score: 78 out of 100')).toBeInTheDocument()
|
|
155
151
|
})
|
|
156
152
|
|
|
157
153
|
it('has no accessibility violations', async () => {
|
|
158
|
-
const { container } = render(
|
|
159
|
-
<ReadinessCheck {...baseProps} factors={makeFactors()} />,
|
|
160
|
-
)
|
|
154
|
+
const { container } = render(<ReadinessCheck {...baseProps} factors={makeFactors()} />)
|
|
161
155
|
expect(await axe(container)).toHaveNoViolations()
|
|
162
156
|
})
|
|
163
157
|
|
|
@@ -173,7 +167,7 @@ describe('ReadinessCheck', () => {
|
|
|
173
167
|
status: 'moderate',
|
|
174
168
|
}}
|
|
175
169
|
onConfirm={vi.fn()}
|
|
176
|
-
|
|
170
|
+
/>
|
|
177
171
|
)
|
|
178
172
|
expect(await axe(container)).toHaveNoViolations()
|
|
179
173
|
})
|
|
@@ -3,11 +3,13 @@ import { View, Text, Pressable } from 'react-native'
|
|
|
3
3
|
import { Card } from '../../ui/card'
|
|
4
4
|
import { Badge, type BadgeColor } from '../../ui/badge'
|
|
5
5
|
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
6
|
+
import { alpha } from '../../../utils/colors'
|
|
6
7
|
|
|
7
8
|
const t = getSemanticColors('dark')
|
|
8
9
|
|
|
9
10
|
const BRAND_PRIMARY = t['brand-primary']
|
|
10
|
-
const
|
|
11
|
+
const ON_BRAND_PRIMARY = t['on-brand-primary']
|
|
12
|
+
const BRAND_PRIMARY_SUBTLE = alpha(BRAND_PRIMARY, 0.12)
|
|
11
13
|
const STATUS_SUCCESS = t['status-success']
|
|
12
14
|
const STATUS_WARNING = t['status-warning']
|
|
13
15
|
const STATUS_ERROR = t['status-error']
|
|
@@ -71,7 +73,11 @@ const WARMUP_BADGE: Record<WarmUpStatus, { color: BadgeColor; label: string }> =
|
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
function emojiSet(factor: ReadinessFactor): readonly string[] {
|
|
74
|
-
return
|
|
76
|
+
return (
|
|
77
|
+
EMOJI_SETS[factor.id.toLowerCase()] ??
|
|
78
|
+
EMOJI_SETS[factor.label.toLowerCase()] ??
|
|
79
|
+
DEFAULT_EMOJI_SET
|
|
80
|
+
)
|
|
75
81
|
}
|
|
76
82
|
|
|
77
83
|
/** Warm-up velocity phrasing. Deficit is % below the 14-day average, so a
|
|
@@ -158,7 +164,12 @@ function ScoreGauge({ score }: { score: number }) {
|
|
|
158
164
|
}}
|
|
159
165
|
>
|
|
160
166
|
<Text
|
|
161
|
-
style={{
|
|
167
|
+
style={{
|
|
168
|
+
fontSize: 20,
|
|
169
|
+
fontWeight: '700',
|
|
170
|
+
fontFamily: '"Space Grotesk", sans-serif',
|
|
171
|
+
color,
|
|
172
|
+
}}
|
|
162
173
|
testID="readiness-check-score-value"
|
|
163
174
|
>
|
|
164
175
|
{score}
|
|
@@ -260,7 +271,14 @@ export function ReadinessCheck({
|
|
|
260
271
|
opacity: pressed ? 0.8 : 1,
|
|
261
272
|
})}
|
|
262
273
|
>
|
|
263
|
-
<Text
|
|
274
|
+
<Text
|
|
275
|
+
style={{
|
|
276
|
+
fontSize: 13,
|
|
277
|
+
fontWeight: '700',
|
|
278
|
+
fontFamily: 'Inter, sans-serif',
|
|
279
|
+
color: ON_BRAND_PRIMARY,
|
|
280
|
+
}}
|
|
281
|
+
>
|
|
264
282
|
Start Workout
|
|
265
283
|
</Text>
|
|
266
284
|
</Pressable>
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { Decorator, Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import { View, Text } from 'react-native'
|
|
3
3
|
import { RestTimer } from './RestTimer'
|
|
4
|
+
import { greyRamp } from '../../../theme/tokens/primitives'
|
|
5
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
6
|
+
|
|
7
|
+
const t = getSemanticColors('dark')
|
|
4
8
|
|
|
5
9
|
const meta: Meta<typeof RestTimer> = {
|
|
6
|
-
title: 'Workout/RestTimer',
|
|
10
|
+
title: 'Custom/Workout/RestTimer',
|
|
7
11
|
component: RestTimer,
|
|
8
12
|
tags: ['autodocs'],
|
|
9
13
|
parameters: {
|
|
@@ -16,7 +20,8 @@ const meta: Meta<typeof RestTimer> = {
|
|
|
16
20
|
'across-the-room wall treatment: a draining countdown ring (composes `CircularProgress`) ' +
|
|
17
21
|
'with the mm:ss countdown in its center, flipping to a full `success` ring reading "GO" ' +
|
|
18
22
|
'when rest is up. `displayOnly` hides the +30s/Skip controls in either variant; `size` ' +
|
|
19
|
-
'sets the ring diameter.'
|
|
23
|
+
'sets the ring diameter.' +
|
|
24
|
+
' Composes **CircularTimer**.',
|
|
20
25
|
},
|
|
21
26
|
},
|
|
22
27
|
},
|
|
@@ -99,10 +104,17 @@ export const JustStarted: Story = {
|
|
|
99
104
|
|
|
100
105
|
/** Wall-background frame for the ring stories (mirrors the north-star rest page). */
|
|
101
106
|
const ringDecorator: Decorator = (Story) => (
|
|
102
|
-
<View
|
|
107
|
+
<View
|
|
108
|
+
style={{
|
|
109
|
+
width: 420,
|
|
110
|
+
padding: 32,
|
|
111
|
+
alignItems: 'center',
|
|
112
|
+
backgroundColor: t['background-frame'],
|
|
113
|
+
}}
|
|
114
|
+
>
|
|
103
115
|
<Text
|
|
104
116
|
style={{
|
|
105
|
-
color:
|
|
117
|
+
color: greyRamp[700],
|
|
106
118
|
fontSize: 10,
|
|
107
119
|
fontWeight: '700',
|
|
108
120
|
letterSpacing: 1,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { View, Text, Pressable } from 'react-native'
|
|
3
3
|
import { resolveColor } from '../../../theme/resolve-color'
|
|
4
4
|
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
5
|
+
import { primitiveColors } from '../../../theme/tokens/primitives'
|
|
6
|
+
import { alpha } from '../../../utils/colors'
|
|
5
7
|
import { useTimer } from '../../../hooks/useTimer'
|
|
6
8
|
import { CircularTimer } from '../CircularTimer/CircularTimer'
|
|
7
9
|
|
|
@@ -37,7 +39,7 @@ function RestActions({ onAddTime, onSkip }: { onAddTime: () => void; onSkip: ()
|
|
|
37
39
|
<Pressable
|
|
38
40
|
onPress={onAddTime}
|
|
39
41
|
style={{
|
|
40
|
-
backgroundColor:
|
|
42
|
+
backgroundColor: alpha(primitiveColors.white, 0.06),
|
|
41
43
|
paddingVertical: 8,
|
|
42
44
|
paddingHorizontal: 20,
|
|
43
45
|
borderRadius: 8,
|
|
@@ -56,7 +58,7 @@ function RestActions({ onAddTime, onSkip }: { onAddTime: () => void; onSkip: ()
|
|
|
56
58
|
<Pressable
|
|
57
59
|
onPress={onSkip}
|
|
58
60
|
style={{
|
|
59
|
-
backgroundColor:
|
|
61
|
+
backgroundColor: alpha(BRAND_PRIMARY, 0.12),
|
|
60
62
|
paddingVertical: 8,
|
|
61
63
|
paddingHorizontal: 20,
|
|
62
64
|
borderRadius: 8,
|
|
@@ -9,14 +9,15 @@ const DAY = 24 * HOUR
|
|
|
9
9
|
const NOW = Date.now()
|
|
10
10
|
|
|
11
11
|
const meta: Meta<typeof ScheduleTiles> = {
|
|
12
|
-
title: 'Workout/ScheduleTiles',
|
|
12
|
+
title: 'Custom/Workout/ScheduleTiles',
|
|
13
13
|
component: ScheduleTiles,
|
|
14
14
|
tags: ['autodocs'],
|
|
15
15
|
parameters: {
|
|
16
16
|
docs: {
|
|
17
17
|
description: {
|
|
18
18
|
component:
|
|
19
|
-
'**Molecule.** An HStack of [Tile](?path=/docs/components-atoms-tile--docs); Until reuses [DateTime](?path=/docs/custom-datetime--docs) relative. Used-by ↑ SessionHeader.'
|
|
19
|
+
'**Molecule.** An HStack of [Tile](?path=/docs/components-atoms-tile--docs); Until reuses [DateTime](?path=/docs/custom-datetime--docs) relative. Used-by ↑ SessionHeader.' +
|
|
20
|
+
' Composes **HStack** · **Tile**.',
|
|
20
21
|
},
|
|
21
22
|
},
|
|
22
23
|
},
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import { render, screen } from '@testing-library/react'
|
|
3
3
|
import { ScheduleTiles, compactUntil } from './ScheduleTiles'
|
|
4
|
-
import {
|
|
4
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
5
5
|
|
|
6
6
|
const HOUR = 60 * 60 * 1000
|
|
7
7
|
const DAY = 24 * HOUR
|
|
8
|
-
const ORANGE = primitiveRamps.orange[400]
|
|
9
8
|
|
|
10
9
|
// A fixed reference; the compact Until label is deterministic from (when - now).
|
|
11
10
|
const NOW = Date.now()
|
|
@@ -25,10 +24,10 @@ describe('ScheduleTiles', () => {
|
|
|
25
24
|
expect(value.style.color).toBe('')
|
|
26
25
|
})
|
|
27
26
|
|
|
28
|
-
it('accents the Until value
|
|
27
|
+
it('accents the Until value with the brand token when less than a day away', () => {
|
|
29
28
|
const when = NOW + 5 * HOUR
|
|
30
29
|
render(<ScheduleTiles now={NOW} when={when} />)
|
|
31
30
|
const value = screen.getByText(compactUntil(when - NOW))
|
|
32
|
-
expect(value).toHaveStyle({ color:
|
|
31
|
+
expect(value).toHaveStyle({ color: resolveColor('brand-primary') })
|
|
33
32
|
})
|
|
34
33
|
})
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
2
|
import { type ViewProps } from 'react-native'
|
|
3
|
-
import {
|
|
3
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
4
4
|
import { HStack } from '../../ui/stack'
|
|
5
5
|
import { Tile } from '../../ui/tile/Tile'
|
|
6
6
|
import { formatDateTime } from '../DateTime/DateTime'
|
|
7
7
|
|
|
8
8
|
const DAY_MS = 24 * 60 * 60 * 1000
|
|
9
9
|
|
|
10
|
-
/** Accent applied to the Until value when the session is < 1 day away. */
|
|
11
|
-
const SOON_ACCENT = primitiveRamps.orange[400]
|
|
12
|
-
|
|
13
10
|
/** Compact time-until label: `30m` / `5h` / `2d` / `3w`. Deterministic from the delta. */
|
|
14
11
|
export function compactUntil(ms: number): string {
|
|
15
12
|
if (ms <= 0) return 'now'
|
|
@@ -37,8 +34,8 @@ export interface ScheduleTilesProps extends ViewProps {
|
|
|
37
34
|
* ScheduleTiles — Date / Time / Until row for an upcoming session.
|
|
38
35
|
*
|
|
39
36
|
* An HStack of three {@link Tile}s derived from a single scheduled moment. The
|
|
40
|
-
* Until value reuses {@link formatDateTime} relative formatting and
|
|
41
|
-
*
|
|
37
|
+
* Until value reuses {@link formatDateTime} relative formatting and takes the
|
|
38
|
+
* `brand-primary` accent only when the session is less than a day away.
|
|
42
39
|
*
|
|
43
40
|
* @example
|
|
44
41
|
* <ScheduleTiles when={Date.now() + 5 * 60 * 60 * 1000} />
|
|
@@ -63,7 +60,7 @@ export function ScheduleTiles({ when, now, gap = 1, ...props }: ScheduleTilesPro
|
|
|
63
60
|
<Tile
|
|
64
61
|
label="Until"
|
|
65
62
|
value={compactUntil(whenMs - reference)}
|
|
66
|
-
valueColor={soon ?
|
|
63
|
+
valueColor={soon ? resolveColor('brand-primary') : undefined}
|
|
67
64
|
/>
|
|
68
65
|
</HStack>
|
|
69
66
|
)
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
-
import { View } from 'react-native'
|
|
3
2
|
import { SegmentedBar } from './SegmentedBar'
|
|
3
|
+
import { Surface } from '../../ui/surface'
|
|
4
|
+
import { primitiveColors, primitiveRamps } from '../../../theme/tokens/primitives'
|
|
5
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
6
|
+
|
|
7
|
+
const t = getSemanticColors('dark')
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* `SegmentedBar` — a horizontal track split into weighted, individually-fillable
|
|
@@ -9,7 +13,7 @@ import { SegmentedBar } from './SegmentedBar'
|
|
|
9
13
|
* vertical line at a fraction of the width. Colours are passed-in literal hex.
|
|
10
14
|
*/
|
|
11
15
|
const meta: Meta<typeof SegmentedBar> = {
|
|
12
|
-
title: 'Workout/SegmentedBar',
|
|
16
|
+
title: 'Custom/Workout/SegmentedBar',
|
|
13
17
|
component: SegmentedBar,
|
|
14
18
|
tags: ['autodocs'],
|
|
15
19
|
parameters: {
|
|
@@ -19,7 +23,7 @@ const meta: Meta<typeof SegmentedBar> = {
|
|
|
19
23
|
'**Atom.** A horizontal track split into weighted, individually-fillable ' +
|
|
20
24
|
'segments (weight · fill · colour · pulse) with an optional marker line — the ' +
|
|
21
25
|
'presentational primitive the per-set strips build on. ' +
|
|
22
|
-
'Used-by ↑ [SetStrip](?path=/docs/workout-setstrip--docs).',
|
|
26
|
+
'Used-by ↑ [SetStrip](?path=/docs/custom-workout-setstrip--docs).',
|
|
23
27
|
},
|
|
24
28
|
},
|
|
25
29
|
},
|
|
@@ -30,9 +34,9 @@ const meta: Meta<typeof SegmentedBar> = {
|
|
|
30
34
|
},
|
|
31
35
|
decorators: [
|
|
32
36
|
(Story) => (
|
|
33
|
-
<
|
|
37
|
+
<Surface level="base" style={{ width: 240, padding: 16 }}>
|
|
34
38
|
<Story />
|
|
35
|
-
</
|
|
39
|
+
</Surface>
|
|
36
40
|
),
|
|
37
41
|
],
|
|
38
42
|
}
|
|
@@ -44,10 +48,10 @@ export const EqualSegments: Story = {
|
|
|
44
48
|
args: {
|
|
45
49
|
height: 8,
|
|
46
50
|
segments: [
|
|
47
|
-
{ color:
|
|
48
|
-
{ color: '
|
|
49
|
-
{ color: '
|
|
50
|
-
{ color: '
|
|
51
|
+
{ color: primitiveRamps.red[600] },
|
|
52
|
+
{ color: t['brand-primary'] },
|
|
53
|
+
{ color: t['status-warning'] },
|
|
54
|
+
{ color: t['status-success'] },
|
|
51
55
|
],
|
|
52
56
|
},
|
|
53
57
|
}
|
|
@@ -58,9 +62,9 @@ export const Weighted: Story = {
|
|
|
58
62
|
gap: 4,
|
|
59
63
|
radius: 2,
|
|
60
64
|
segments: [
|
|
61
|
-
{ color: '
|
|
62
|
-
{ color: '
|
|
63
|
-
{ color:
|
|
65
|
+
{ color: t['status-success'], weight: 3 },
|
|
66
|
+
{ color: t['status-warning'], weight: 2 },
|
|
67
|
+
{ color: primitiveRamps.red[600], weight: 1 },
|
|
64
68
|
],
|
|
65
69
|
},
|
|
66
70
|
parameters: {
|
|
@@ -74,9 +78,9 @@ export const PartialFills: Story = {
|
|
|
74
78
|
gap: 4,
|
|
75
79
|
radius: 2,
|
|
76
80
|
segments: [
|
|
77
|
-
{ color: '
|
|
78
|
-
{ color: '
|
|
79
|
-
{ color:
|
|
81
|
+
{ color: t['status-success'], fill: 1 },
|
|
82
|
+
{ color: t['status-warning'], fill: 0.6 },
|
|
83
|
+
{ color: primitiveRamps.cyan[400], fill: 0.3, pulse: true },
|
|
80
84
|
],
|
|
81
85
|
},
|
|
82
86
|
parameters: {
|
|
@@ -90,8 +94,8 @@ export const WithMarker: Story = {
|
|
|
90
94
|
args: {
|
|
91
95
|
height: 10,
|
|
92
96
|
radius: 2,
|
|
93
|
-
segments: [{ color:
|
|
94
|
-
marker: { position: 0.5, color:
|
|
97
|
+
segments: [{ color: primitiveRamps.cyan[400], fill: 0.7 }],
|
|
98
|
+
marker: { position: 0.5, color: primitiveColors.white },
|
|
95
99
|
},
|
|
96
100
|
parameters: {
|
|
97
101
|
docs: { description: { story: 'A single fill with a target marker at the halfway point.' } },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
2
|
import { useEffect, useState } from 'react'
|
|
3
3
|
import { View, Animated, Easing, type ViewProps, type DimensionValue } from 'react-native'
|
|
4
|
+
import { SET_LEVEL_FLAT_BAR } from '../charts/flatBarGeometry'
|
|
4
5
|
|
|
5
6
|
/** ~1.9s full cycle: a pulsing segment eases up then back down (2 × half). */
|
|
6
7
|
const PULSE_HALF_MS = 950
|
|
@@ -9,20 +10,23 @@ const PULSE_HALF_MS = 950
|
|
|
9
10
|
const PULSE_MIN_OPACITY = 0.45
|
|
10
11
|
|
|
11
12
|
/** Default between-segment gap — matches SetStrip's between-set gap so strips read the same. */
|
|
12
|
-
const SEGMENTED_BAR_GAP =
|
|
13
|
+
const SEGMENTED_BAR_GAP = SET_LEVEL_FLAT_BAR.gap
|
|
13
14
|
|
|
14
15
|
export interface SegmentedBarSegment {
|
|
15
16
|
/** Flex weight of this segment's slot. Default 1 (all segments equal width). */
|
|
16
17
|
weight?: number
|
|
17
18
|
/** Fraction 0..1 of the slot the coloured fill covers, left-aligned. Default 1 (full). */
|
|
18
19
|
fill?: number
|
|
19
|
-
/** Fill colour — a
|
|
20
|
+
/** Fill colour. Pass `resolveColor(token)` — a plain fill takes a `var()` ref fine. */
|
|
20
21
|
color: string
|
|
21
22
|
/** When true the fill animates on the shared active-pulse loop. */
|
|
22
23
|
pulse?: boolean
|
|
23
24
|
/**
|
|
24
25
|
* When pulsing, interpolate the fill's `backgroundColor` from→to over the loop
|
|
25
26
|
* (full opacity). Omit to fall back to the default opacity breathe.
|
|
27
|
+
*
|
|
28
|
+
* Literal hex only: `Animated.interpolate` parses these two endpoints itself
|
|
29
|
+
* and cannot read a `var()` ref, so `resolveColor(token)` does not work here.
|
|
26
30
|
*/
|
|
27
31
|
pulseColor?: [from: string, to: string]
|
|
28
32
|
/**
|
|
@@ -90,13 +94,14 @@ function usePulse(active: boolean): Animated.Value {
|
|
|
90
94
|
* presentational atom the per-set strips are built from. Each segment is a flex
|
|
91
95
|
* slot (flex = `weight`) holding a left-aligned fill (`fill` fraction, `color`);
|
|
92
96
|
* `pulse` segments breathe on a shared active-pulse loop, and `marker` drops a
|
|
93
|
-
* vertical line at a fraction of the total width.
|
|
97
|
+
* vertical line at a fraction of the total width. Every colour is injected by the
|
|
98
|
+
* composer, so this atom holds no palette of its own.
|
|
94
99
|
*/
|
|
95
100
|
export function SegmentedBar({
|
|
96
101
|
segments,
|
|
97
|
-
height =
|
|
102
|
+
height = SET_LEVEL_FLAT_BAR.height,
|
|
98
103
|
gap = SEGMENTED_BAR_GAP,
|
|
99
|
-
radius =
|
|
104
|
+
radius = SET_LEVEL_FLAT_BAR.radius,
|
|
100
105
|
marker = null,
|
|
101
106
|
segmentTestID,
|
|
102
107
|
style,
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
3
|
-
import { View } from 'react-native'
|
|
4
3
|
import { SegmentedProgressBar } from './SegmentedProgressBar'
|
|
4
|
+
import { Surface } from '../../ui/surface'
|
|
5
5
|
|
|
6
6
|
const PLAN = [{ weight: 3 }, { weight: 3 }, { weight: 2 }, { weight: 2 }, { weight: 2 }]
|
|
7
7
|
|
|
8
8
|
const meta: Meta<typeof SegmentedProgressBar> = {
|
|
9
|
-
title: 'Workout/SegmentedProgressBar',
|
|
9
|
+
title: 'Custom/Workout/SegmentedProgressBar',
|
|
10
10
|
component: SegmentedProgressBar,
|
|
11
11
|
tags: ['autodocs'],
|
|
12
12
|
parameters: {
|
|
13
13
|
docs: {
|
|
14
14
|
description: {
|
|
15
15
|
component:
|
|
16
|
-
'**Atom.** Composes [SegmentedBar](?path=/docs/workout-segmentedbar--docs) + paceTone. Used-by ↑ SessionHeader.',
|
|
16
|
+
'**Atom.** Composes [SegmentedBar](?path=/docs/custom-workout-segmentedbar--docs) + paceTone. Used-by ↑ SessionHeader.',
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
decorators: [
|
|
21
21
|
(Story) => (
|
|
22
|
-
<
|
|
22
|
+
<Surface level="base" style={{ width: 246, padding: 16 }}>
|
|
23
23
|
<Story />
|
|
24
|
-
</
|
|
24
|
+
</Surface>
|
|
25
25
|
),
|
|
26
26
|
],
|
|
27
27
|
}
|