@titan-design/react-ui 0.12.0 → 0.13.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 +46 -47
- package/dist/bodymap.js +768 -701
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +770 -703
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +1320 -215
- package/dist/index.d.ts +1320 -215
- package/dist/index.js +5996 -4498
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5773 -4357
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-CvsFqNtx.d.mts → pages-CpW3OB3g.d.mts} +21 -3
- package/dist/{pages-B1hqnGIC.d.ts → pages-_3Ajpiqu.d.ts} +21 -3
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1435 -1428
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1443 -1436
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +202 -1042
- package/dist/theme/index.d.ts +202 -1042
- package/dist/theme/index.js +215 -300
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +202 -296
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +62 -5
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +62 -5
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/dist/theme/tokens.d.mts +972 -0
- package/dist/theme/tokens.d.ts +972 -0
- package/dist/theme/tokens.js +904 -0
- package/dist/theme/tokens.js.map +1 -0
- package/dist/theme/tokens.mjs +880 -0
- package/dist/theme/tokens.mjs.map +1 -0
- 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/package.json +7 -1
- package/src/arch/arch-graph.freshness.test.ts +52 -0
- package/src/arch/arch-graph.json +5021 -1617
- 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 +181 -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 +4 -3
- 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 +2 -2
- package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.tsx +4 -1
- 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 +46 -8
- package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
- package/src/components/custom/Scatter/Scatter.tsx +116 -14
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +40 -7
- 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 +98 -15
- 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 +2 -2
- package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
- package/src/components/custom/Treemap/Treemap.tsx +7 -2
- 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 +9 -1
- package/src/components/custom/Workout/BaseBadge.stories.tsx +19 -7
- package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
- package/src/components/custom/Workout/BaseBadge.tsx +3 -0
- package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
- package/src/components/custom/Workout/BodyMap.tsx +3 -1
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +16 -4
- package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +45 -9
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +10 -8
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
- package/src/components/custom/Workout/CapacityBandChart.tsx +139 -108
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
- package/src/components/custom/Workout/DeviationBar.tsx +21 -16
- package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +182 -0
- package/src/components/custom/Workout/DualVelocityStrip.test.tsx +3 -2
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -7
- package/src/components/custom/Workout/ExerciseCard.test.tsx +13 -3
- package/src/components/custom/Workout/ExerciseCard.tsx +42 -51
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +7 -7
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
- package/src/components/custom/Workout/ExerciseHeading.tsx +8 -5
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -4
- 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/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
- package/src/components/custom/Workout/IntensityBar.tsx +4 -2
- 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 +12 -9
- 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 +9 -23
- 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 +1 -1
- 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 +4 -1
- 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 +12 -7
- 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 +19 -3
- package/src/components/custom/Workout/RestTimer.stories.tsx +3 -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 +5 -5
- package/src/components/custom/Workout/SegmentedBar.tsx +6 -2
- 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 +60 -5
- 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 +3 -5
- package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
- 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 +9 -3
- package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
- package/src/components/custom/Workout/StrengthTrendChart.tsx +31 -30
- 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 +22 -7
- package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
- 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 +7 -4
- package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +4 -1
- package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +4 -1
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
- package/src/components/custom/Workout/VelocityStrip.tsx +3 -0
- 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 +7 -6
- package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
- package/src/components/custom/Workout/index.ts +5 -0
- package/src/components/custom/Workout/metricText.stories.tsx +6 -5
- package/src/components/custom/Workout/metricText.tsx +4 -0
- package/src/components/custom/Workout/setHeadingKit.tsx +207 -26
- package/src/components/custom/charts/README.md +61 -0
- package/src/components/custom/charts/SetBarChart.test.tsx +30 -1
- package/src/components/custom/charts/SetBarChart.tsx +42 -4
- 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/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 +13 -28
- 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 +90 -27
- 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 +1 -1
- 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 +32 -25
- 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 +6 -26
- 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 +9 -2
- 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 -30
- 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 +2 -12
- package/src/components/ui/indicator/Indicator.stories.tsx +1 -1
- 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 +11 -2
- 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 +29 -19
- package/src/components/ui/pill/Pill.stories.tsx +58 -23
- package/src/components/ui/pill/Pill.test.tsx +101 -3
- package/src/components/ui/pill/Pill.tsx +164 -49
- package/src/components/ui/pill/index.ts +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +5 -7
- 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/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 +5 -14
- 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 +14 -14
- 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 +1 -4
- package/src/components/ui/stack/Stack.stories.tsx +1 -1
- package/src/components/ui/stack/Stack.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +17 -5
- 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 +7 -22
- 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 +43 -53
- 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 +25 -43
- 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 +100 -47
- package/src/test/no-device-internals.test.ts +3 -3
- 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 +24 -22
- 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 +28 -0
- package/src/theme/elevation.test.ts +82 -56
- package/src/theme/elevation.ts +77 -561
- package/src/theme/global.css +30 -2
- 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/surface-planes.test.ts +37 -0
- package/src/theme/surface-planes.ts +68 -0
- package/src/theme/token-export-guard.test.ts +102 -0
- package/src/theme/tokens/primitives.test.ts +15 -7
- package/src/theme/tokens/primitives.ts +67 -35
- package/src/theme/tokens/semantic.ts +71 -37
- 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.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 +5 -0
- 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
|
@@ -2,11 +2,11 @@ import { describe, it, expect, vi } from 'vitest'
|
|
|
2
2
|
import { render, screen, fireEvent } from '@testing-library/react'
|
|
3
3
|
import { Text } from 'react-native'
|
|
4
4
|
import { axe } from 'jest-axe'
|
|
5
|
-
import { DashboardShell } from './
|
|
5
|
+
import { WorkoutShell, DashboardShell } from './WorkoutShell'
|
|
6
6
|
|
|
7
|
-
describe('
|
|
7
|
+
describe('WorkoutShell', () => {
|
|
8
8
|
it('composes the SideNav rail and its categories', () => {
|
|
9
|
-
render(<
|
|
9
|
+
render(<WorkoutShell activeKey="live" />)
|
|
10
10
|
expect(screen.getByRole('tablist')).toBeInTheDocument()
|
|
11
11
|
;['Live', 'Review', 'Plan', 'Body'].forEach((name) => {
|
|
12
12
|
expect(screen.getByRole('tab', { name })).toBeInTheDocument()
|
|
@@ -14,15 +14,15 @@ describe('DashboardShell', () => {
|
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
it('renders the content-slot placeholder when no children are given', () => {
|
|
17
|
-
render(<
|
|
17
|
+
render(<WorkoutShell activeKey="live" />)
|
|
18
18
|
expect(screen.getByText('main content region')).toBeInTheDocument()
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
it('mounts children in the content slot and drops the placeholder', () => {
|
|
22
22
|
render(
|
|
23
|
-
<
|
|
23
|
+
<WorkoutShell activeKey="review">
|
|
24
24
|
<Text>my page body</Text>
|
|
25
|
-
</
|
|
25
|
+
</WorkoutShell>
|
|
26
26
|
)
|
|
27
27
|
expect(screen.getByText('my page body')).toBeInTheDocument()
|
|
28
28
|
expect(screen.queryByText('main content region')).not.toBeInTheDocument()
|
|
@@ -30,13 +30,24 @@ describe('DashboardShell', () => {
|
|
|
30
30
|
|
|
31
31
|
it('forwards nav taps through onNavigate', () => {
|
|
32
32
|
const onNavigate = vi.fn()
|
|
33
|
-
render(<
|
|
33
|
+
render(<WorkoutShell activeKey="live" onNavigate={onNavigate} />)
|
|
34
34
|
fireEvent.click(screen.getByRole('tab', { name: 'Body' }))
|
|
35
35
|
expect(onNavigate).toHaveBeenCalledWith('body')
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
+
it('fills the generic top-bar slot with the workout chrome', () => {
|
|
39
|
+
render(<WorkoutShell activeKey="live" state="rest" />)
|
|
40
|
+
expect(screen.getByText('VOLTRAS')).toBeInTheDocument()
|
|
41
|
+
expect(screen.getByText('REST')).toBeInTheDocument()
|
|
42
|
+
expect(screen.getByRole('button', { name: 'Devices' })).toBeInTheDocument()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('still exports the pre-AW-132 DashboardShell name', () => {
|
|
46
|
+
expect(DashboardShell).toBe(WorkoutShell)
|
|
47
|
+
})
|
|
48
|
+
|
|
38
49
|
it('has no a11y violations', async () => {
|
|
39
|
-
const { container } = render(<
|
|
50
|
+
const { container } = render(<WorkoutShell activeKey="live" />)
|
|
40
51
|
expect(await axe(container)).toHaveNoViolations()
|
|
41
52
|
})
|
|
42
53
|
})
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import { AppShell } from '../AppShell'
|
|
3
|
+
import { type SideNavItem } from '../SideNav'
|
|
4
|
+
import { WorkoutTopBar } from './WorkoutTopBar'
|
|
5
|
+
import { workoutNavItems } from './workoutNavItems'
|
|
6
|
+
import { type Device } from './DeviceRow'
|
|
7
|
+
import { type SessionState } from './SessionStatePill'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `WorkoutShell` — the workout wall-dashboard chrome. Composes the generic
|
|
11
|
+
* {@link AppShell} and fills its top-bar slot with the workout's own
|
|
12
|
+
* {@link WorkoutTopBar} (session state + device menu) and its nav slot with the
|
|
13
|
+
* four workout categories. The generic shell knows none of this; this component
|
|
14
|
+
* is the whole workout-specific surface. Driven entirely by props.
|
|
15
|
+
*/
|
|
16
|
+
export interface WorkoutShellProps {
|
|
17
|
+
/** Active nav category key. */
|
|
18
|
+
activeKey?: string
|
|
19
|
+
/** Nav categories, top → bottom. Defaults to the four workout categories. */
|
|
20
|
+
navItems?: SideNavItem[]
|
|
21
|
+
/** A category with off-view live activity → a quiet cue on that item. */
|
|
22
|
+
liveKey?: string | null
|
|
23
|
+
/** Global session state → the TopBar status pill. */
|
|
24
|
+
state?: SessionState
|
|
25
|
+
/** Connected devices → the TopBar connection glyph + dropdown. */
|
|
26
|
+
devices?: Device[]
|
|
27
|
+
/** TopBar brand subtitle. */
|
|
28
|
+
subtitle?: string
|
|
29
|
+
onNavigate?: (key: string) => void
|
|
30
|
+
onSelectDevice?: (device: Device) => void
|
|
31
|
+
/** Main content region. A placeholder renders when omitted. */
|
|
32
|
+
children?: ReactNode
|
|
33
|
+
className?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DEMO_DEVICES: Device[] = [
|
|
37
|
+
{ id: 'Voltra-A3F2', nickname: 'Left Cable', slot: 'L', state: 'connected' },
|
|
38
|
+
{ id: 'Voltra-9B1C', nickname: 'Right Cable', slot: 'R', state: 'connected' },
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
export function WorkoutShell({
|
|
42
|
+
activeKey = 'live',
|
|
43
|
+
navItems = workoutNavItems,
|
|
44
|
+
liveKey = null,
|
|
45
|
+
state = 'live',
|
|
46
|
+
devices = DEMO_DEVICES,
|
|
47
|
+
subtitle = 'wall dashboard',
|
|
48
|
+
onNavigate,
|
|
49
|
+
onSelectDevice,
|
|
50
|
+
children,
|
|
51
|
+
className,
|
|
52
|
+
}: WorkoutShellProps) {
|
|
53
|
+
return (
|
|
54
|
+
<AppShell
|
|
55
|
+
className={className}
|
|
56
|
+
navItems={navItems}
|
|
57
|
+
activeKey={activeKey}
|
|
58
|
+
liveKey={liveKey}
|
|
59
|
+
onNavigate={onNavigate}
|
|
60
|
+
topBar={
|
|
61
|
+
<WorkoutTopBar
|
|
62
|
+
state={state}
|
|
63
|
+
devices={devices}
|
|
64
|
+
subtitle={subtitle}
|
|
65
|
+
onSelectDevice={onSelectDevice}
|
|
66
|
+
/>
|
|
67
|
+
}
|
|
68
|
+
>
|
|
69
|
+
{children}
|
|
70
|
+
</AppShell>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** @deprecated Renamed to `WorkoutShell` — same props (AW-132). Removed after consumer migration. */
|
|
75
|
+
export const DashboardShell = WorkoutShell
|
|
76
|
+
/** @deprecated Renamed to `WorkoutShellProps` (AW-132). */
|
|
77
|
+
export type DashboardShellProps = WorkoutShellProps
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { WorkoutTopBar } from './WorkoutTopBar'
|
|
3
|
+
import { type Device } from './DeviceRow'
|
|
4
|
+
|
|
5
|
+
const DEVICES: Device[] = [
|
|
6
|
+
{ id: 'Voltra-A3F2', nickname: 'Left Cable', slot: 'L', state: 'connected' },
|
|
7
|
+
{ id: 'Voltra-9B1C', nickname: 'Right Cable', slot: 'R', state: 'connected' },
|
|
8
|
+
{ id: 'Voltra-77E0', nickname: 'Spare', slot: null, state: 'available' },
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
const meta: Meta<typeof WorkoutTopBar> = {
|
|
12
|
+
title: 'Shell/Workout/WorkoutTopBar',
|
|
13
|
+
component: WorkoutTopBar,
|
|
14
|
+
tags: ['autodocs', 'status:candidate', '!status:review'],
|
|
15
|
+
args: { state: 'live', devices: DEVICES },
|
|
16
|
+
argTypes: {
|
|
17
|
+
state: { control: 'select', options: ['live', 'rest', 'idle'] },
|
|
18
|
+
devices: { control: 'object' },
|
|
19
|
+
subtitle: { control: 'text' },
|
|
20
|
+
showSubtitle: { control: 'boolean' },
|
|
21
|
+
showClock: { control: 'boolean' },
|
|
22
|
+
time: { control: false },
|
|
23
|
+
onSelectDevice: { control: false },
|
|
24
|
+
},
|
|
25
|
+
parameters: {
|
|
26
|
+
layout: 'fullscreen',
|
|
27
|
+
docs: {
|
|
28
|
+
description: {
|
|
29
|
+
component:
|
|
30
|
+
'**Organism (workout app).** The generic ' +
|
|
31
|
+
"[TopBar](?path=/docs/shell-topbar--docs) with the workout's own chrome in its " +
|
|
32
|
+
'`trailing` slot: [SessionStatePill](?path=/docs/shell-workout-sessionstatepill--docs) ' +
|
|
33
|
+
'then [DeviceMenu](?path=/docs/shell-workout-devicemenu--docs). The bar adds the ' +
|
|
34
|
+
'dividers and the edge-pinned clock; this component only supplies the items ' +
|
|
35
|
+
'(AW-132).\n\n' +
|
|
36
|
+
'**Try it:** use the **Controls** to change `state`, edit `devices` (set one to ' +
|
|
37
|
+
'`lost` to see the fault), or toggle `showSubtitle` / `showClock`. **Resize the ' +
|
|
38
|
+
'canvas** to watch the container-responsive collapse (SIZE-D01). Click the device ' +
|
|
39
|
+
'glyph to open the menu.',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
export default meta
|
|
45
|
+
type Story = StoryObj<typeof WorkoutTopBar>
|
|
46
|
+
|
|
47
|
+
export const Default: Story = {}
|
|
48
|
+
|
|
49
|
+
/** A lost device — the glyph alone carries the fault. */
|
|
50
|
+
export const DeviceLost: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
state: 'rest',
|
|
53
|
+
devices: [
|
|
54
|
+
{ id: 'Voltra-A3F2', nickname: 'Left Cable', slot: 'L', state: 'connected' },
|
|
55
|
+
{ id: 'Voltra-9B1C', nickname: 'Right Cable', slot: 'R', state: 'lost' },
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import { axe } from 'jest-axe'
|
|
4
|
+
import { WorkoutTopBar } from './WorkoutTopBar'
|
|
5
|
+
import { type Device } from './DeviceRow'
|
|
6
|
+
|
|
7
|
+
const devices: Device[] = [
|
|
8
|
+
{ id: 'Voltra-A3F2', nickname: 'Left Cable', slot: 'L', state: 'connected' },
|
|
9
|
+
{ id: 'Voltra-9B1C', nickname: 'Right Cable', slot: 'R', state: 'connected' },
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
const AT_1612 = new Date(2024, 0, 1, 16, 12) // local 16:12
|
|
13
|
+
|
|
14
|
+
describe('WorkoutTopBar', () => {
|
|
15
|
+
it('renders brand, session state, the device glyph and a 24h clock', () => {
|
|
16
|
+
render(<WorkoutTopBar state="live" devices={devices} time={AT_1612} showClock />)
|
|
17
|
+
expect(screen.getByText('VOLTRAS')).toBeInTheDocument()
|
|
18
|
+
expect(screen.getByText('LIVE')).toBeInTheDocument()
|
|
19
|
+
expect(screen.getByRole('button', { name: 'Devices' })).toBeInTheDocument()
|
|
20
|
+
expect(screen.getByText('16:12')).toBeInTheDocument()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('hides the clock when showClock is false', () => {
|
|
24
|
+
render(<WorkoutTopBar state="live" devices={devices} time={AT_1612} showClock={false} />)
|
|
25
|
+
expect(screen.queryByText('16:12')).not.toBeInTheDocument()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('hides the subtitle when showSubtitle is false', () => {
|
|
29
|
+
render(<WorkoutTopBar state="rest" devices={devices} showSubtitle={false} />)
|
|
30
|
+
expect(screen.queryByText('/ wall dashboard')).not.toBeInTheDocument()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('has no accessibility violations', async () => {
|
|
34
|
+
const { container } = render(
|
|
35
|
+
<WorkoutTopBar state="live" devices={devices} time={AT_1612} showClock />
|
|
36
|
+
)
|
|
37
|
+
expect(await axe(container)).toHaveNoViolations()
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { TopBar } from '../TopBar'
|
|
2
|
+
import { SessionStatePill, type SessionState } from './SessionStatePill'
|
|
3
|
+
import { DeviceMenu } from './DeviceMenu'
|
|
4
|
+
import { type Device } from './DeviceRow'
|
|
5
|
+
|
|
6
|
+
export interface WorkoutTopBarProps {
|
|
7
|
+
/** Global session state → the status pill. */
|
|
8
|
+
state: SessionState
|
|
9
|
+
/** Devices for the connection glyph + dropdown. */
|
|
10
|
+
devices: Device[]
|
|
11
|
+
/** The moment to display in the clock (Date/timestamp). Omit for a live ticking clock. */
|
|
12
|
+
time?: number | Date
|
|
13
|
+
/** Brand subtitle. Default "wall dashboard". */
|
|
14
|
+
subtitle?: string
|
|
15
|
+
/** Force the subtitle on/off; defaults to container-responsive. */
|
|
16
|
+
showSubtitle?: boolean
|
|
17
|
+
/** Force the clock on/off; defaults to container-responsive. */
|
|
18
|
+
showClock?: boolean
|
|
19
|
+
onSelectDevice?: (device: Device) => void
|
|
20
|
+
className?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The workout app's top bar — the generic {@link TopBar} with the workout's own
|
|
25
|
+
* chrome in its `trailing` slot: session state, then the device menu. The bar
|
|
26
|
+
* adds its dividers and the clock; this component only supplies the items.
|
|
27
|
+
*/
|
|
28
|
+
export function WorkoutTopBar({
|
|
29
|
+
state,
|
|
30
|
+
devices,
|
|
31
|
+
time,
|
|
32
|
+
subtitle,
|
|
33
|
+
showSubtitle,
|
|
34
|
+
showClock,
|
|
35
|
+
onSelectDevice,
|
|
36
|
+
className,
|
|
37
|
+
}: WorkoutTopBarProps) {
|
|
38
|
+
return (
|
|
39
|
+
<TopBar
|
|
40
|
+
brand="voltras"
|
|
41
|
+
subtitle={subtitle}
|
|
42
|
+
showSubtitle={showSubtitle}
|
|
43
|
+
showClock={showClock}
|
|
44
|
+
time={time}
|
|
45
|
+
className={className}
|
|
46
|
+
trailing={[
|
|
47
|
+
<SessionStatePill key="state" state={state} />,
|
|
48
|
+
<DeviceMenu key="devices" devices={devices} onSelectDevice={onSelectDevice} />,
|
|
49
|
+
]}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Workout-app shell chrome — composes the generic shell family one directory up.
|
|
2
|
+
// Nothing here is reusable by another app; nothing generic may import from here.
|
|
3
|
+
export * from './SessionStatePill'
|
|
4
|
+
export * from './DeviceIndicator'
|
|
5
|
+
export * from './DeviceRow'
|
|
6
|
+
export * from './DeviceMenu'
|
|
7
|
+
export * from './workoutNavItems'
|
|
8
|
+
export * from './WorkoutTopBar'
|
|
9
|
+
export * from './WorkoutShell'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ActivityIcon, HistoryIcon, LayersIcon, PersonStandingIcon } from '../../icons'
|
|
2
|
+
import { type SideNavItem } from '../SideNav'
|
|
3
|
+
|
|
4
|
+
/** The four workout-dashboard categories with their locked S2 glyphs (activity · history · layers · figure). */
|
|
5
|
+
export const workoutNavItems: SideNavItem[] = [
|
|
6
|
+
{ key: 'live', label: 'Live', icon: <ActivityIcon size={20} color="currentColor" /> },
|
|
7
|
+
{ key: 'review', label: 'Review', icon: <HistoryIcon size={20} color="currentColor" /> },
|
|
8
|
+
{ key: 'program', label: 'Plan', icon: <LayersIcon size={20} color="currentColor" /> },
|
|
9
|
+
{ key: 'body', label: 'Body', icon: <PersonStandingIcon size={20} color="currentColor" /> },
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Use `workoutNavItems` — these are the workout app's categories,
|
|
14
|
+
* not a generic shell default. `SideNav.items` is required now (AW-132).
|
|
15
|
+
*/
|
|
16
|
+
export const defaultNavItems = workoutNavItems
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# `ui/*` — the generic primitive family
|
|
2
|
+
|
|
3
|
+
The domain-free foundation tier: 38 primitives that know nothing about workouts,
|
|
4
|
+
sessions or initiatives. Everything in `custom/*` and `shell/*` is built on this
|
|
5
|
+
layer, and `ui/*` may not import from either of them — the tier order is
|
|
6
|
+
`theme → icons → ui → custom → shell → pages`.
|
|
7
|
+
|
|
8
|
+
This README is the **index**. It maps each primitive's dependencies
|
|
9
|
+
(**composes ↓**) and its consumers (**used-by ↑**) so the tree navigates in both
|
|
10
|
+
directions and a hand-rolled element that should have reached for an existing
|
|
11
|
+
primitive is visible. Storybook mirrors it under
|
|
12
|
+
`Components/Atoms|Molecules|Organisms/…`; each primitive's autodocs page repeats
|
|
13
|
+
its Composes links.
|
|
14
|
+
|
|
15
|
+
Counts below are generated, not hand-kept: they come from
|
|
16
|
+
[`src/arch/arch-graph.json`](../../arch/arch-graph.json) (regenerate with
|
|
17
|
+
`pnpm arch:graph`, which `arch-graph.freshness.test.ts` keeps honest). **In-repo**
|
|
18
|
+
is in-library consumers; **external** is import sites in the three checkouts the
|
|
19
|
+
graph scans (voltras mobile, voltras-mcp, codewatch dashboard). It is a floor,
|
|
20
|
+
not a census: `docs/audits/2026-09-08-critique-addenda.md` §D1 found seven
|
|
21
|
+
downstream checkouts, and audiobook/frontend — the one that tracks HEAD — is not
|
|
22
|
+
among the three.
|
|
23
|
+
|
|
24
|
+
## The one rule this family exists to enforce
|
|
25
|
+
|
|
26
|
+
A primitive here is the _only_ implementation of its shape. When a family needs
|
|
27
|
+
a rule, a pill, a dot or a plane, it composes `ui/*` — it does not draw one. The
|
|
28
|
+
audit that produced this file found four container primitives competing and
|
|
29
|
+
twelve pill-shaped components; roadmap decisions 1, 3, 4, 5, 10 and 11 collapsed
|
|
30
|
+
them, and the survivors are marked as presets below.
|
|
31
|
+
|
|
32
|
+
## Dependency map
|
|
33
|
+
|
|
34
|
+
| Component | Tier | Composes ↓ | Used-by ↑ (in-repo) | In-repo | External |
|
|
35
|
+
| ---------------- | -------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------- |
|
|
36
|
+
| `alert` | atom | — | — (app-facing leaf) | 0 | 6 |
|
|
37
|
+
| `autocomplete` | molecule | Surface | — | 0 | 0 |
|
|
38
|
+
| `avatar` | atom | — | — | 0 | 0 |
|
|
39
|
+
| `badge` | molecule | Pill, Indicator | BodyMapDetailPanel, MesoCard, ReadinessCheck | 3 | 3 |
|
|
40
|
+
| `breadcrumbs` | atom | — | — | 0 | 0 |
|
|
41
|
+
| `button` | atom | — | examples | 1 | 17 |
|
|
42
|
+
| `card` | molecule | Surface | CoChangeChip, FileActivityDetail, FileHistoryExplorer, InitiativeCard, MesoCard, MesoStatusCard, PortfolioOverview, ReadinessCheck, SessionDetail, WorkoutCard | 10 | 74 |
|
|
43
|
+
| `checkbox` | atom | — | examples | 1 | 0 |
|
|
44
|
+
| `chip` | molecule | Pill | — (external-only preset) | 0 | 0 |
|
|
45
|
+
| `collapse` | atom | — | SessionDetail | 1 | 0 |
|
|
46
|
+
| `data-row` | atom | — | FileActivityDetail, VolumeLandmarkBar | 2 | 2 |
|
|
47
|
+
| `divider` | atom | — | FileHistoryExplorer, OpenLoops, SessionDetail, SessionList, TopBar | 5 | 2 |
|
|
48
|
+
| `drawer` | molecule | Surface | PrHistoryModal | 1 | 6 |
|
|
49
|
+
| `form-field` | atom | — | examples | 1 | 0 |
|
|
50
|
+
| `help-tip` | molecule | Surface | — **deprecated**, use Tooltip | 0 | 0 |
|
|
51
|
+
| `icon-box` | atom | — | — | 0 | 0 |
|
|
52
|
+
| `indicator` | atom | — | Badge, DeviceRow, SessionStatePill, SeverityLabel | 6 | 0 |
|
|
53
|
+
| `input` | atom | — | examples | 1 | 1 |
|
|
54
|
+
| `link` | atom | — | — | 0 | 0 |
|
|
55
|
+
| `list-item` | atom | — | — (app-facing leaf) | 0 | 9 |
|
|
56
|
+
| `menu` | molecule | Surface | — | 0 | 0 |
|
|
57
|
+
| `modal` | molecule | Surface | — | 0 | 0 |
|
|
58
|
+
| `pill` | atom | — | Badge, Chip, CoChangeChip, FileActivityDetail, InitiativeCard, InitiativeHeader, MuscleGroupChip, OpenLoops, SessionDetail, StatusPill, TaskRow | 11 | 1 |
|
|
59
|
+
| `popover` | molecule | Surface | DeviceMenu | 1 | 0 |
|
|
60
|
+
| `progress` | atom | — | CircularTimer | 1 | 2 |
|
|
61
|
+
| `radio` | atom | — | examples | 1 | 2 |
|
|
62
|
+
| `section` | atom | — | — (app-facing leaf) | 0 | 10 |
|
|
63
|
+
| `select` | molecule | Surface | examples | 2 | 1 |
|
|
64
|
+
| `skeleton` | atom | — | — | 0 | 0 |
|
|
65
|
+
| `spinner` | atom | — | — (app-facing leaf) | 0 | 2 |
|
|
66
|
+
| `stack` | atom | — | MetricTiles, ScheduleTiles | 2 | 27 |
|
|
67
|
+
| `surface` | atom | — | Autocomplete, Card, DashboardShell, Drawer, HelpTip, LiveFatigueCard, Menu, Modal, Popover, Select, SessionHeader, SessionRail, Toast, ToolbarButton, Tooltip | 15 | 29 |
|
|
68
|
+
| `switch` | atom | — | — | 0 | 0 |
|
|
69
|
+
| `tabs` | atom | — | — | 0 | 0 |
|
|
70
|
+
| `tile` | atom | — | FileActivityDetail, FileHistoryExplorer, MetricTiles, ScheduleTiles — **deprecated**, use a Card stat preset | 4 | 0 |
|
|
71
|
+
| `toast` | molecule | Surface | — | 0 | 0 |
|
|
72
|
+
| `toolbar-button` | molecule | Surface | — | 0 | 0 |
|
|
73
|
+
| `tooltip` | molecule | Surface | FatigueLights, SessionDetail, SessionListItem, Table, TaskRow, ZoneTrack | 8 | 1 |
|
|
74
|
+
|
|
75
|
+
Two roots carry the family: **`surface`** (15 in-repo consumers — every floating
|
|
76
|
+
and raised plane) and **`pill`** (11 — every pill-shaped label since decision 3).
|
|
77
|
+
Nothing else in `ui/*` is composed by more than six.
|
|
78
|
+
|
|
79
|
+
## Reuse audit — where `ui/*` still hand-rolls
|
|
80
|
+
|
|
81
|
+
| Leaf | Should compose | Status |
|
|
82
|
+
| -------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
83
|
+
| Text runs (79 raw `<Text>` in 27 files) | `Typography` | **Open.** `Typography` is in `custom/`, which `ui/*` may not import. Roadmap decision 9 moves it into `ui/`; until then every heading and label here is hand-styled. |
|
|
84
|
+
| Pill-shaped labels | `Pill` | **Closed** (#172). `Badge` and `Chip` now render `<Pill>`; the six folded-in variants are in `DEPRECATIONS.md`. |
|
|
85
|
+
| Status dots | `Indicator` | **Closed** for `ui/*`. `StatusDot` (Workout) is deprecated toward `Indicator` (decision 10). |
|
|
86
|
+
| Raised / floating planes | `Surface` (`raise` / `elevation`) | **Closed** (#166, #173). Eleven molecules compose `Surface` rather than setting `bg-surface-*` themselves. |
|
|
87
|
+
| Rules and separators (20 `border-hairline*` in 12 files) | `Divider` | **Partly open.** Decision 4 allows `border-hairline` only on Card `outline`/`subtle`, Table rules and input borders — `Select`, `Radio`, `Drawer` and `Tabs` still draw their own. |
|
|
88
|
+
| Tooltip-with-a-label lockup | `Tooltip` + your own label | **Closed** by deprecation. `HelpTip` and `LabelWithHelp` are retired (decision 5). |
|
|
89
|
+
|
|
90
|
+
## Watch list
|
|
91
|
+
|
|
92
|
+
- **`Typography` cannot be composed here.** The tier order forbids the import, so
|
|
93
|
+
the 79 raw `<Text>` runs above cannot be fixed inside this family. Blocked on
|
|
94
|
+
roadmap E3 moving `Typography` and `Eyebrow` into `ui/`.
|
|
95
|
+
- **Fourteen primitives read as dead** — `autocomplete`, `avatar`, `breadcrumbs`,
|
|
96
|
+
`chip`, `help-tip`, `icon-box`, `link`, `menu`, `modal`, `skeleton`, `switch`,
|
|
97
|
+
`tabs`, `toast`, `toolbar-button`. That is not automatically a delete: the graph
|
|
98
|
+
sees three of seven downstream checkouts, and `Chip` in particular has a known
|
|
99
|
+
consumer (audiobook/frontend, §D1) the graph cannot see. Settle per component
|
|
100
|
+
under roadmap E6.4, not by reading this table.
|
|
101
|
+
- **`modal` and `menu` read dead while `drawer` and `popover` do not.** The
|
|
102
|
+
overlay set is mid-migration onto the floating lift (E1); recheck after the
|
|
103
|
+
trigger work lands rather than treating the split as a decision.
|
|
104
|
+
|
|
105
|
+
## Maturity
|
|
106
|
+
|
|
107
|
+
Status tags on these stories are derived, not chosen — the rule is in
|
|
108
|
+
[`MATURITY.md`](../../../MATURITY.md). Membership in the dependency map above is
|
|
109
|
+
one of its three inputs, so **adding a primitive here without adding its row
|
|
110
|
+
leaves it `status:candidate`**.
|
|
@@ -5,7 +5,7 @@ import { Alert, AlertTitle, AlertDescription } from './Alert'
|
|
|
5
5
|
const meta: Meta<typeof Alert> = {
|
|
6
6
|
title: 'Components/Molecules/Alert',
|
|
7
7
|
component: Alert,
|
|
8
|
-
tags: ['autodocs'],
|
|
8
|
+
tags: ['autodocs', 'status:stable', '!status:review'],
|
|
9
9
|
parameters: {
|
|
10
10
|
docs: {
|
|
11
11
|
description: {
|
|
@@ -6,7 +6,7 @@ import { Autocomplete, AutocompleteOption } from './Autocomplete'
|
|
|
6
6
|
const meta: Meta<typeof Autocomplete> = {
|
|
7
7
|
title: 'Components/Molecules/Autocomplete',
|
|
8
8
|
component: Autocomplete,
|
|
9
|
-
tags: ['autodocs'],
|
|
9
|
+
tags: ['autodocs', 'status:stable', '!status:review'],
|
|
10
10
|
argTypes: {
|
|
11
11
|
isDisabled: {
|
|
12
12
|
control: 'boolean',
|
|
@@ -48,9 +48,7 @@ export const Default: Story = {
|
|
|
48
48
|
onChange={setValue}
|
|
49
49
|
placeholder="Search fruits..."
|
|
50
50
|
/>
|
|
51
|
-
<Text className="text-sm text-text-secondary mt-2">
|
|
52
|
-
Selected: {value || 'None'}
|
|
53
|
-
</Text>
|
|
51
|
+
<Text className="text-sm text-text-secondary mt-2">Selected: {value || 'None'}</Text>
|
|
54
52
|
</View>
|
|
55
53
|
)
|
|
56
54
|
},
|
|
@@ -140,12 +138,7 @@ export const Disabled: Story = {
|
|
|
140
138
|
render: function Render() {
|
|
141
139
|
return (
|
|
142
140
|
<View className="w-64">
|
|
143
|
-
<Autocomplete
|
|
144
|
-
options={fruitOptions}
|
|
145
|
-
value="apple"
|
|
146
|
-
label="Disabled field"
|
|
147
|
-
isDisabled
|
|
148
|
-
/>
|
|
141
|
+
<Autocomplete options={fruitOptions} value="apple" label="Disabled field" isDisabled />
|
|
149
142
|
</View>
|
|
150
143
|
)
|
|
151
144
|
},
|
|
@@ -175,7 +168,12 @@ export const DisabledOptions: Story = {
|
|
|
175
168
|
const optionsWithDisabled: AutocompleteOption[] = [
|
|
176
169
|
{ value: 'free', label: 'Free Plan' },
|
|
177
170
|
{ value: 'pro', label: 'Pro Plan' },
|
|
178
|
-
{
|
|
171
|
+
{
|
|
172
|
+
value: 'enterprise',
|
|
173
|
+
label: 'Enterprise Plan',
|
|
174
|
+
isDisabled: true,
|
|
175
|
+
description: 'Contact sales',
|
|
176
|
+
},
|
|
179
177
|
]
|
|
180
178
|
return (
|
|
181
179
|
<View className="w-64">
|
|
@@ -289,8 +287,8 @@ export const FormExample: Story = {
|
|
|
289
287
|
|
|
290
288
|
<View className="pt-2 border-t border-hairline">
|
|
291
289
|
<Text className="text-sm text-text-secondary">
|
|
292
|
-
Selected: {country ? `${countryOptions.find(c => c.value === country)?.label}` : '-'}
|
|
293
|
-
{city ? `, ${cityOptions[country!]?.find(c => c.value === city)?.label}` : ''}
|
|
290
|
+
Selected: {country ? `${countryOptions.find((c) => c.value === country)?.label}` : '-'}
|
|
291
|
+
{city ? `, ${cityOptions[country!]?.find((c) => c.value === city)?.label}` : ''}
|
|
294
292
|
</Text>
|
|
295
293
|
</View>
|
|
296
294
|
</View>
|
|
@@ -102,26 +102,20 @@ describe('Autocomplete', () => {
|
|
|
102
102
|
})
|
|
103
103
|
|
|
104
104
|
it('shows clear button when value is selected', () => {
|
|
105
|
-
render(
|
|
106
|
-
<Autocomplete options={defaultOptions} value="1" isClearable />
|
|
107
|
-
)
|
|
105
|
+
render(<Autocomplete options={defaultOptions} value="1" isClearable />)
|
|
108
106
|
expect(screen.getByLabelText('Clear selection')).toBeInTheDocument()
|
|
109
107
|
})
|
|
110
108
|
|
|
111
109
|
it('calls onChange with null when clear is pressed', () => {
|
|
112
110
|
const onChange = vi.fn()
|
|
113
|
-
render(
|
|
114
|
-
<Autocomplete options={defaultOptions} value="1" onChange={onChange} isClearable />
|
|
115
|
-
)
|
|
111
|
+
render(<Autocomplete options={defaultOptions} value="1" onChange={onChange} isClearable />)
|
|
116
112
|
|
|
117
113
|
fireEvent.click(screen.getByLabelText('Clear selection'))
|
|
118
114
|
expect(onChange).toHaveBeenCalledWith(null)
|
|
119
115
|
})
|
|
120
116
|
|
|
121
117
|
it('does not show clear button when isClearable is false', () => {
|
|
122
|
-
render(
|
|
123
|
-
<Autocomplete options={defaultOptions} value="1" isClearable={false} />
|
|
124
|
-
)
|
|
118
|
+
render(<Autocomplete options={defaultOptions} value="1" isClearable={false} />)
|
|
125
119
|
expect(screen.queryByLabelText('Clear selection')).not.toBeInTheDocument()
|
|
126
120
|
})
|
|
127
121
|
|
|
@@ -144,13 +138,7 @@ describe('Autocomplete', () => {
|
|
|
144
138
|
})
|
|
145
139
|
|
|
146
140
|
it('shows custom minCharsText', () => {
|
|
147
|
-
render(
|
|
148
|
-
<Autocomplete
|
|
149
|
-
options={defaultOptions}
|
|
150
|
-
minChars={3}
|
|
151
|
-
minCharsText="Keep typing..."
|
|
152
|
-
/>
|
|
153
|
-
)
|
|
141
|
+
render(<Autocomplete options={defaultOptions} minChars={3} minCharsText="Keep typing..." />)
|
|
154
142
|
const input = screen.getByPlaceholderText('Search...')
|
|
155
143
|
|
|
156
144
|
typeInInput(input, 'A')
|
|
@@ -185,9 +173,7 @@ describe('Autocomplete', () => {
|
|
|
185
173
|
})
|
|
186
174
|
|
|
187
175
|
it('does not show clear button when disabled', () => {
|
|
188
|
-
render(
|
|
189
|
-
<Autocomplete options={defaultOptions} value="1" isDisabled isClearable />
|
|
190
|
-
)
|
|
176
|
+
render(<Autocomplete options={defaultOptions} value="1" isDisabled isClearable />)
|
|
191
177
|
expect(screen.queryByLabelText('Clear selection')).not.toBeInTheDocument()
|
|
192
178
|
})
|
|
193
179
|
})
|
|
@@ -225,9 +211,7 @@ describe('Autocomplete', () => {
|
|
|
225
211
|
|
|
226
212
|
describe('accessibility', () => {
|
|
227
213
|
it('has no accessibility violations', async () => {
|
|
228
|
-
const { container } = render(
|
|
229
|
-
<Autocomplete options={defaultOptions} label="Search" />
|
|
230
|
-
)
|
|
214
|
+
const { container } = render(<Autocomplete options={defaultOptions} label="Search" />)
|
|
231
215
|
const results = await axe(container)
|
|
232
216
|
expect(results).toHaveNoViolations()
|
|
233
217
|
})
|
|
@@ -238,9 +222,7 @@ describe('Autocomplete', () => {
|
|
|
238
222
|
})
|
|
239
223
|
|
|
240
224
|
it('clear button has accessible label', () => {
|
|
241
|
-
render(
|
|
242
|
-
<Autocomplete options={defaultOptions} value="1" isClearable />
|
|
243
|
-
)
|
|
225
|
+
render(<Autocomplete options={defaultOptions} value="1" isClearable />)
|
|
244
226
|
expect(screen.getByLabelText('Clear selection')).toBeInTheDocument()
|
|
245
227
|
})
|
|
246
228
|
})
|