@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
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import React, { useMemo, useState } from 'react'
|
|
2
|
-
import { View, Text, Pressable, type ViewProps } from 'react-native'
|
|
2
|
+
import { View, Text, Pressable, type ViewProps, type ViewStyle } from 'react-native'
|
|
3
3
|
import { cn } from '../../../utils/cn'
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
getValidatedElevation,
|
|
9
|
-
type ElevationLevel
|
|
10
|
-
} from '../../../theme'
|
|
11
|
-
import { useTheme } from '../../../utils/useTheme'
|
|
4
|
+
import { liftStyle, type LiftStep } from '../../../theme/lift'
|
|
5
|
+
import { Surface } from '../surface/Surface'
|
|
6
|
+
import { SurfaceContext, type SurfaceContextValue } from '../surface/SurfaceContext'
|
|
7
|
+
import { useResolvedSurface } from '../surface/resolveSurface'
|
|
12
8
|
|
|
13
9
|
export type CardVariant = 'elevated' | 'outline' | 'filled' | 'accent' | 'subtle'
|
|
14
|
-
|
|
10
|
+
/** Planes to lift above the enclosing Surface. */
|
|
11
|
+
export type CardElevation = 1 | 2 | 3
|
|
15
12
|
|
|
16
13
|
export interface CardProps extends ViewProps {
|
|
17
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* How the card separates from its host:
|
|
16
|
+
* - `elevated` (default): lifts `elevation` planes and wears the lift (rim + shadow).
|
|
17
|
+
* - `accent`: as `elevated`, plus a left stripe.
|
|
18
|
+
* - `filled`: lifts `elevation` planes, tone only — for tiles nested in a lifted card.
|
|
19
|
+
* - `outline`: stays on the host plane with a hairline-strong edge — status borders.
|
|
20
|
+
* - `subtle`: stays on the host plane with a hairline-subtle edge.
|
|
21
|
+
*/
|
|
18
22
|
variant?: CardVariant
|
|
19
|
-
/**
|
|
23
|
+
/** Planes to lift above the enclosing Surface (default 2: page → the card plane). */
|
|
20
24
|
elevation?: CardElevation
|
|
21
25
|
/** Whether the card is interactive (hoverable/pressable) */
|
|
22
26
|
isInteractive?: boolean
|
|
@@ -26,7 +30,10 @@ export interface CardProps extends ViewProps {
|
|
|
26
30
|
onPress?: () => void
|
|
27
31
|
/** Custom border color (hex, rgb, or CSS color). Useful for status cards. */
|
|
28
32
|
borderColor?: string
|
|
29
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Custom background color. The one way to override the plane: a `bg-*`
|
|
35
|
+
* className is discarded because the plane is written into `style`.
|
|
36
|
+
*/
|
|
30
37
|
bgColor?: string
|
|
31
38
|
/** Accent stripe color for accent variant (CSS color or hex) */
|
|
32
39
|
accentColor?: string
|
|
@@ -43,16 +50,51 @@ export interface CardProps extends ViewProps {
|
|
|
43
50
|
skeletonContentLines?: number
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
const
|
|
47
|
-
elevated: '',
|
|
48
|
-
|
|
49
|
-
filled: '',
|
|
50
|
-
|
|
53
|
+
const EDGE_CLASS: Record<CardVariant, string> = {
|
|
54
|
+
elevated: '',
|
|
55
|
+
accent: '',
|
|
56
|
+
filled: '',
|
|
57
|
+
outline: 'border border-hairline-strong',
|
|
51
58
|
subtle: 'border border-hairline-subtle',
|
|
52
59
|
}
|
|
53
60
|
|
|
61
|
+
const LIFTED: Record<CardVariant, boolean> = {
|
|
62
|
+
elevated: true,
|
|
63
|
+
accent: true,
|
|
64
|
+
filled: false,
|
|
65
|
+
outline: false,
|
|
66
|
+
subtle: false,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const STAYS_ON_HOST: Record<CardVariant, boolean> = {
|
|
70
|
+
elevated: false,
|
|
71
|
+
accent: false,
|
|
72
|
+
filled: false,
|
|
73
|
+
outline: true,
|
|
74
|
+
subtle: true,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** The card's plane and treatment, hover lifting one more plane when clickable. */
|
|
78
|
+
function useCardDepth(variant: CardVariant, elevation: CardElevation, hovered: boolean) {
|
|
79
|
+
const raise = STAYS_ON_HOST[variant] ? undefined : elevation
|
|
80
|
+
const resolved = useResolvedSurface({ raise, lift: LIFTED[variant] })
|
|
81
|
+
const depthStyle = useMemo(() => {
|
|
82
|
+
if (!hovered || !LIFTED[variant]) return resolved.depthStyle
|
|
83
|
+
const hoverStep = Math.min(3, resolved.step + 1) as LiftStep
|
|
84
|
+
return liftStyle(hoverStep, resolved.mode)
|
|
85
|
+
}, [hovered, variant, resolved])
|
|
86
|
+
return { ...resolved, depthStyle }
|
|
87
|
+
}
|
|
88
|
+
|
|
54
89
|
/**
|
|
55
|
-
* Card component for containing related content.
|
|
90
|
+
* Card component for containing related content. Sits `elevation` planes above
|
|
91
|
+
* the enclosing Surface and publishes its own plane, so a card nested in a card
|
|
92
|
+
* steps up again (and clamps at the top of the ramp).
|
|
93
|
+
*
|
|
94
|
+
* Lift sparingly: a card lifts off the page, but a small card lifted off a
|
|
95
|
+
* small card reads as clutter. Inside a card, organise with `CardInset`, a
|
|
96
|
+
* `filled` tile, or a divider, and keep a second lift for something that
|
|
97
|
+
* genuinely floats over the first.
|
|
56
98
|
*
|
|
57
99
|
* @example
|
|
58
100
|
* <Card>
|
|
@@ -63,14 +105,6 @@ const variantStyles: Record<CardVariant, string> = {
|
|
|
63
105
|
* <CardContent>
|
|
64
106
|
* <Text>Card content goes here</Text>
|
|
65
107
|
* </CardContent>
|
|
66
|
-
* <CardFooter>
|
|
67
|
-
* <Button>Action</Button>
|
|
68
|
-
* </CardFooter>
|
|
69
|
-
* </Card>
|
|
70
|
-
*
|
|
71
|
-
* // Interactive card
|
|
72
|
-
* <Card isInteractive onPress={() => console.log('pressed')}>
|
|
73
|
-
* <CardContent>Click me</CardContent>
|
|
74
108
|
* </Card>
|
|
75
109
|
*/
|
|
76
110
|
export function Card({
|
|
@@ -93,131 +127,67 @@ export function Card({
|
|
|
93
127
|
}: CardProps) {
|
|
94
128
|
const isClickable = isInteractive || !!onPress
|
|
95
129
|
const [isHovered, setIsHovered] = useState(false)
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
// Get elevation level (validate and clamp to card's allowed range)
|
|
99
|
-
const elevationLevel = useMemo(() => {
|
|
100
|
-
const validated = getValidatedElevation('card', elevation as ElevationLevel)
|
|
101
|
-
// Map variant to elevation if needed
|
|
102
|
-
if (variant === 'outline' || variant === 'accent' || variant === 'subtle') {
|
|
103
|
-
return 1 as ElevationLevel // These border variants use subtle elevation
|
|
104
|
-
}
|
|
105
|
-
return validated
|
|
106
|
-
}, [variant, elevation])
|
|
107
|
-
|
|
108
|
-
// Get base surface color for theme
|
|
109
|
-
const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme])
|
|
110
|
-
|
|
111
|
-
// Calculate surface color and shadow from elevation
|
|
112
|
-
const surfaceColor = useMemo(() => {
|
|
113
|
-
// Outline variant in light mode uses a specific off-white for clear visibility
|
|
114
|
-
if ((variant === 'outline' || variant === 'accent') && theme === 'light') {
|
|
115
|
-
return '#FAFAFA' // Matches --color-surface-elevated in light mode
|
|
116
|
-
}
|
|
117
|
-
// Subtle variant uses the base surface color without elevation lift
|
|
118
|
-
if (variant === 'subtle') {
|
|
119
|
-
return getElevationSurface(baseColor, 0 as ElevationLevel, theme)
|
|
120
|
-
}
|
|
121
|
-
return getElevationSurface(baseColor, elevationLevel, theme)
|
|
122
|
-
}, [baseColor, elevationLevel, theme, variant])
|
|
123
|
-
|
|
124
|
-
const shadowStyle = useMemo(() => {
|
|
125
|
-
// Only apply hover shadow if card is actually clickable
|
|
126
|
-
const shouldHover = isHovered && isClickable
|
|
127
|
-
return getElevationShadow(baseColor, elevationLevel, theme, shouldHover)
|
|
128
|
-
}, [baseColor, elevationLevel, theme, isHovered, isClickable])
|
|
129
|
-
|
|
130
|
-
// Render skeleton content when loading, otherwise render children
|
|
131
|
-
const cardContent = isLoading ? (
|
|
132
|
-
<>
|
|
133
|
-
{skeletonHasHeader && (
|
|
134
|
-
<CardHeader>
|
|
135
|
-
<View className="h-5 w-1/3 bg-interactive-disabled rounded" />
|
|
136
|
-
<View className="mt-2 h-4 w-2/3 bg-interactive-disabled rounded" />
|
|
137
|
-
</CardHeader>
|
|
138
|
-
)}
|
|
139
|
-
<CardContent>
|
|
140
|
-
{Array.from({ length: skeletonContentLines }).map((_, i) => (
|
|
141
|
-
<View
|
|
142
|
-
key={i}
|
|
143
|
-
className={cn(
|
|
144
|
-
'h-4 bg-interactive-disabled rounded',
|
|
145
|
-
i < skeletonContentLines - 1 ? 'mb-2 w-full' : 'w-4/5'
|
|
146
|
-
)}
|
|
147
|
-
/>
|
|
148
|
-
))}
|
|
149
|
-
</CardContent>
|
|
150
|
-
{skeletonHasFooter && (
|
|
151
|
-
<CardFooter>
|
|
152
|
-
<View className="h-9 w-24 bg-interactive-disabled rounded" />
|
|
153
|
-
</CardFooter>
|
|
154
|
-
)}
|
|
155
|
-
</>
|
|
156
|
-
) : (
|
|
157
|
-
children
|
|
158
|
-
)
|
|
130
|
+
const depth = useCardDepth(variant, elevation, isHovered && isClickable)
|
|
159
131
|
|
|
160
132
|
const baseClassName = cn(
|
|
161
133
|
'rounded-lg overflow-hidden relative',
|
|
162
|
-
|
|
163
|
-
variant === 'outline'
|
|
164
|
-
? borderColor
|
|
165
|
-
? 'border-2' // Just the border width, color via style
|
|
166
|
-
: variantStyles[variant] // Full variant styles including color
|
|
167
|
-
: variantStyles[variant],
|
|
168
|
-
// Remove Tailwind shadow classes - we're using elevation shadows via style prop
|
|
134
|
+
borderColor ? 'border' : EDGE_CLASS[variant],
|
|
169
135
|
isClickable && 'web:cursor-pointer web:transition-all web:duration-150',
|
|
170
136
|
isClickable && 'web:hover:-translate-y-0.5 active:scale-[0.99]',
|
|
171
137
|
isLoading && 'pointer-events-none animate-pulse',
|
|
172
138
|
className
|
|
173
139
|
)
|
|
174
140
|
|
|
175
|
-
// Accent variant: left stripe via borderLeft override
|
|
176
|
-
const accentStyle = useMemo(() => variant === 'accent' ? {
|
|
177
|
-
borderLeftWidth: accentWidth ?? 3,
|
|
178
|
-
borderLeftColor: accentColor ?? 'var(--color-brand-primary)',
|
|
179
|
-
} : {}, [variant, accentWidth, accentColor])
|
|
180
|
-
|
|
181
|
-
// Merge styles: background color from elevation + shadow style + custom colors + custom style
|
|
182
141
|
const mergedStyle = useMemo(() => {
|
|
183
|
-
const
|
|
184
|
-
backgroundColor: bgColor ||
|
|
142
|
+
const own: ViewStyle & Record<string, unknown> = {
|
|
143
|
+
backgroundColor: bgColor || depth.backgroundColor,
|
|
185
144
|
borderRadius: 8,
|
|
186
|
-
overflow: 'hidden'
|
|
187
|
-
...
|
|
188
|
-
...accentStyle,
|
|
145
|
+
overflow: 'hidden',
|
|
146
|
+
...depth.depthStyle,
|
|
189
147
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
elevationStyle.borderColor = borderColor
|
|
148
|
+
if (variant === 'accent') {
|
|
149
|
+
own.borderLeftWidth = accentWidth ?? 3
|
|
150
|
+
own.borderLeftColor = accentColor ?? 'var(--color-brand-primary)'
|
|
194
151
|
}
|
|
152
|
+
if (borderColor) own.borderColor = borderColor
|
|
153
|
+
return style ? [own, style] : own
|
|
154
|
+
}, [style, depth, bgColor, borderColor, variant, accentWidth, accentColor])
|
|
195
155
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
156
|
+
const context = useMemo<SurfaceContextValue>(
|
|
157
|
+
() => ({ mode: depth.mode, level: depth.plane }),
|
|
158
|
+
[depth.mode, depth.plane]
|
|
159
|
+
)
|
|
200
160
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
{...props}
|
|
211
|
-
>
|
|
212
|
-
{cardContent}
|
|
213
|
-
</Pressable>
|
|
214
|
-
)
|
|
215
|
-
}
|
|
161
|
+
const content = isLoading ? (
|
|
162
|
+
<SkeletonBody
|
|
163
|
+
hasHeader={skeletonHasHeader}
|
|
164
|
+
hasFooter={skeletonHasFooter}
|
|
165
|
+
contentLines={skeletonContentLines}
|
|
166
|
+
/>
|
|
167
|
+
) : (
|
|
168
|
+
children
|
|
169
|
+
)
|
|
216
170
|
|
|
217
171
|
return (
|
|
218
|
-
<
|
|
219
|
-
{
|
|
220
|
-
|
|
172
|
+
<SurfaceContext.Provider value={context}>
|
|
173
|
+
{isClickable ? (
|
|
174
|
+
<Pressable
|
|
175
|
+
onPress={onPress}
|
|
176
|
+
onHoverIn={() => setIsHovered(true)}
|
|
177
|
+
onHoverOut={() => setIsHovered(false)}
|
|
178
|
+
accessibilityRole="button"
|
|
179
|
+
className={baseClassName}
|
|
180
|
+
style={mergedStyle}
|
|
181
|
+
{...props}
|
|
182
|
+
>
|
|
183
|
+
{content}
|
|
184
|
+
</Pressable>
|
|
185
|
+
) : (
|
|
186
|
+
<View className={baseClassName} style={mergedStyle} {...props}>
|
|
187
|
+
{content}
|
|
188
|
+
</View>
|
|
189
|
+
)}
|
|
190
|
+
</SurfaceContext.Provider>
|
|
221
191
|
)
|
|
222
192
|
}
|
|
223
193
|
|
|
@@ -230,11 +200,7 @@ export interface CardHeaderProps {
|
|
|
230
200
|
* Header section of a Card.
|
|
231
201
|
*/
|
|
232
202
|
export function CardHeader({ children, className }: CardHeaderProps) {
|
|
233
|
-
return (
|
|
234
|
-
<View className={cn('px-6 py-6', className)}>
|
|
235
|
-
{children}
|
|
236
|
-
</View>
|
|
237
|
-
)
|
|
203
|
+
return <View className={cn('px-6 py-6', className)}>{children}</View>
|
|
238
204
|
}
|
|
239
205
|
|
|
240
206
|
export interface CardTitleProps {
|
|
@@ -265,11 +231,7 @@ export interface CardDescriptionProps {
|
|
|
265
231
|
* Description for CardHeader.
|
|
266
232
|
*/
|
|
267
233
|
export function CardDescription({ children, className }: CardDescriptionProps) {
|
|
268
|
-
return (
|
|
269
|
-
<Text className={cn('mt-1.5 text-sm text-text-secondary', className)}>
|
|
270
|
-
{children}
|
|
271
|
-
</Text>
|
|
272
|
-
)
|
|
234
|
+
return <Text className={cn('mt-1.5 text-sm text-text-secondary', className)}>{children}</Text>
|
|
273
235
|
}
|
|
274
236
|
|
|
275
237
|
export interface CardContentProps {
|
|
@@ -281,11 +243,7 @@ export interface CardContentProps {
|
|
|
281
243
|
* Content section of a Card.
|
|
282
244
|
*/
|
|
283
245
|
export function CardContent({ children, className }: CardContentProps) {
|
|
284
|
-
return (
|
|
285
|
-
<View className={cn('px-6 py-4', className)}>
|
|
286
|
-
{children}
|
|
287
|
-
</View>
|
|
288
|
-
)
|
|
246
|
+
return <View className={cn('px-6 py-4', className)}>{children}</View>
|
|
289
247
|
}
|
|
290
248
|
|
|
291
249
|
export interface CardFooterProps {
|
|
@@ -297,35 +255,18 @@ export interface CardFooterProps {
|
|
|
297
255
|
* Footer section of a Card.
|
|
298
256
|
*/
|
|
299
257
|
export function CardFooter({ children, className }: CardFooterProps) {
|
|
300
|
-
return (
|
|
301
|
-
<View className={cn('px-6 py-4 flex-row items-center gap-2', className)}>
|
|
302
|
-
{children}
|
|
303
|
-
</View>
|
|
304
|
-
)
|
|
258
|
+
return <View className={cn('px-6 py-4 flex-row items-center gap-2', className)}>{children}</View>
|
|
305
259
|
}
|
|
306
260
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
hasFooter?: boolean
|
|
312
|
-
/** Number of content lines */
|
|
313
|
-
contentLines?: number
|
|
314
|
-
/** Additional className */
|
|
315
|
-
className?: string
|
|
261
|
+
interface SkeletonBodyProps {
|
|
262
|
+
hasHeader: boolean
|
|
263
|
+
hasFooter: boolean
|
|
264
|
+
contentLines: number
|
|
316
265
|
}
|
|
317
266
|
|
|
318
|
-
|
|
319
|
-
* Skeleton placeholder for Card loading state.
|
|
320
|
-
*/
|
|
321
|
-
export function CardSkeleton({
|
|
322
|
-
hasHeader = true,
|
|
323
|
-
hasFooter = false,
|
|
324
|
-
contentLines = 3,
|
|
325
|
-
className,
|
|
326
|
-
}: CardSkeletonProps) {
|
|
267
|
+
function SkeletonBody({ hasHeader, hasFooter, contentLines }: SkeletonBodyProps) {
|
|
327
268
|
return (
|
|
328
|
-
|
|
269
|
+
<>
|
|
329
270
|
{hasHeader && (
|
|
330
271
|
<CardHeader>
|
|
331
272
|
<View className="h-5 w-1/3 bg-interactive-disabled rounded" />
|
|
@@ -348,54 +289,60 @@ export function CardSkeleton({
|
|
|
348
289
|
<View className="h-9 w-24 bg-interactive-disabled rounded" />
|
|
349
290
|
</CardFooter>
|
|
350
291
|
)}
|
|
292
|
+
</>
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export interface CardSkeletonProps {
|
|
297
|
+
/** Whether to show header skeleton */
|
|
298
|
+
hasHeader?: boolean
|
|
299
|
+
/** Whether to show footer skeleton */
|
|
300
|
+
hasFooter?: boolean
|
|
301
|
+
/** Number of content lines */
|
|
302
|
+
contentLines?: number
|
|
303
|
+
/** Additional className */
|
|
304
|
+
className?: string
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Skeleton placeholder for Card loading state.
|
|
309
|
+
*/
|
|
310
|
+
export function CardSkeleton({
|
|
311
|
+
hasHeader = true,
|
|
312
|
+
hasFooter = false,
|
|
313
|
+
contentLines = 3,
|
|
314
|
+
className,
|
|
315
|
+
}: CardSkeletonProps) {
|
|
316
|
+
return (
|
|
317
|
+
<Card variant="elevated" className={cn('animate-pulse', className)}>
|
|
318
|
+
<SkeletonBody hasHeader={hasHeader} hasFooter={hasFooter} contentLines={contentLines} />
|
|
351
319
|
</Card>
|
|
352
320
|
)
|
|
353
321
|
}
|
|
354
322
|
|
|
355
323
|
export interface CardInsetProps extends ViewProps {
|
|
356
|
-
/** Elevation level for inset (-2=deep, -1=shallow) */
|
|
357
|
-
elevation?: -2 | -1
|
|
358
324
|
/** Additional className */
|
|
359
325
|
className?: string
|
|
360
326
|
children?: React.ReactNode
|
|
361
327
|
}
|
|
362
328
|
|
|
363
329
|
/**
|
|
364
|
-
*
|
|
365
|
-
* to
|
|
366
|
-
*
|
|
330
|
+
* A sunken well inside a Card: one plane down from the card with the inset
|
|
331
|
+
* recess. Nest one inside another to step down again (clamps at the frame).
|
|
332
|
+
*
|
|
367
333
|
* @example
|
|
368
|
-
* <Card
|
|
334
|
+
* <Card>
|
|
369
335
|
* <CardContent>
|
|
370
|
-
* <CardInset
|
|
336
|
+
* <CardInset className="p-4">
|
|
371
337
|
* <Text>This content appears inset/sunken</Text>
|
|
372
338
|
* </CardInset>
|
|
373
339
|
* </CardContent>
|
|
374
340
|
* </Card>
|
|
375
341
|
*/
|
|
376
|
-
export function CardInset({
|
|
377
|
-
elevation = -1,
|
|
378
|
-
className,
|
|
379
|
-
children,
|
|
380
|
-
style,
|
|
381
|
-
...props
|
|
382
|
-
}: CardInsetProps) {
|
|
383
|
-
const theme = useTheme()
|
|
384
|
-
const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme])
|
|
385
|
-
const surfaceColor = useMemo(() => {
|
|
386
|
-
return getElevationSurface(baseColor, elevation as ElevationLevel, theme)
|
|
387
|
-
}, [baseColor, elevation, theme])
|
|
388
|
-
const shadowStyle = useMemo(() => {
|
|
389
|
-
return getElevationShadow(baseColor, elevation as ElevationLevel, theme)
|
|
390
|
-
}, [baseColor, elevation, theme])
|
|
391
|
-
|
|
342
|
+
export function CardInset({ className, children, ...props }: CardInsetProps) {
|
|
392
343
|
return (
|
|
393
|
-
<
|
|
394
|
-
className={cn('rounded', className)}
|
|
395
|
-
style={[{ backgroundColor: surfaceColor }, shadowStyle, style]}
|
|
396
|
-
{...props}
|
|
397
|
-
>
|
|
344
|
+
<Surface pressed className={cn('rounded', className)} rounded={false} {...props}>
|
|
398
345
|
{children}
|
|
399
|
-
</
|
|
346
|
+
</Surface>
|
|
400
347
|
)
|
|
401
348
|
}
|
|
@@ -5,7 +5,7 @@ import { Checkbox, CheckboxGroup } from './Checkbox'
|
|
|
5
5
|
const meta: Meta<typeof Checkbox> = {
|
|
6
6
|
title: 'Components/Molecules/Checkbox',
|
|
7
7
|
component: Checkbox,
|
|
8
|
-
tags: ['autodocs'],
|
|
8
|
+
tags: ['autodocs', 'status:stable', '!status:review'],
|
|
9
9
|
argTypes: {
|
|
10
10
|
isChecked: {
|
|
11
11
|
control: 'boolean',
|
|
@@ -78,11 +78,7 @@ export const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox(
|
|
|
78
78
|
disabled: isDisabled,
|
|
79
79
|
}}
|
|
80
80
|
accessibilityLabel={label}
|
|
81
|
-
className={cn(
|
|
82
|
-
'flex-row items-start gap-2',
|
|
83
|
-
isDisabled && 'opacity-50',
|
|
84
|
-
className
|
|
85
|
-
)}
|
|
81
|
+
className={cn('flex-row items-start gap-2', isDisabled && 'opacity-50', className)}
|
|
86
82
|
{...props}
|
|
87
83
|
>
|
|
88
84
|
<View
|
|
@@ -102,23 +98,15 @@ export const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox(
|
|
|
102
98
|
<Text className="text-brand-primary font-bold text-center leading-none">✓</Text>
|
|
103
99
|
</View>
|
|
104
100
|
)}
|
|
105
|
-
{isIndeterminate && (
|
|
106
|
-
<View className={cn('bg-white h-0.5 w-2/3 rounded')} />
|
|
107
|
-
)}
|
|
101
|
+
{isIndeterminate && <View className={cn('bg-white h-0.5 w-2/3 rounded')} />}
|
|
108
102
|
</View>
|
|
109
103
|
|
|
110
104
|
{(label || helperText) && (
|
|
111
105
|
<View className="flex-1">
|
|
112
106
|
{label && (
|
|
113
|
-
<Text className={cn('text-text-primary font-medium', styles.label)}>
|
|
114
|
-
{label}
|
|
115
|
-
</Text>
|
|
116
|
-
)}
|
|
117
|
-
{helperText && (
|
|
118
|
-
<Text className="text-xs text-text-secondary mt-0.5">
|
|
119
|
-
{helperText}
|
|
120
|
-
</Text>
|
|
107
|
+
<Text className={cn('text-text-primary font-medium', styles.label)}>{label}</Text>
|
|
121
108
|
)}
|
|
109
|
+
{helperText && <Text className="text-xs text-text-secondary mt-0.5">{helperText}</Text>}
|
|
122
110
|
</View>
|
|
123
111
|
)}
|
|
124
112
|
</Pressable>
|
|
@@ -146,16 +134,8 @@ export function CheckboxGroup({
|
|
|
146
134
|
}: CheckboxGroupProps) {
|
|
147
135
|
return (
|
|
148
136
|
<View className={cn('gap-1', className)}>
|
|
149
|
-
{label &&
|
|
150
|
-
|
|
151
|
-
{label}
|
|
152
|
-
</Text>
|
|
153
|
-
)}
|
|
154
|
-
<View
|
|
155
|
-
className={cn(
|
|
156
|
-
orientation === 'vertical' ? 'flex-col gap-2' : 'flex-row gap-4'
|
|
157
|
-
)}
|
|
158
|
-
>
|
|
137
|
+
{label && <Text className="text-sm font-medium text-text-primary mb-2">{label}</Text>}
|
|
138
|
+
<View className={cn(orientation === 'vertical' ? 'flex-col gap-2' : 'flex-row gap-4')}>
|
|
159
139
|
{children}
|
|
160
140
|
</View>
|
|
161
141
|
</View>
|
|
@@ -5,7 +5,7 @@ import { Chip } from './Chip'
|
|
|
5
5
|
const meta: Meta<typeof Chip> = {
|
|
6
6
|
title: 'Components/Atoms/Chip',
|
|
7
7
|
component: Chip,
|
|
8
|
-
tags: ['autodocs'],
|
|
8
|
+
tags: ['autodocs', 'status:stable', '!status:review'],
|
|
9
9
|
argTypes: {
|
|
10
10
|
variant: {
|
|
11
11
|
control: 'select',
|
|
@@ -53,9 +53,15 @@ export const AllVariants: Story = {
|
|
|
53
53
|
render: () => (
|
|
54
54
|
<View style={{ gap: 12 }}>
|
|
55
55
|
<View style={{ flexDirection: 'row', gap: 8 }}>
|
|
56
|
-
<Chip variant="solid" color="primary">
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
<Chip variant="solid" color="primary">
|
|
57
|
+
Solid
|
|
58
|
+
</Chip>
|
|
59
|
+
<Chip variant="subtle" color="primary">
|
|
60
|
+
Subtle
|
|
61
|
+
</Chip>
|
|
62
|
+
<Chip variant="outline" color="primary">
|
|
63
|
+
Outline
|
|
64
|
+
</Chip>
|
|
59
65
|
</View>
|
|
60
66
|
</View>
|
|
61
67
|
),
|
|
@@ -75,8 +81,12 @@ export const Dismissible: Story = {
|
|
|
75
81
|
render: () => (
|
|
76
82
|
<View style={{ flexDirection: 'row', gap: 8 }}>
|
|
77
83
|
<Chip onDelete={() => console.log('delete')}>Remove me</Chip>
|
|
78
|
-
<Chip color="primary" onDelete={() => console.log('delete')}>
|
|
79
|
-
|
|
84
|
+
<Chip color="primary" onDelete={() => console.log('delete')}>
|
|
85
|
+
Primary
|
|
86
|
+
</Chip>
|
|
87
|
+
<Chip color="error" onDelete={() => console.log('delete')}>
|
|
88
|
+
Error
|
|
89
|
+
</Chip>
|
|
80
90
|
</View>
|
|
81
91
|
),
|
|
82
92
|
}
|
|
@@ -85,7 +95,9 @@ export const Clickable: Story = {
|
|
|
85
95
|
render: () => (
|
|
86
96
|
<View style={{ flexDirection: 'row', gap: 8 }}>
|
|
87
97
|
<Chip onPress={() => console.log('clicked')}>Click me</Chip>
|
|
88
|
-
<Chip color="primary" onPress={() => console.log('clicked')}>
|
|
98
|
+
<Chip color="primary" onPress={() => console.log('clicked')}>
|
|
99
|
+
Primary
|
|
100
|
+
</Chip>
|
|
89
101
|
</View>
|
|
90
102
|
),
|
|
91
103
|
}
|
|
@@ -94,8 +106,12 @@ export const Disabled: Story = {
|
|
|
94
106
|
render: () => (
|
|
95
107
|
<View style={{ flexDirection: 'row', gap: 8 }}>
|
|
96
108
|
<Chip isDisabled>Disabled</Chip>
|
|
97
|
-
<Chip isDisabled onDelete={() => {}}>
|
|
98
|
-
|
|
109
|
+
<Chip isDisabled onDelete={() => {}}>
|
|
110
|
+
Disabled Dismissible
|
|
111
|
+
</Chip>
|
|
112
|
+
<Chip isDisabled onPress={() => {}}>
|
|
113
|
+
Disabled Clickable
|
|
114
|
+
</Chip>
|
|
99
115
|
</View>
|
|
100
116
|
),
|
|
101
117
|
}
|
|
@@ -103,10 +119,18 @@ export const Disabled: Story = {
|
|
|
103
119
|
export const AsTagList: Story = {
|
|
104
120
|
render: () => (
|
|
105
121
|
<View style={{ flexDirection: 'row', gap: 8, flexWrap: 'wrap', maxWidth: 300 }}>
|
|
106
|
-
<Chip size="sm" color="primary" onDelete={() => {}}>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<Chip size="sm" color="
|
|
122
|
+
<Chip size="sm" color="primary" onDelete={() => {}}>
|
|
123
|
+
React
|
|
124
|
+
</Chip>
|
|
125
|
+
<Chip size="sm" color="secondary" onDelete={() => {}}>
|
|
126
|
+
TypeScript
|
|
127
|
+
</Chip>
|
|
128
|
+
<Chip size="sm" color="info" onDelete={() => {}}>
|
|
129
|
+
Tailwind
|
|
130
|
+
</Chip>
|
|
131
|
+
<Chip size="sm" color="success" onDelete={() => {}}>
|
|
132
|
+
NativeWind
|
|
133
|
+
</Chip>
|
|
110
134
|
</View>
|
|
111
135
|
),
|
|
112
136
|
}
|
|
@@ -53,11 +53,7 @@ describe('Chip', () => {
|
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
it('renders leftElement', () => {
|
|
56
|
-
render(
|
|
57
|
-
<Chip leftElement={<span data-testid="icon">icon</span>}>
|
|
58
|
-
With Icon
|
|
59
|
-
</Chip>
|
|
60
|
-
)
|
|
56
|
+
render(<Chip leftElement={<span data-testid="icon">icon</span>}>With Icon</Chip>)
|
|
61
57
|
expect(screen.getByTestId('icon')).toBeInTheDocument()
|
|
62
58
|
})
|
|
63
59
|
|
|
@@ -71,7 +67,15 @@ describe('Chip', () => {
|
|
|
71
67
|
})
|
|
72
68
|
|
|
73
69
|
it('renders with all color options', () => {
|
|
74
|
-
const colors = [
|
|
70
|
+
const colors = [
|
|
71
|
+
'default',
|
|
72
|
+
'primary',
|
|
73
|
+
'secondary',
|
|
74
|
+
'success',
|
|
75
|
+
'error',
|
|
76
|
+
'warning',
|
|
77
|
+
'info',
|
|
78
|
+
] as const
|
|
75
79
|
colors.forEach((color) => {
|
|
76
80
|
const { unmount } = render(<Chip color={color}>Test</Chip>)
|
|
77
81
|
expect(screen.getByText('Test')).toBeInTheDocument()
|