@titan-design/react-ui 0.12.1 → 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 +1319 -216
- package/dist/index.d.ts +1319 -216
- 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 +195 -134
- package/dist/theme/index.d.ts +195 -134
- 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 +73 -5
- package/dist/theme/tokens.d.ts +73 -5
- package/dist/theme/tokens.js +55 -7
- package/dist/theme/tokens.js.map +1 -1
- package/dist/theme/tokens.mjs +55 -8
- 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/package.json +1 -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 +11 -6
- 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 +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 +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 +23 -21
- 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 +1 -3
- package/src/theme/tokens/primitives.test.ts +15 -7
- package/src/theme/tokens/primitives.ts +65 -33
- 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
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
|
+
import { View, Pressable } from 'react-native'
|
|
3
|
+
import { SparkBars } from '../charts'
|
|
4
|
+
import { Typography } from '../Typography'
|
|
5
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
6
|
+
import { categoricalPalette } from '../../../theme/tokens/primitives'
|
|
7
|
+
import { FilePathLabel } from './FilePathLabel'
|
|
8
|
+
|
|
9
|
+
/** Fill per event kind, shared by the row's counts and the detail pane's tiles. */
|
|
10
|
+
export interface FileEventColors {
|
|
11
|
+
reads: string
|
|
12
|
+
writes: string
|
|
13
|
+
edits: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Reads/writes/edits read as *importance* rather than as peer categories: reads
|
|
18
|
+
* are cheap and quiet, writes are the consequential ones, edits sit between.
|
|
19
|
+
*/
|
|
20
|
+
export const FILE_EVENT_COLOR_SEMANTIC: FileEventColors = {
|
|
21
|
+
reads: resolveColor('text-tertiary'),
|
|
22
|
+
writes: resolveColor('brand-primary'),
|
|
23
|
+
edits: resolveColor('status-info'),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The same three as *peer categories*, taken in order from the canonical
|
|
28
|
+
* CVD-safe palette (TOKENS.md §2).
|
|
29
|
+
*/
|
|
30
|
+
export const FILE_EVENT_COLOR_CATEGORICAL: FileEventColors = {
|
|
31
|
+
reads: categoricalPalette.default[0],
|
|
32
|
+
writes: categoricalPalette.default[1],
|
|
33
|
+
edits: categoricalPalette.default[2],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The family default: the three event kinds are peer categories, so they take
|
|
38
|
+
* the canonical CVD-safe palette in order rather than a hand-picked triple.
|
|
39
|
+
* Costs three of `CATEGORICAL_CVD_SAFE_MAX` — a view that also plots series
|
|
40
|
+
* needs to start from index 3, or supply its own `eventColors`.
|
|
41
|
+
*/
|
|
42
|
+
export const FILE_EVENT_COLOR = FILE_EVENT_COLOR_CATEGORICAL
|
|
43
|
+
|
|
44
|
+
/** Per-file activity mined from session transcripts. */
|
|
45
|
+
export interface FileActivity {
|
|
46
|
+
/** Repo-relative path. */
|
|
47
|
+
path: string
|
|
48
|
+
reads: number
|
|
49
|
+
writes: number
|
|
50
|
+
edits: number
|
|
51
|
+
/** Total events across reads + writes + edits. */
|
|
52
|
+
touches: number
|
|
53
|
+
/** Per-session net char delta, oldest first. Drives the sparkline. */
|
|
54
|
+
timeline: number[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface FileActivityRowProps {
|
|
58
|
+
file: FileActivity
|
|
59
|
+
/** Renders the selected treatment (one tone up from the list pane + leading accent bar). */
|
|
60
|
+
selected?: boolean
|
|
61
|
+
onSelect?: () => void
|
|
62
|
+
/** Override the read/write/edit fills. Defaults to {@link FILE_EVENT_COLOR}. */
|
|
63
|
+
eventColors?: FileEventColors
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function EventCount({ value, suffix, color }: { value: number; suffix: string; color: string }) {
|
|
67
|
+
return (
|
|
68
|
+
<Typography variant="mono" className="text-xs" style={{ color }}>
|
|
69
|
+
{`${value}${suffix}`}
|
|
70
|
+
</Typography>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* FileActivityRow — one file in the ranked "hottest files" list: its path, total
|
|
76
|
+
* touches, the read/write/edit split, and a sparkline of per-session growth.
|
|
77
|
+
*
|
|
78
|
+
* Composes {@link FilePathLabel} and {@link SparkBars}. Used by
|
|
79
|
+
* {@link FileHistoryExplorer}.
|
|
80
|
+
*/
|
|
81
|
+
export function FileActivityRow({
|
|
82
|
+
file,
|
|
83
|
+
selected = false,
|
|
84
|
+
onSelect,
|
|
85
|
+
eventColors = FILE_EVENT_COLOR,
|
|
86
|
+
}: FileActivityRowProps) {
|
|
87
|
+
return (
|
|
88
|
+
<Pressable
|
|
89
|
+
onPress={onSelect}
|
|
90
|
+
// Raw `role`/`aria-selected` rather than `accessibilityState={{ selected }}`:
|
|
91
|
+
// RNW silently drops the latter, so selection would never reach AT.
|
|
92
|
+
role="option"
|
|
93
|
+
aria-selected={selected}
|
|
94
|
+
accessibilityLabel={`${file.path}, ${file.touches} touches`}
|
|
95
|
+
testID="file-activity-row"
|
|
96
|
+
// The row lives inside the lifted list pane (surface-raised), so the selected
|
|
97
|
+
// fill steps one tone above it. Tone as a state cue; no lift.
|
|
98
|
+
className={`relative gap-1.5 rounded-md px-3 py-2 ${selected ? 'bg-surface-overlay' : ''}`}
|
|
99
|
+
>
|
|
100
|
+
{selected ? (
|
|
101
|
+
<View
|
|
102
|
+
testID="file-activity-row-accent"
|
|
103
|
+
className="absolute bottom-2 left-0 top-2 w-[3px] rounded-r-[3px] bg-brand-primary"
|
|
104
|
+
/>
|
|
105
|
+
) : null}
|
|
106
|
+
|
|
107
|
+
<View className="flex-row items-center justify-between gap-2.5">
|
|
108
|
+
<View className="shrink flex-row items-center">
|
|
109
|
+
<FilePathLabel path={file.path} />
|
|
110
|
+
</View>
|
|
111
|
+
<Typography variant="mono" className="text-xs font-bold text-text-secondary">
|
|
112
|
+
{String(file.touches)}
|
|
113
|
+
</Typography>
|
|
114
|
+
</View>
|
|
115
|
+
|
|
116
|
+
<View className="flex-row items-center justify-between gap-2.5">
|
|
117
|
+
<View className="flex-row items-center gap-2">
|
|
118
|
+
<EventCount value={file.reads} suffix="r" color={eventColors.reads} />
|
|
119
|
+
<EventCount value={file.writes} suffix="w" color={eventColors.writes} />
|
|
120
|
+
<EventCount value={file.edits} suffix="e" color={eventColors.edits} />
|
|
121
|
+
</View>
|
|
122
|
+
<SparkBars
|
|
123
|
+
values={file.timeline}
|
|
124
|
+
height={16}
|
|
125
|
+
label={`Per-session growth for ${file.path}`}
|
|
126
|
+
/>
|
|
127
|
+
</View>
|
|
128
|
+
</Pressable>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { Surface } from '../../ui/surface'
|
|
3
|
+
import { FileHistoryExplorer } from './FileHistoryExplorer'
|
|
4
|
+
import {
|
|
5
|
+
FILE_HISTORY_CO_EDGES,
|
|
6
|
+
FILE_HISTORY_FILES,
|
|
7
|
+
FILE_HISTORY_STATS,
|
|
8
|
+
} from './file-history-fixture'
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof FileHistoryExplorer> = {
|
|
11
|
+
title: 'Custom/ActiveWork/FileHistoryExplorer',
|
|
12
|
+
component: FileHistoryExplorer,
|
|
13
|
+
tags: ['autodocs', 'status:candidate', '!status:review'],
|
|
14
|
+
decorators: [
|
|
15
|
+
(Story) => (
|
|
16
|
+
<Surface level="base" className="min-h-screen p-6" testID="page-surface">
|
|
17
|
+
<Story />
|
|
18
|
+
</Surface>
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
parameters: {
|
|
22
|
+
layout: 'fullscreen',
|
|
23
|
+
docs: {
|
|
24
|
+
description: {
|
|
25
|
+
component:
|
|
26
|
+
'**Organism.** A file browser ranked by mined activity instead of alphabetised by name: ' +
|
|
27
|
+
'a KPI strip, a two-pane hottest-files list ⇄ detail, and the repo’s strongest ' +
|
|
28
|
+
'co-change pairs. The co-change view is the part a plain file tree cannot show. Composes ' +
|
|
29
|
+
'[Card](?path=/docs/components-molecules-card--docs), ' +
|
|
30
|
+
'[Tile](?path=/docs/components-atoms-tile--docs), ' +
|
|
31
|
+
'[Divider](?path=/docs/components-atoms-divider--docs), ' +
|
|
32
|
+
'[FileActivityRow](?path=/docs/custom-activework-fileactivityrow--docs), ' +
|
|
33
|
+
'[FileActivityDetail](?path=/docs/custom-activework-fileactivitydetail--docs), ' +
|
|
34
|
+
'[CoChangeChip](?path=/docs/custom-activework-cochangechip--docs), and ' +
|
|
35
|
+
'[Eyebrow](?path=/docs/components-molecules-eyebrow--docs). ' +
|
|
36
|
+
'Presentational only — the caller supplies every prop.',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
args: {
|
|
41
|
+
stats: FILE_HISTORY_STATS,
|
|
42
|
+
files: FILE_HISTORY_FILES,
|
|
43
|
+
coEdges: FILE_HISTORY_CO_EDGES,
|
|
44
|
+
provenance:
|
|
45
|
+
'deterministically mined from Claude Code session transcripts · ranked by total touches',
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
export default meta
|
|
49
|
+
type Story = StoryObj<typeof FileHistoryExplorer>
|
|
50
|
+
|
|
51
|
+
export const Default: Story = {}
|
|
52
|
+
|
|
53
|
+
/** Selection is internal by default — pressing a row moves the detail pane. */
|
|
54
|
+
export const NetShrinkSelected: Story = {
|
|
55
|
+
args: { selectedPath: 'src/utils/fs-atomic.ts' },
|
|
56
|
+
parameters: {
|
|
57
|
+
docs: {
|
|
58
|
+
description: {
|
|
59
|
+
story:
|
|
60
|
+
'A file that net-*shrank*: negative sparkline bars render in the error token and the ' +
|
|
61
|
+
'net-change readout flips colour.',
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** No co-change edges mined yet — the bottom strip drops out entirely. */
|
|
68
|
+
export const NoCoChanges: Story = {
|
|
69
|
+
args: { coEdges: [] },
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** A single file: the ranked list is still a list, and the detail pane fills. */
|
|
73
|
+
export const SingleFile: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
files: FILE_HISTORY_FILES.slice(3),
|
|
76
|
+
coEdges: [],
|
|
77
|
+
stats: [
|
|
78
|
+
{ label: 'Files', value: '1' },
|
|
79
|
+
{ label: 'File events', value: '55' },
|
|
80
|
+
{ label: 'Sessions', value: '8' },
|
|
81
|
+
{ label: 'Transcripts', value: '11' },
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
3
|
+
import { axe } from 'jest-axe'
|
|
4
|
+
import { FileHistoryExplorer } from './FileHistoryExplorer'
|
|
5
|
+
import {
|
|
6
|
+
FILE_HISTORY_CO_EDGES,
|
|
7
|
+
FILE_HISTORY_FILES,
|
|
8
|
+
FILE_HISTORY_STATS,
|
|
9
|
+
} from './file-history-fixture'
|
|
10
|
+
|
|
11
|
+
const base = {
|
|
12
|
+
stats: FILE_HISTORY_STATS,
|
|
13
|
+
files: FILE_HISTORY_FILES,
|
|
14
|
+
coEdges: FILE_HISTORY_CO_EDGES,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('FileHistoryExplorer', () => {
|
|
18
|
+
it('renders a KPI tile per stat', () => {
|
|
19
|
+
render(<FileHistoryExplorer {...base} />)
|
|
20
|
+
for (const s of FILE_HISTORY_STATS) {
|
|
21
|
+
// "Sessions" also appears in the detail pane's growth block, so match loosely.
|
|
22
|
+
expect(screen.getAllByText(s.label).length).toBeGreaterThan(0)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('renders the provenance caption only when supplied', () => {
|
|
27
|
+
const { rerender } = render(<FileHistoryExplorer {...base} />)
|
|
28
|
+
expect(screen.queryByText('mined deterministically')).not.toBeInTheDocument()
|
|
29
|
+
rerender(<FileHistoryExplorer {...base} provenance="mined deterministically" />)
|
|
30
|
+
expect(screen.getByText('mined deterministically')).toBeInTheDocument()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('renders a row per file, capped by maxRows', () => {
|
|
34
|
+
const { rerender } = render(<FileHistoryExplorer {...base} />)
|
|
35
|
+
expect(screen.getAllByTestId('file-activity-row')).toHaveLength(4)
|
|
36
|
+
rerender(<FileHistoryExplorer {...base} maxRows={2} />)
|
|
37
|
+
expect(screen.getAllByTestId('file-activity-row')).toHaveLength(2)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('selects the first file by default', () => {
|
|
41
|
+
render(<FileHistoryExplorer {...base} />)
|
|
42
|
+
const rows = screen.getAllByTestId('file-activity-row')
|
|
43
|
+
expect(rows[0]).toHaveAttribute('aria-selected', 'true')
|
|
44
|
+
expect(rows[1]).toHaveAttribute('aria-selected', 'false')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('moves the selection on press when uncontrolled', () => {
|
|
48
|
+
render(<FileHistoryExplorer {...base} />)
|
|
49
|
+
fireEvent.click(screen.getAllByTestId('file-activity-row')[1])
|
|
50
|
+
const rows = screen.getAllByTestId('file-activity-row')
|
|
51
|
+
expect(rows[0]).toHaveAttribute('aria-selected', 'false')
|
|
52
|
+
expect(rows[1]).toHaveAttribute('aria-selected', 'true')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('honours selectedPath and does not self-update when controlled', () => {
|
|
56
|
+
const onSelectFile = vi.fn()
|
|
57
|
+
render(
|
|
58
|
+
<FileHistoryExplorer
|
|
59
|
+
{...base}
|
|
60
|
+
selectedPath="src/utils/fs-atomic.ts"
|
|
61
|
+
onSelectFile={onSelectFile}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
expect(screen.getAllByTestId('file-activity-row')[2]).toHaveAttribute('aria-selected', 'true')
|
|
65
|
+
|
|
66
|
+
fireEvent.click(screen.getAllByTestId('file-activity-row')[0])
|
|
67
|
+
expect(onSelectFile).toHaveBeenCalledWith('src/commands/open.ts')
|
|
68
|
+
expect(screen.getAllByTestId('file-activity-row')[2]).toHaveAttribute('aria-selected', 'true')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('falls back to the first file when selectedPath matches nothing', () => {
|
|
72
|
+
render(<FileHistoryExplorer {...base} selectedPath="does/not/exist.ts" />)
|
|
73
|
+
expect(screen.getAllByTestId('file-activity-row')[0]).toHaveAttribute('aria-selected', 'true')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('renders a co-change chip per edge, capped by maxCoEdges', () => {
|
|
77
|
+
const { rerender } = render(<FileHistoryExplorer {...base} />)
|
|
78
|
+
expect(screen.getAllByTestId('co-change-chip')).toHaveLength(4)
|
|
79
|
+
rerender(<FileHistoryExplorer {...base} maxCoEdges={2} />)
|
|
80
|
+
expect(screen.getAllByTestId('co-change-chip')).toHaveLength(2)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('drops the co-change strip entirely when there are no edges', () => {
|
|
84
|
+
render(<FileHistoryExplorer {...base} coEdges={[]} />)
|
|
85
|
+
expect(screen.queryByTestId('co-change-chip')).not.toBeInTheDocument()
|
|
86
|
+
expect(screen.queryByText('Strongest co-changes across the repo')).not.toBeInTheDocument()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('renders no detail pane when there are no files', () => {
|
|
90
|
+
render(<FileHistoryExplorer {...base} files={[]} coEdges={[]} />)
|
|
91
|
+
expect(screen.queryByTestId('file-activity-detail')).not.toBeInTheDocument()
|
|
92
|
+
expect(screen.getByTestId('file-history-explorer')).toBeInTheDocument()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('has no a11y violations', async () => {
|
|
96
|
+
const { container } = render(<FileHistoryExplorer {...base} />)
|
|
97
|
+
expect(await axe(container)).toHaveNoViolations()
|
|
98
|
+
})
|
|
99
|
+
})
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
import { View, type ViewProps } from 'react-native'
|
|
4
|
+
import { Card } from '../../ui/card'
|
|
5
|
+
import { Divider } from '../../ui/divider'
|
|
6
|
+
import { Tile } from '../../ui/tile'
|
|
7
|
+
import { Typography } from '../Typography'
|
|
8
|
+
import { Eyebrow } from './Eyebrow'
|
|
9
|
+
import { CoChangeChip } from './CoChangeChip'
|
|
10
|
+
import { FileActivityRow } from './FileActivityRow'
|
|
11
|
+
import { FileActivityDetail, type FileActivityDetailData } from './FileActivityDetail'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* React Native's `Role` union has `'option'` but omits `'listbox'`, even though
|
|
15
|
+
* RNW passes it straight through to the DOM. Cast once here rather than drop
|
|
16
|
+
* the ARIA parent that makes the option rows valid.
|
|
17
|
+
*/
|
|
18
|
+
const LISTBOX_ROLE = 'listbox' as ViewProps['role']
|
|
19
|
+
|
|
20
|
+
/** A KPI shown in the strip above the explorer. */
|
|
21
|
+
export interface FileHistoryStat {
|
|
22
|
+
label: string
|
|
23
|
+
value: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** A repo-wide co-change pair, strongest first. */
|
|
27
|
+
export interface CoChangeEdge {
|
|
28
|
+
a: string
|
|
29
|
+
b: string
|
|
30
|
+
count: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface FileHistoryExplorerProps extends ViewProps {
|
|
34
|
+
/** KPI tiles, e.g. Files / File events / Sessions / Transcripts. */
|
|
35
|
+
stats: FileHistoryStat[]
|
|
36
|
+
/** Files for the ranked list, already sorted (typically by descending touches). */
|
|
37
|
+
files: FileActivityDetailData[]
|
|
38
|
+
/** Repo-wide co-change pairs, already sorted by descending count. */
|
|
39
|
+
coEdges?: CoChangeEdge[]
|
|
40
|
+
/** Caption under the KPI strip explaining where the numbers came from. */
|
|
41
|
+
provenance?: string
|
|
42
|
+
/** Cap on ranked rows rendered. */
|
|
43
|
+
maxRows?: number
|
|
44
|
+
/** Cap on co-change chips rendered. */
|
|
45
|
+
maxCoEdges?: number
|
|
46
|
+
/** Selected file path. Omit to let the explorer manage selection itself. */
|
|
47
|
+
selectedPath?: string
|
|
48
|
+
/** Fires on row press. Required for the selection to move when `selectedPath` is set. */
|
|
49
|
+
onSelectFile?: (path: string) => void
|
|
50
|
+
className?: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* FileHistoryExplorer — a file browser ranked by mined activity instead of
|
|
55
|
+
* alphabetised by name: a KPI strip, a two-pane hottest-files list ⇄ detail,
|
|
56
|
+
* and the repo's strongest co-change pairs.
|
|
57
|
+
*
|
|
58
|
+
* Composes Card / Tile / Divider plus {@link FileActivityRow},
|
|
59
|
+
* {@link FileActivityDetail}, {@link CoChangeChip} and {@link Eyebrow}.
|
|
60
|
+
* Selection is controlled when `selectedPath` is supplied and internal
|
|
61
|
+
* otherwise.
|
|
62
|
+
*
|
|
63
|
+
* Data plan: presentational only — no fetch or store dependency. The caller
|
|
64
|
+
* derives `stats`, `files` and `coEdges` from its own source of truth (the
|
|
65
|
+
* active-work session-history miner). Wiring that export to these props is a
|
|
66
|
+
* caller-side concern and the integration's only open gap; a shared adapter is
|
|
67
|
+
* deliberately out of scope for this unit.
|
|
68
|
+
*/
|
|
69
|
+
export function FileHistoryExplorer({
|
|
70
|
+
stats,
|
|
71
|
+
files,
|
|
72
|
+
coEdges = [],
|
|
73
|
+
provenance,
|
|
74
|
+
maxRows = 30,
|
|
75
|
+
maxCoEdges = 8,
|
|
76
|
+
selectedPath,
|
|
77
|
+
onSelectFile,
|
|
78
|
+
className,
|
|
79
|
+
...props
|
|
80
|
+
}: FileHistoryExplorerProps) {
|
|
81
|
+
const [internalPath, setInternalPath] = useState<string | undefined>(files[0]?.path)
|
|
82
|
+
const activePath = selectedPath ?? internalPath
|
|
83
|
+
const selected = files.find((f) => f.path === activePath) ?? files[0]
|
|
84
|
+
|
|
85
|
+
const select = (path: string) => {
|
|
86
|
+
if (selectedPath === undefined) setInternalPath(path)
|
|
87
|
+
onSelectFile?.(path)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<View className={`gap-3.5 ${className ?? ''}`} testID="file-history-explorer" {...props}>
|
|
92
|
+
<View className="gap-1.5">
|
|
93
|
+
<View className="flex-row flex-wrap gap-2.5">
|
|
94
|
+
{stats.map((s) => (
|
|
95
|
+
<Tile key={s.label} label={s.label} value={s.value} className="min-w-[130px]" />
|
|
96
|
+
))}
|
|
97
|
+
</View>
|
|
98
|
+
{provenance ? (
|
|
99
|
+
<Typography variant="caption" className="text-xs text-text-tertiary">
|
|
100
|
+
{provenance}
|
|
101
|
+
</Typography>
|
|
102
|
+
) : null}
|
|
103
|
+
</View>
|
|
104
|
+
|
|
105
|
+
<View className="flex-row gap-3.5">
|
|
106
|
+
<Card className="w-[420px] p-2" testID="file-list-pane">
|
|
107
|
+
<View className="px-2.5 pb-1.5 pt-1">
|
|
108
|
+
<Eyebrow>Hottest files</Eyebrow>
|
|
109
|
+
</View>
|
|
110
|
+
<Divider />
|
|
111
|
+
<View className="pt-1" role={LISTBOX_ROLE} aria-label="Hottest files">
|
|
112
|
+
{files.slice(0, maxRows).map((f) => (
|
|
113
|
+
<FileActivityRow
|
|
114
|
+
key={f.path}
|
|
115
|
+
file={f}
|
|
116
|
+
selected={f.path === selected?.path}
|
|
117
|
+
onSelect={() => select(f.path)}
|
|
118
|
+
/>
|
|
119
|
+
))}
|
|
120
|
+
</View>
|
|
121
|
+
</Card>
|
|
122
|
+
|
|
123
|
+
{selected ? <FileActivityDetail file={selected} /> : null}
|
|
124
|
+
</View>
|
|
125
|
+
|
|
126
|
+
{coEdges.length ? (
|
|
127
|
+
<View className="gap-2">
|
|
128
|
+
<Eyebrow>Strongest co-changes across the repo</Eyebrow>
|
|
129
|
+
<View className="flex-row flex-wrap gap-2">
|
|
130
|
+
{coEdges.slice(0, maxCoEdges).map((e) => (
|
|
131
|
+
<CoChangeChip key={`${e.a}|${e.b}`} a={e.a} b={e.b} count={e.count} />
|
|
132
|
+
))}
|
|
133
|
+
</View>
|
|
134
|
+
</View>
|
|
135
|
+
) : null}
|
|
136
|
+
</View>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { FilePathLabel } from './FilePathLabel'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof FilePathLabel> = {
|
|
5
|
+
title: 'Custom/ActiveWork/FilePathLabel',
|
|
6
|
+
component: FilePathLabel,
|
|
7
|
+
tags: ['autodocs', 'status:candidate', '!status:review'],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'**Molecule.** A file path with the directory dimmed and the basename bright — in a list ' +
|
|
13
|
+
'of paths the basename is the identifier and the directory is disambiguation, so they get ' +
|
|
14
|
+
'different weight rather than one flat string. Composes ' +
|
|
15
|
+
"[Typography](?path=/docs/foundations-typography--docs)'s `mono` variant.",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
args: { path: 'src/commands/_open-helpers.ts', size: 'md', baseOnly: false },
|
|
20
|
+
}
|
|
21
|
+
export default meta
|
|
22
|
+
type Story = StoryObj<typeof FilePathLabel>
|
|
23
|
+
|
|
24
|
+
export const Default: Story = {}
|
|
25
|
+
|
|
26
|
+
/** A bare filename has no directory to dim. */
|
|
27
|
+
export const NoDirectory: Story = {
|
|
28
|
+
args: { path: 'README.md' },
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** `baseOnly` drops the directory — used at chip size where the prefix is noise. */
|
|
32
|
+
export const BaseOnly: Story = {
|
|
33
|
+
args: { baseOnly: true },
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The dense variant, as used inside CoChangeChip and the co-change list. */
|
|
37
|
+
export const Small: Story = {
|
|
38
|
+
args: { size: 'sm' },
|
|
39
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import { axe } from 'jest-axe'
|
|
4
|
+
import { FilePathLabel, splitPath } from './FilePathLabel'
|
|
5
|
+
|
|
6
|
+
describe('splitPath', () => {
|
|
7
|
+
it('splits a nested path into a trailing-slash dir and a basename', () => {
|
|
8
|
+
expect(splitPath('src/commands/open.ts')).toEqual({
|
|
9
|
+
dir: 'src/commands/',
|
|
10
|
+
base: 'open.ts',
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
it('returns an empty dir for a bare filename', () => {
|
|
15
|
+
expect(splitPath('README.md')).toEqual({ dir: '', base: 'README.md' })
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe('FilePathLabel', () => {
|
|
20
|
+
it('renders the directory and the basename as separate elements', () => {
|
|
21
|
+
render(<FilePathLabel path="src/commands/open.ts" />)
|
|
22
|
+
expect(screen.getByText('src/commands/')).toBeInTheDocument()
|
|
23
|
+
expect(screen.getByText('open.ts')).toBeInTheDocument()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('omits the directory element for a bare filename', () => {
|
|
27
|
+
render(<FilePathLabel path="README.md" />)
|
|
28
|
+
expect(screen.getByText('README.md')).toBeInTheDocument()
|
|
29
|
+
expect(screen.queryByText('/')).not.toBeInTheDocument()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('drops the directory when baseOnly is set', () => {
|
|
33
|
+
render(<FilePathLabel path="src/commands/open.ts" baseOnly />)
|
|
34
|
+
expect(screen.queryByText('src/commands/')).not.toBeInTheDocument()
|
|
35
|
+
expect(screen.getByText('open.ts')).toBeInTheDocument()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// The dir/base size difference now comes from `text-xs` / `text-sm` classes, and
|
|
39
|
+
// nativewind does not compile classNames in the vitest env — so the rendered size
|
|
40
|
+
// is not observable here. Asserting it would mean asserting nothing. Left to
|
|
41
|
+
// visual regression (see the family README's testing follow-up); what remains
|
|
42
|
+
// testable is that both sizes render their parts.
|
|
43
|
+
it.each(['sm', 'md'] as const)('renders both parts at size %s', (size) => {
|
|
44
|
+
render(<FilePathLabel path="src/open.ts" size={size} />)
|
|
45
|
+
expect(screen.getByText('src/')).toBeInTheDocument()
|
|
46
|
+
expect(screen.getByText('open.ts')).toBeInTheDocument()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('has no a11y violations', async () => {
|
|
50
|
+
const { container } = render(<FilePathLabel path="src/commands/open.ts" />)
|
|
51
|
+
expect(await axe(container)).toHaveNoViolations()
|
|
52
|
+
})
|
|
53
|
+
})
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
|
+
import { View, type ViewProps } from 'react-native'
|
|
3
|
+
import { cn } from '../../../utils/cn'
|
|
4
|
+
import { Typography } from '../Typography'
|
|
5
|
+
|
|
6
|
+
/** Split a path into its directory prefix (trailing slash kept) and basename. */
|
|
7
|
+
export function splitPath(path: string): { dir: string; base: string } {
|
|
8
|
+
const i = path.lastIndexOf('/')
|
|
9
|
+
return i === -1 ? { dir: '', base: path } : { dir: path.slice(0, i + 1), base: path.slice(i + 1) }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Basename size on the type scale, with the directory one step quieter. */
|
|
13
|
+
export type FilePathLabelSize = 'sm' | 'md'
|
|
14
|
+
|
|
15
|
+
const SIZE_CLASS: Record<FilePathLabelSize, { base: string; dir: string }> = {
|
|
16
|
+
sm: { base: 'text-xs', dir: 'text-xs' },
|
|
17
|
+
md: { base: 'text-sm', dir: 'text-xs' },
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface FilePathLabelProps extends ViewProps {
|
|
21
|
+
/** A repo-relative path, e.g. `src/commands/open.ts`. */
|
|
22
|
+
path: string
|
|
23
|
+
/** `md` for standalone rows, `sm` for dense contexts like chips. */
|
|
24
|
+
size?: FilePathLabelSize
|
|
25
|
+
/** Render only the basename, dropping the directory prefix. */
|
|
26
|
+
baseOnly?: boolean
|
|
27
|
+
className?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* FilePathLabel — a file path with the directory dimmed and the basename bright.
|
|
32
|
+
*
|
|
33
|
+
* In a list of paths the basename is the identifier and the directory is
|
|
34
|
+
* disambiguation, so they get different weight rather than one flat string. The
|
|
35
|
+
* directory shrinks first under width pressure; the basename never truncates.
|
|
36
|
+
*/
|
|
37
|
+
export function FilePathLabel({
|
|
38
|
+
path,
|
|
39
|
+
size = 'md',
|
|
40
|
+
baseOnly = false,
|
|
41
|
+
className,
|
|
42
|
+
...props
|
|
43
|
+
}: FilePathLabelProps) {
|
|
44
|
+
const { dir, base } = splitPath(path)
|
|
45
|
+
const cls = SIZE_CLASS[size]
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<View className={cn('flex-row items-center', className)} {...props}>
|
|
49
|
+
{dir && !baseOnly ? (
|
|
50
|
+
<Typography
|
|
51
|
+
variant="mono"
|
|
52
|
+
numberOfLines={1}
|
|
53
|
+
className={cn('shrink text-text-tertiary', cls.dir)}
|
|
54
|
+
>
|
|
55
|
+
{dir}
|
|
56
|
+
</Typography>
|
|
57
|
+
) : null}
|
|
58
|
+
<Typography variant="mono" className={cn('text-text-primary', cls.base)}>
|
|
59
|
+
{base}
|
|
60
|
+
</Typography>
|
|
61
|
+
</View>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { Card } from '../../ui/card'
|
|
3
|
+
import { Surface } from '../../ui/surface'
|
|
4
|
+
import { InitiativeBrief } from './InitiativeBrief'
|
|
5
|
+
import { sessionLinkers } from './session-linkers'
|
|
6
|
+
import { INITIATIVE_BRIEF_FIXTURE } from './initiative-fixture'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* **InitiativeBrief** — a brief's prose, each `##` section a collapsible block
|
|
10
|
+
* with the first open, references auto-linked.
|
|
11
|
+
*
|
|
12
|
+
* Composes `Collapse` · `Eyebrow` · `MarkdownProse` · `Typography`.
|
|
13
|
+
*/
|
|
14
|
+
const meta: Meta<typeof InitiativeBrief> = {
|
|
15
|
+
title: 'Custom/ActiveWork/InitiativeBrief',
|
|
16
|
+
component: InitiativeBrief,
|
|
17
|
+
tags: ['autodocs', 'status:candidate', '!status:review'],
|
|
18
|
+
args: {
|
|
19
|
+
brief: INITIATIVE_BRIEF_FIXTURE,
|
|
20
|
+
linkers: sessionLinkers(),
|
|
21
|
+
},
|
|
22
|
+
argTypes: {
|
|
23
|
+
brief: { table: { disable: true } },
|
|
24
|
+
linkers: { table: { disable: true } },
|
|
25
|
+
},
|
|
26
|
+
decorators: [
|
|
27
|
+
(Story) => (
|
|
28
|
+
<Surface level="base" className="min-h-screen w-full max-w-[560px] p-6" testID="page-surface">
|
|
29
|
+
<Card className="gap-1 p-4">
|
|
30
|
+
<Story />
|
|
31
|
+
</Card>
|
|
32
|
+
</Surface>
|
|
33
|
+
),
|
|
34
|
+
],
|
|
35
|
+
parameters: {
|
|
36
|
+
layout: 'fullscreen',
|
|
37
|
+
docs: {
|
|
38
|
+
description: {
|
|
39
|
+
component:
|
|
40
|
+
'Composes **Collapse** · **Eyebrow** · **MarkdownProse** · **Typography**. Used-by ↑ the Initiative Reader composition.',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
export default meta
|
|
46
|
+
|
|
47
|
+
type Story = StoryObj<typeof InitiativeBrief>
|
|
48
|
+
|
|
49
|
+
/** The active-work brief, its sections collapsible. */
|
|
50
|
+
export const Default: Story = {}
|