@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
|
@@ -1,22 +1,54 @@
|
|
|
1
1
|
# Shell chrome — component family
|
|
2
2
|
|
|
3
|
-
The persistent dashboard frame (top bar, and — as the decomposition proceeds —
|
|
4
|
-
rail, drawers, pinned strip).
|
|
5
|
-
|
|
3
|
+
The persistent dashboard frame (top bar, side nav, and — as the decomposition proceeds — session
|
|
4
|
+
rail, drawers, pinned strip). The tiering below is a documentation contract, not a directory
|
|
5
|
+
layout, so promoting/composing is pure import churn.
|
|
6
6
|
|
|
7
7
|
This README is the **index**: it maps each component's dependencies (**composes ↓**) and its consumers
|
|
8
8
|
(**used-by ↑**) so you can navigate the tree in both directions and spot where a hand-rolled element
|
|
9
9
|
should be reaching for an existing primitive instead. Storybook mirrors this tree under `Shell/TopBar/…`,
|
|
10
10
|
and every component's autodocs page repeats its "Composes" links.
|
|
11
11
|
|
|
12
|
+
## The generic/app split (AW-132)
|
|
13
|
+
|
|
14
|
+
`shell/` is **generic**. It knows about a band, a rail, a brand lockup and a content region, and
|
|
15
|
+
nothing about any one product. `shell/workout/` is the **workout app's** chrome, and it composes
|
|
16
|
+
the generic family. The dependency arrow points one way only: nothing in `shell/` may import from
|
|
17
|
+
`shell/workout/`, and a second app (audiobook, active-work, agent dashboards, brain) gets its own
|
|
18
|
+
sibling directory rather than a new prop on `AppShell`.
|
|
19
|
+
|
|
20
|
+
**The composition mechanism is the library's existing slot idiom** — named `ReactNode` props with a
|
|
21
|
+
built-in default, the same shape as `Pill`'s `leading`/`trailing` and `SectionHeader`'s `trailing`.
|
|
22
|
+
No second mechanism was introduced.
|
|
23
|
+
|
|
24
|
+
| Slot | On | Default | An app uses it to… |
|
|
25
|
+
| ------------------------ | ----------- | -------------------------------- | ---------------------------------------- |
|
|
26
|
+
| `TopBar.trailing` | `TopBar` | just the clock | put its own chrome in the right cluster |
|
|
27
|
+
| `TopBar.leading` | `TopBar` | `<BrandLockup brand=…>` | replace the brand region outright |
|
|
28
|
+
| `AppShell.topBarTrailing` | `AppShell` | — | pass chrome through to the default bar |
|
|
29
|
+
| `AppShell.topBar` | `AppShell` | `<TopBar brand=…>` | swap the whole band |
|
|
30
|
+
| `AppShell.nav` | `AppShell` | `<SideNav items=…>` | swap the whole rail |
|
|
31
|
+
| `AppShell.children` | `AppShell` | a placeholder | mount its page |
|
|
32
|
+
|
|
33
|
+
`TopBar.trailing` takes an array as well as a node. **The bar interleaves its own vertical dividers
|
|
34
|
+
between the items**, so an app supplies the controls and the shell keeps the divider rhythm from the
|
|
35
|
+
S1 lock — the app never hand-places a `Divider`, and can't drift from it.
|
|
36
|
+
|
|
37
|
+
Two things stopped being generic defaults and became the workout app's data:
|
|
38
|
+
|
|
39
|
+
- `SideNav.items` is **required**. The four Live · Review · Plan · Body categories are
|
|
40
|
+
`workoutNavItems` in `shell/workout/`.
|
|
41
|
+
- `BrandLockup` is generic over `brand` (five presets in `brands.tsx`), rather than hard-coding
|
|
42
|
+
the Voltras mark and wordmark.
|
|
43
|
+
|
|
12
44
|
## Specimen: `SideNav` (the second shell unit, S2)
|
|
13
45
|
|
|
14
46
|
```
|
|
15
47
|
SideNav ...................... organism — the 60px left rail (Shell/SideNav)
|
|
16
|
-
├─ NavItem ................... molecule ×
|
|
17
|
-
│ ├─ icon ................... icons (shared primitive) —
|
|
48
|
+
├─ NavItem ................... molecule × `items` (the app's own categories)
|
|
49
|
+
│ ├─ icon ................... icons (shared primitive) — supplied per item
|
|
18
50
|
│ └─ Typography ............. titan · button variant (uppercase micro-label)
|
|
19
|
-
└─ (accent bar) ..............
|
|
51
|
+
└─ (accent bar) .............. edge bar on the active item, in the app's brand accent
|
|
20
52
|
```
|
|
21
53
|
|
|
22
54
|
Decisions locked 2026-07-08 (specimen `sources/design/shell/S2-sidenav/`): lucide glyphs
|
|
@@ -24,41 +56,58 @@ Decisions locked 2026-07-08 (specimen `sources/design/shell/S2-sidenav/`): lucid
|
|
|
24
56
|
bar** (short, centered on the icon+label) · **60px** icon+micro-label · live cue = **muted-green label**
|
|
25
57
|
(`status-live-muted`) on the Live item while a set runs off-Live · four items, no footer, no top-nav. Fixed
|
|
26
58
|
60px at every width (labels sit under the glyph). `SideNav` is presentational — `activeKey` / `onNavigate` /
|
|
27
|
-
`liveKey`; the app owns routing + which key is live.
|
|
59
|
+
`liveKey`; the app owns routing + which key is live. Those four categories are now
|
|
60
|
+
`workoutNavItems` in `shell/workout/` (AW-132); the rail itself has no built-in set.
|
|
28
61
|
|
|
29
62
|
## Specimen: `TopBar` (the first shell unit, S1)
|
|
30
63
|
|
|
31
64
|
```
|
|
32
65
|
TopBar ....................... organism — the chrome band (Shell/TopBar)
|
|
33
|
-
├─ BrandLockup ............... molecule
|
|
34
|
-
│ ├─
|
|
66
|
+
├─ BrandLockup ............... molecule — default `leading`
|
|
67
|
+
│ ├─ brand mark ............. icons (shared primitive) — per `brands.tsx` preset
|
|
35
68
|
│ └─ Typography ............. titan · button variant
|
|
36
|
-
├─
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
├─ Divider ................... titan · bg-border-prominent
|
|
40
|
-
├─ DeviceMenu ................ organism
|
|
41
|
-
│ ├─ Popover ................ titan
|
|
42
|
-
│ ├─ DeviceIndicator ........ molecule → BluetoothIcon (icons primitive)
|
|
43
|
-
│ ├─ DeviceRow .............. molecule → Indicator + Typography (body2 / mono)
|
|
44
|
-
│ └─ Typography ............. titan · monoLabel (header)
|
|
45
|
-
├─ DateTime .................. titan · mono variant, live 24h clock
|
|
69
|
+
├─ trailing[] ................ SLOT — app chrome, divider-interleaved by the bar
|
|
70
|
+
├─ Divider ................... titan · bg-border-prominent (one per slot gap)
|
|
71
|
+
├─ DateTime .................. titan · mono variant, live 24h clock (edge-pinned)
|
|
46
72
|
└─ surfaceGradient.chrome .... theme · gradient primitive
|
|
47
73
|
```
|
|
48
74
|
|
|
49
|
-
##
|
|
75
|
+
## Specimen: `WorkoutTopBar` (the same band, filled by the workout app)
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
WorkoutTopBar ................ organism — Shell/Workout/WorkoutTopBar
|
|
79
|
+
└─ TopBar .................... generic band, brand="voltras"
|
|
80
|
+
└─ trailing[] ............. supplied by the workout app:
|
|
81
|
+
├─ SessionStatePill .... molecule → Indicator + Typography (monoLabel)
|
|
82
|
+
└─ DeviceMenu .......... organism
|
|
83
|
+
├─ Popover .......... titan
|
|
84
|
+
├─ DeviceIndicator .. molecule → BluetoothIcon (icons primitive)
|
|
85
|
+
├─ DeviceRow ........ molecule → Indicator + Typography (body2 / mono)
|
|
86
|
+
└─ Typography ....... titan · monoLabel (header)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Dependency map — generic (`shell/`)
|
|
50
90
|
|
|
51
91
|
| Component | Tier | Composes ↓ | Used-by ↑ |
|
|
52
92
|
|---|---|---|---|
|
|
53
|
-
| `
|
|
93
|
+
| `AppShell` | page shell | TopBar, SideNav, Surface | WorkoutShell, any app root |
|
|
94
|
+
| `SideNav` | organism | NavItem × `items` | AppShell |
|
|
54
95
|
| `NavItem` | molecule | icon, Typography | SideNav |
|
|
55
|
-
| `TopBar` | organism | BrandLockup,
|
|
56
|
-
| `BrandLockup` | molecule |
|
|
57
|
-
| `
|
|
58
|
-
|
|
96
|
+
| `TopBar` | organism | BrandLockup, Divider, DateTime, `surfaceGradient.chrome` | AppShell, WorkoutTopBar |
|
|
97
|
+
| `BrandLockup` | molecule | a brand mark icon, Typography | TopBar |
|
|
98
|
+
| `brands.tsx` | data | VoltrasMark / Headphones / Kanban / Bot / Brain icons | BrandLockup, TopBar, AppShell |
|
|
99
|
+
|
|
100
|
+
## Dependency map — workout app (`shell/workout/`)
|
|
101
|
+
|
|
102
|
+
| Component | Tier | Composes ↓ | Used-by ↑ |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| `WorkoutShell` | page shell | AppShell, WorkoutTopBar, workoutNavItems | dashboard app root |
|
|
105
|
+
| `WorkoutTopBar` | organism | TopBar, SessionStatePill, DeviceMenu | WorkoutShell |
|
|
106
|
+
| `SessionStatePill` | molecule | Indicator, Typography | WorkoutTopBar, **Live-view header** *(planned reuse)* |
|
|
107
|
+
| `DeviceMenu` | organism | Popover, DeviceIndicator, DeviceRow, Typography | WorkoutTopBar |
|
|
59
108
|
| `DeviceIndicator` | molecule | BluetoothIcon | DeviceMenu |
|
|
60
109
|
| `DeviceRow` | molecule | Indicator, Typography | DeviceMenu |
|
|
61
|
-
| `
|
|
110
|
+
| `workoutNavItems` | data | Activity/History/Layers/PersonStanding icons | WorkoutShell |
|
|
62
111
|
|
|
63
112
|
## Shared substrates introduced here (reusable beyond the shell)
|
|
64
113
|
|
|
@@ -98,6 +147,20 @@ Every leaf now composes a primitive rather than hand-rolling it:
|
|
|
98
147
|
- **Lint guardrails** — components may not inline `linear-gradient` (use `surfaceGradient`); shell + icons may
|
|
99
148
|
not use raw hex (use tokens).
|
|
100
149
|
|
|
150
|
+
**AW-132 shared substrate:** four brand marks added to `components/icons` (`HeadphonesIcon`,
|
|
151
|
+
`KanbanIcon`, `BotIcon`, `BrainIcon`), so `brands.tsx` can carry a preset for every app expected to
|
|
152
|
+
mount this shell. Brand accents come from `data-*` rather than `status-*`: `data-*` is the library's
|
|
153
|
+
set of distinct, CVD-checked hues with no semantic load, which is what a per-app identity accent
|
|
154
|
+
needs. Voltras keeps the real `brand-primary` token.
|
|
155
|
+
|
|
156
|
+
**The nav accent is brand-level, not shell-level** (operator, Gate 2 2026-09-11). `SideNav`'s active
|
|
157
|
+
item and its edge bar take the mounting app's accent, so a Brain shell reads yellow throughout
|
|
158
|
+
rather than showing a Voltras-orange active item under a yellow lockup. `AppShell` threads it down
|
|
159
|
+
from `brand`; a bare `SideNav` takes `accentClassName` / `accentBarClassName`. Each preset declares
|
|
160
|
+
both as literals (`text-data-3` + `bg-data-3`) because Tailwind only emits classes it can see in the
|
|
161
|
+
source — a name built at runtime is never generated — and a test asserts the pair always matches.
|
|
162
|
+
Workout is unaffected: its accent *is* `brand-primary`.
|
|
163
|
+
|
|
101
164
|
**S2 shared substrate:** four nav glyphs added to `components/icons` (`ActivityIcon`, `HistoryIcon`,
|
|
102
165
|
`LayersIcon`, `PersonStandingIcon` — lucide-mirrored, like Dumbbell/Star), available system-wide.
|
|
103
166
|
|
|
@@ -3,15 +3,20 @@ import { useArgs } from 'storybook/preview-api'
|
|
|
3
3
|
import { View } from 'react-native'
|
|
4
4
|
import { SideNav } from './SideNav'
|
|
5
5
|
import { Typography } from '../custom/Typography'
|
|
6
|
+
import { Surface } from '../ui/surface'
|
|
7
|
+
import { BotIcon, BrainIcon, LayersIcon } from '../icons'
|
|
8
|
+
import { workoutNavItems } from './workout'
|
|
9
|
+
import { brandPresets } from './brands'
|
|
6
10
|
|
|
7
11
|
const meta: Meta<typeof SideNav> = {
|
|
8
12
|
title: 'Shell/SideNav',
|
|
9
13
|
component: SideNav,
|
|
10
|
-
tags: ['autodocs'],
|
|
11
|
-
args: { activeKey: 'live', liveKey: null },
|
|
14
|
+
tags: ['autodocs', 'status:candidate', '!status:review'],
|
|
15
|
+
args: { items: workoutNavItems, activeKey: 'live', liveKey: null },
|
|
12
16
|
argTypes: {
|
|
13
17
|
activeKey: { control: 'select', options: ['live', 'review', 'program', 'body'] },
|
|
14
18
|
liveKey: { control: 'select', options: [null, 'live', 'review', 'program', 'body'] },
|
|
19
|
+
items: { control: false },
|
|
15
20
|
onNavigate: { action: 'navigate' },
|
|
16
21
|
},
|
|
17
22
|
// Interactive AND Controls-synced: clicking a category writes `activeKey` back to the
|
|
@@ -35,14 +40,14 @@ const meta: Meta<typeof SideNav> = {
|
|
|
35
40
|
// stretches with the viewport (resize the canvas height to see it hold).
|
|
36
41
|
decorators: [
|
|
37
42
|
(Story) => (
|
|
38
|
-
<
|
|
43
|
+
<Surface level="base" className="min-h-screen flex-row">
|
|
39
44
|
<Story />
|
|
40
45
|
<View className="flex-1 items-center justify-center">
|
|
41
46
|
<Typography variant="body2" color="tertiary">
|
|
42
47
|
main viewport
|
|
43
48
|
</Typography>
|
|
44
49
|
</View>
|
|
45
|
-
</
|
|
50
|
+
</Surface>
|
|
46
51
|
),
|
|
47
52
|
],
|
|
48
53
|
parameters: {
|
|
@@ -50,9 +55,11 @@ const meta: Meta<typeof SideNav> = {
|
|
|
50
55
|
docs: {
|
|
51
56
|
description: {
|
|
52
57
|
component:
|
|
53
|
-
'**Organism** (shell region). The persistent 60px left rail
|
|
54
|
-
'
|
|
55
|
-
'shared [icon set](?path=/docs/foundations-icons--docs).
|
|
58
|
+
'**Organism** (shell region). The persistent 60px left rail that switches the main viewport ' +
|
|
59
|
+
"between an app's categories. Composes [NavItem](?path=/docs/shell-navitem--docs) × `items` + the " +
|
|
60
|
+
'shared [icon set](?path=/docs/foundations-icons--docs). It has no built-in categories: `items` is ' +
|
|
61
|
+
'required, and each app supplies its own (the workout set is `workoutNavItems`). ' +
|
|
62
|
+
'Presentational — drive it with `activeKey` / ' +
|
|
56
63
|
'`onNavigate` / `liveKey`. Active = left accent bar; `liveKey` (when not active) tints that ' +
|
|
57
64
|
'label a muted green.\n\n' +
|
|
58
65
|
'**Try it:** stories render in a full-height shell frame — the rail pins to the left edge and ' +
|
|
@@ -79,3 +86,27 @@ export const LiveElsewhere: Story = {
|
|
|
79
86
|
},
|
|
80
87
|
},
|
|
81
88
|
}
|
|
89
|
+
|
|
90
|
+
/** A different app's categories and accent in the same rail (AW-132). */
|
|
91
|
+
export const AnotherApp: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
items: [
|
|
94
|
+
{ key: 'notes', label: 'Notes', icon: <LayersIcon size={20} color="currentColor" /> },
|
|
95
|
+
{ key: 'graph', label: 'Graph', icon: <BrainIcon size={20} color="currentColor" /> },
|
|
96
|
+
{ key: 'agents', label: 'Agents', icon: <BotIcon size={20} color="currentColor" /> },
|
|
97
|
+
],
|
|
98
|
+
activeKey: 'graph',
|
|
99
|
+
accentClassName: brandPresets.brain.accentClassName,
|
|
100
|
+
accentBarClassName: brandPresets.brain.accentBarClassName,
|
|
101
|
+
},
|
|
102
|
+
parameters: {
|
|
103
|
+
docs: {
|
|
104
|
+
description: {
|
|
105
|
+
story:
|
|
106
|
+
"The brain app's three categories in its own accent. Same rail, same states, different " +
|
|
107
|
+
'`items` and accent. `AppShell` passes the accent down from its `brand`; drive the bare ' +
|
|
108
|
+
'rail with `accentClassName` / `accentBarClassName`.',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest'
|
|
2
2
|
import { render, screen, fireEvent, within } from '@testing-library/react'
|
|
3
3
|
import { axe } from 'jest-axe'
|
|
4
|
-
import { SideNav } from './SideNav'
|
|
4
|
+
import { SideNav, type SideNavItem } from './SideNav'
|
|
5
|
+
|
|
6
|
+
// A generic four-category set — the rail has no built-in categories any more.
|
|
7
|
+
const items: SideNavItem[] = [
|
|
8
|
+
{ key: 'live', label: 'Live', icon: null },
|
|
9
|
+
{ key: 'review', label: 'Review', icon: null },
|
|
10
|
+
{ key: 'program', label: 'Plan', icon: null },
|
|
11
|
+
{ key: 'body', label: 'Body', icon: null },
|
|
12
|
+
]
|
|
5
13
|
|
|
6
14
|
describe('SideNav', () => {
|
|
7
|
-
it('renders the
|
|
8
|
-
render(<SideNav activeKey="live" />)
|
|
15
|
+
it('renders the supplied categories as tabs in a tablist', () => {
|
|
16
|
+
render(<SideNav items={items} activeKey="live" />)
|
|
9
17
|
expect(screen.getByRole('tablist')).toBeInTheDocument()
|
|
10
18
|
;['Live', 'Review', 'Plan', 'Body'].forEach((name) => {
|
|
11
19
|
expect(screen.getByRole('tab', { name })).toBeInTheDocument()
|
|
@@ -13,7 +21,7 @@ describe('SideNav', () => {
|
|
|
13
21
|
})
|
|
14
22
|
|
|
15
23
|
it('shows the accent bar only on the active category', () => {
|
|
16
|
-
render(<SideNav activeKey="program" />)
|
|
24
|
+
render(<SideNav items={items} activeKey="program" />)
|
|
17
25
|
expect(screen.getAllByTestId('nav-item-accent')).toHaveLength(1)
|
|
18
26
|
expect(
|
|
19
27
|
within(screen.getByRole('tab', { name: 'Plan' })).getByTestId('nav-item-accent')
|
|
@@ -25,13 +33,13 @@ describe('SideNav', () => {
|
|
|
25
33
|
|
|
26
34
|
it('reports the tapped key via onNavigate', () => {
|
|
27
35
|
const onNavigate = vi.fn()
|
|
28
|
-
render(<SideNav activeKey="live" onNavigate={onNavigate} />)
|
|
36
|
+
render(<SideNav items={items} activeKey="live" onNavigate={onNavigate} />)
|
|
29
37
|
fireEvent.click(screen.getByRole('tab', { name: 'Body' }))
|
|
30
38
|
expect(onNavigate).toHaveBeenCalledWith('body')
|
|
31
39
|
})
|
|
32
40
|
|
|
33
41
|
it('keeps the active item as active even when it is also the liveKey (no double-state)', () => {
|
|
34
|
-
render(<SideNav activeKey="live" liveKey="live" />)
|
|
42
|
+
render(<SideNav items={items} activeKey="live" liveKey="live" />)
|
|
35
43
|
// active wins: exactly one accent bar, on Live (the live cue never applies to the active view)
|
|
36
44
|
expect(screen.getAllByTestId('nav-item-accent')).toHaveLength(1)
|
|
37
45
|
expect(
|
|
@@ -39,13 +47,13 @@ describe('SideNav', () => {
|
|
|
39
47
|
).toBeInTheDocument()
|
|
40
48
|
})
|
|
41
49
|
|
|
42
|
-
it('accepts
|
|
50
|
+
it('accepts an app-specific item set', () => {
|
|
43
51
|
render(<SideNav activeKey="a" items={[{ key: 'a', label: 'Alpha', icon: null }]} />)
|
|
44
52
|
expect(screen.getByRole('tab', { name: 'Alpha' })).toBeInTheDocument()
|
|
45
53
|
})
|
|
46
54
|
|
|
47
55
|
it('has no accessibility violations', async () => {
|
|
48
|
-
const { container } = render(<SideNav activeKey="live" />)
|
|
56
|
+
const { container } = render(<SideNav items={items} activeKey="live" />)
|
|
49
57
|
expect(await axe(container)).toHaveNoViolations()
|
|
50
58
|
})
|
|
51
59
|
})
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
2
|
import { View } from 'react-native'
|
|
3
3
|
import { cn } from '../../utils/cn'
|
|
4
|
-
import { ActivityIcon, HistoryIcon, LayersIcon, PersonStandingIcon } from '../icons'
|
|
5
4
|
import { NavItem } from './NavItem'
|
|
6
5
|
|
|
7
6
|
export interface SideNavItem {
|
|
@@ -14,8 +13,8 @@ export interface SideNavItem {
|
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
export interface SideNavProps {
|
|
17
|
-
/** Category items, top → bottom.
|
|
18
|
-
items
|
|
16
|
+
/** Category items, top → bottom. The app owns its own categories. */
|
|
17
|
+
items: SideNavItem[]
|
|
19
18
|
/** Key of the active category. */
|
|
20
19
|
activeKey: string
|
|
21
20
|
/** Called with the tapped item's key. */
|
|
@@ -25,30 +24,29 @@ export interface SideNavProps {
|
|
|
25
24
|
* running off its view) → a quiet green cue on that item's label.
|
|
26
25
|
*/
|
|
27
26
|
liveKey?: string | null
|
|
27
|
+
/** Semantic `text-*` token for the active item. Defaults to the Voltras brand. */
|
|
28
|
+
accentClassName?: string
|
|
29
|
+
/** Semantic `bg-*` token for the active bar. Pair it with `accentClassName`. */
|
|
30
|
+
accentBarClassName?: string
|
|
28
31
|
className?: string
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
/** The four dashboard categories with their locked S2 glyphs (activity · history · layers · figure). */
|
|
32
|
-
export const defaultNavItems: SideNavItem[] = [
|
|
33
|
-
{ key: 'live', label: 'Live', icon: <ActivityIcon size={20} color="currentColor" /> },
|
|
34
|
-
{ key: 'review', label: 'Review', icon: <HistoryIcon size={20} color="currentColor" /> },
|
|
35
|
-
{ key: 'program', label: 'Plan', icon: <LayersIcon size={20} color="currentColor" /> },
|
|
36
|
-
{ key: 'body', label: 'Body', icon: <PersonStandingIcon size={20} color="currentColor" /> },
|
|
37
|
-
]
|
|
38
|
-
|
|
39
34
|
/**
|
|
40
35
|
* Shell S2 · SideNav — the persistent 60px left rail that switches the main
|
|
41
|
-
* viewport between
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* the active view) tints that item's label a muted green.
|
|
45
|
-
* width — labels sit under the glyph, so they never change
|
|
36
|
+
* viewport between an app's categories. Presentational: it renders `items` and
|
|
37
|
+
* reports taps via `onNavigate`; the app owns its categories, routing, and which
|
|
38
|
+
* key is `live`. Active item shows a left accent bar in the app's brand accent;
|
|
39
|
+
* `liveKey` (when not the active view) tints that item's label a muted green.
|
|
40
|
+
* Fixed 60px at every width — labels sit under the glyph, so they never change
|
|
41
|
+
* the rail width.
|
|
46
42
|
*/
|
|
47
43
|
export function SideNav({
|
|
48
|
-
items
|
|
44
|
+
items,
|
|
49
45
|
activeKey,
|
|
50
46
|
onNavigate,
|
|
51
47
|
liveKey = null,
|
|
48
|
+
accentClassName,
|
|
49
|
+
accentBarClassName,
|
|
52
50
|
className,
|
|
53
51
|
}: SideNavProps) {
|
|
54
52
|
return (
|
|
@@ -66,6 +64,8 @@ export function SideNav({
|
|
|
66
64
|
label={item.label}
|
|
67
65
|
active={item.key === activeKey}
|
|
68
66
|
live={item.key === liveKey && item.key !== activeKey}
|
|
67
|
+
accentClassName={accentClassName}
|
|
68
|
+
accentBarClassName={accentBarClassName}
|
|
69
69
|
onPress={() => onNavigate?.(item.key)}
|
|
70
70
|
/>
|
|
71
71
|
))}
|
|
@@ -1,44 +1,41 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { Pill } from '../ui/pill'
|
|
2
3
|
import { TopBar } from './TopBar'
|
|
3
|
-
import {
|
|
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
|
-
]
|
|
4
|
+
import { brandKeys } from './brands'
|
|
10
5
|
|
|
11
6
|
const meta: Meta<typeof TopBar> = {
|
|
12
7
|
title: 'Shell/TopBar',
|
|
13
8
|
component: TopBar,
|
|
14
|
-
tags: ['autodocs'],
|
|
15
|
-
args: {
|
|
9
|
+
tags: ['autodocs', 'status:candidate', '!status:review'],
|
|
10
|
+
args: { brand: 'voltras' },
|
|
16
11
|
argTypes: {
|
|
17
|
-
|
|
18
|
-
devices: { control: 'object' },
|
|
12
|
+
brand: { control: 'select', options: brandKeys },
|
|
19
13
|
subtitle: { control: 'text' },
|
|
20
14
|
showSubtitle: { control: 'boolean' },
|
|
21
15
|
showClock: { control: 'boolean' },
|
|
22
16
|
time: { control: false },
|
|
23
|
-
|
|
17
|
+
leading: { control: false },
|
|
18
|
+
trailing: { control: false },
|
|
24
19
|
},
|
|
25
20
|
parameters: {
|
|
26
21
|
layout: 'fullscreen',
|
|
27
22
|
docs: {
|
|
28
23
|
description: {
|
|
29
24
|
component:
|
|
30
|
-
'**Organism** — the persistent shell chrome band,
|
|
25
|
+
'**Organism** — the persistent shell chrome band, generic over the app ' +
|
|
31
26
|
'(see `shell/README.md` for the full dependency map). Composes ' +
|
|
32
27
|
'[BrandLockup](?path=/docs/shell-brandlockup--docs) + ' +
|
|
33
|
-
'[SessionStatePill](?path=/docs/shell-sessionstatepill--docs) + ' +
|
|
34
28
|
'[Divider](?path=/docs/components-atoms-divider--docs) (`bg-border-prominent`) + ' +
|
|
35
|
-
'[DeviceMenu](?path=/docs/shell-devicemenu--docs) + ' +
|
|
36
29
|
'[DateTime](?path=/docs/components-molecules-datetime--docs) (`variant="mono"` live clock). ' +
|
|
37
30
|
'Background = the shared `surfaceGradient.chrome` primitive.\n\n' +
|
|
38
|
-
'**
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
|
|
31
|
+
'**Composition (AW-132).** The bar owns the band, the brand region, the divider ' +
|
|
32
|
+
'rhythm and the edge-pinned clock. An app supplies its own chrome through ' +
|
|
33
|
+
'`trailing` — pass an array and the bar puts its dividers between the items. ' +
|
|
34
|
+
"`leading` replaces the brand region outright. The workout app's cluster lives in " +
|
|
35
|
+
'[WorkoutTopBar](?path=/docs/shell-workout-workouttopbar--docs).\n\n' +
|
|
36
|
+
'**Try it:** switch `brand` in the **Controls**, or toggle `showSubtitle` / ' +
|
|
37
|
+
'`showClock`. **Resize the canvas** to watch the container-responsive collapse ' +
|
|
38
|
+
'(SIZE-D01) — subtitle drops < 1024px, clock < 720px.',
|
|
42
39
|
},
|
|
43
40
|
},
|
|
44
41
|
},
|
|
@@ -46,4 +43,32 @@ const meta: Meta<typeof TopBar> = {
|
|
|
46
43
|
export default meta
|
|
47
44
|
type Story = StoryObj<typeof TopBar>
|
|
48
45
|
|
|
46
|
+
/** Brand + clock only. No app has supplied any chrome. */
|
|
49
47
|
export const Default: Story = {}
|
|
48
|
+
|
|
49
|
+
/** Two app-supplied items in `trailing` — the bar adds the dividers and the clock. */
|
|
50
|
+
export const WithAppChrome: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
brand: 'brain',
|
|
53
|
+
trailing: [
|
|
54
|
+
<Pill key="index" tone="success" leading="dot" size="xs">
|
|
55
|
+
indexed
|
|
56
|
+
</Pill>,
|
|
57
|
+
<Pill key="scope" tone="neutral" size="xs">
|
|
58
|
+
4 vaults
|
|
59
|
+
</Pill>,
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** One item, no array — a single node is a valid `trailing` too. */
|
|
65
|
+
export const SingleTrailingItem: Story = {
|
|
66
|
+
args: {
|
|
67
|
+
brand: 'audiobook',
|
|
68
|
+
trailing: (
|
|
69
|
+
<Pill tone="brand-secondary" size="xs">
|
|
70
|
+
3 downloading
|
|
71
|
+
</Pill>
|
|
72
|
+
),
|
|
73
|
+
},
|
|
74
|
+
}
|
|
@@ -1,36 +1,58 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import { Text } from 'react-native'
|
|
3
4
|
import { axe } from 'jest-axe'
|
|
4
5
|
import { TopBar } from './TopBar'
|
|
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
6
|
|
|
12
7
|
const AT_1612 = new Date(2024, 0, 1, 16, 12) // local 16:12
|
|
13
8
|
|
|
14
9
|
describe('TopBar', () => {
|
|
15
|
-
it('renders brand
|
|
16
|
-
render(<TopBar
|
|
10
|
+
it('renders the brand and a 24h clock', () => {
|
|
11
|
+
render(<TopBar time={AT_1612} showClock />)
|
|
17
12
|
expect(screen.getByText('VOLTRAS')).toBeInTheDocument()
|
|
18
|
-
expect(screen.getByText('LIVE')).toBeInTheDocument()
|
|
19
13
|
expect(screen.getByText('16:12')).toBeInTheDocument()
|
|
20
14
|
})
|
|
21
15
|
|
|
16
|
+
it('renders another app brand without knowing anything about it', () => {
|
|
17
|
+
render(<TopBar brand="brain" showClock={false} />)
|
|
18
|
+
expect(screen.getByText('BRAIN')).toBeInTheDocument()
|
|
19
|
+
expect(screen.getByText('/ knowledge')).toBeInTheDocument()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('mounts app chrome from the trailing slot', () => {
|
|
23
|
+
render(
|
|
24
|
+
<TopBar
|
|
25
|
+
showClock={false}
|
|
26
|
+
trailing={[<Text key="a">alpha</Text>, <Text key="b">beta</Text>]}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
expect(screen.getByText('alpha')).toBeInTheDocument()
|
|
30
|
+
expect(screen.getByText('beta')).toBeInTheDocument()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('accepts a single trailing node as well as an array', () => {
|
|
34
|
+
render(<TopBar showClock={false} trailing={<Text>solo</Text>} />)
|
|
35
|
+
expect(screen.getByText('solo')).toBeInTheDocument()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('replaces the brand region when a leading node is given', () => {
|
|
39
|
+
render(<TopBar leading={<Text>my own lockup</Text>} showClock={false} />)
|
|
40
|
+
expect(screen.getByText('my own lockup')).toBeInTheDocument()
|
|
41
|
+
expect(screen.queryByText('VOLTRAS')).not.toBeInTheDocument()
|
|
42
|
+
})
|
|
43
|
+
|
|
22
44
|
it('hides the clock when showClock is false', () => {
|
|
23
|
-
render(<TopBar
|
|
45
|
+
render(<TopBar time={AT_1612} showClock={false} />)
|
|
24
46
|
expect(screen.queryByText('16:12')).not.toBeInTheDocument()
|
|
25
47
|
})
|
|
26
48
|
|
|
27
49
|
it('hides the subtitle when showSubtitle is false', () => {
|
|
28
|
-
render(<TopBar
|
|
50
|
+
render(<TopBar showSubtitle={false} />)
|
|
29
51
|
expect(screen.queryByText('/ wall dashboard')).not.toBeInTheDocument()
|
|
30
52
|
})
|
|
31
53
|
|
|
32
54
|
it('has no accessibility violations', async () => {
|
|
33
|
-
const { container } = render(<TopBar
|
|
55
|
+
const { container } = render(<TopBar time={AT_1612} showClock trailing={<Text>chrome</Text>} />)
|
|
34
56
|
expect(await axe(container)).toHaveNoViolations()
|
|
35
57
|
})
|
|
36
58
|
})
|