@titan-design/react-ui 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -47
- package/dist/bodymap.js +856 -736
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +858 -738
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +1431 -237
- package/dist/index.d.ts +1431 -237
- package/dist/index.js +6506 -4781
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6280 -4642
- package/dist/index.mjs.map +1 -1
- package/dist/{pages-B1hqnGIC.d.ts → pages-CsjsUn0G.d.ts} +51 -16
- package/dist/{pages-CvsFqNtx.d.mts → pages-ZbT_pD_U.d.mts} +51 -16
- package/dist/pages.d.mts +1 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1919 -1937
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +1927 -1945
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +225 -140
- package/dist/theme/index.d.ts +225 -140
- package/dist/theme/index.js +298 -319
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +283 -315
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +145 -24
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +145 -24
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/dist/theme/tokens.d.mts +128 -11
- package/dist/theme/tokens.d.ts +128 -11
- package/dist/theme/tokens.js +126 -26
- package/dist/theme/tokens.js.map +1 -1
- package/dist/theme/tokens.mjs +124 -27
- package/dist/theme/tokens.mjs.map +1 -1
- package/docs/audits/2026-09-08-critique-addenda.md +51 -0
- package/docs/audits/2026-09-08-library-critique.md +212 -0
- package/docs/library-roadmap.md +99 -0
- package/docs/render-testing-pattern.md +130 -0
- package/package.json +1 -1
- package/src/arch/Architecture.stories.tsx +3 -1
- package/src/arch/arch-graph.freshness.test.ts +52 -0
- package/src/arch/arch-graph.json +4989 -1583
- package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
- package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
- package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
- package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
- package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
- package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
- package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
- package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
- package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
- package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
- package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
- package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
- package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
- package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
- package/src/components/custom/ActiveWork/InitiativeBrief.tsx +182 -0
- package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
- package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
- package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
- package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
- package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
- package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
- package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
- package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
- package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
- package/src/components/custom/ActiveWork/README.md +305 -0
- package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
- package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
- package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
- package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
- package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
- package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
- package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
- package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
- package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
- package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
- package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
- package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
- package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
- package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
- package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
- package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
- package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
- package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
- package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
- package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
- package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
- package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
- package/src/components/custom/ActiveWork/format-time.ts +32 -0
- package/src/components/custom/ActiveWork/index.ts +19 -0
- package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
- package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
- package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
- package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
- package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +12 -6
- package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
- package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
- package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
- package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
- package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
- package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
- package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
- package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
- package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
- package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
- package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
- package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
- package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
- package/src/components/custom/Fatigue/README.md +40 -3
- package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
- package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
- package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
- package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
- package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
- package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
- package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
- package/src/components/custom/Fatigue/index.ts +17 -5
- package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
- package/src/components/custom/Fatigue/panel-layout.ts +185 -0
- package/src/components/custom/Gauge/Gauge.stories.tsx +6 -3
- package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
- package/src/components/custom/Gauge/Gauge.tsx +7 -2
- package/src/components/custom/Metric/Metric.stories.tsx +10 -1
- package/src/components/custom/Metric/Metric.test.tsx +1 -3
- package/src/components/custom/Metric/Metric.tsx +5 -20
- package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
- package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
- package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
- package/src/components/custom/Prose/README.md +58 -0
- package/src/components/custom/Prose/index.ts +1 -0
- package/src/components/custom/Scatter/Scatter.stories.tsx +55 -14
- package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
- package/src/components/custom/Scatter/Scatter.tsx +122 -18
- package/src/components/custom/Sidebar/Sidebar.stories.tsx +41 -8
- package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
- package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
- package/src/components/custom/Table/Table.stories.tsx +99 -16
- package/src/components/custom/Table/Table.test.tsx +273 -86
- package/src/components/custom/Table/Table.tsx +159 -67
- package/src/components/custom/Table/column-fit.test.ts +75 -0
- package/src/components/custom/Table/column-fit.ts +116 -0
- package/src/components/custom/Table/index.ts +9 -0
- package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
- package/src/components/custom/Treemap/Treemap.stories.tsx +15 -12
- package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
- package/src/components/custom/Treemap/Treemap.tsx +11 -3
- package/src/components/custom/Typography/Typography.stories.tsx +28 -1
- package/src/components/custom/Typography/Typography.test.tsx +34 -0
- package/src/components/custom/Typography/Typography.tsx +6 -0
- package/src/components/custom/Typography/index.ts +1 -8
- package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +11 -2
- package/src/components/custom/Workout/BaseBadge.stories.tsx +27 -11
- package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
- package/src/components/custom/Workout/BaseBadge.tsx +6 -2
- package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
- package/src/components/custom/Workout/BodyMap.tsx +8 -4
- package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +28 -6
- package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +50 -12
- package/src/components/custom/Workout/CapacityBandChart.stories.tsx +12 -9
- package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
- package/src/components/custom/Workout/CapacityBandChart.tsx +144 -111
- package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
- package/src/components/custom/Workout/DeviationBar.test.tsx +10 -4
- package/src/components/custom/Workout/DeviationBar.tsx +24 -16
- package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +183 -0
- package/src/components/custom/Workout/DualVelocityStrip.test.tsx +32 -18
- package/src/components/custom/Workout/ExerciseCard.stories.tsx +12 -11
- package/src/components/custom/Workout/ExerciseCard.test.tsx +52 -22
- package/src/components/custom/Workout/ExerciseCard.tsx +99 -183
- package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +95 -12
- package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +189 -1
- package/src/components/custom/Workout/ExerciseCardHeading.tsx +167 -18
- package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +3 -2
- package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
- package/src/components/custom/Workout/ExerciseHeading.tsx +194 -46
- package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +12 -9
- package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
- package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
- package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
- package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
- package/src/components/custom/Workout/InputBar.tsx +4 -2
- package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
- package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
- package/src/components/custom/Workout/IntensityBar.tsx +8 -3
- package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
- package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
- package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
- package/src/components/custom/Workout/MesoCard.tsx +14 -10
- package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
- package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
- package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
- package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
- package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
- package/src/components/custom/Workout/MesoStatusCard.tsx +20 -33
- package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
- package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
- package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
- package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
- package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +9 -4
- package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
- package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
- package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
- package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
- package/src/components/custom/Workout/PrBadge.tsx +13 -17
- package/src/components/custom/Workout/PrHistoryModal.stories.tsx +16 -3
- package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
- package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
- package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
- package/src/components/custom/Workout/README.md +68 -17
- package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
- package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
- package/src/components/custom/Workout/ReadinessCheck.tsx +22 -4
- package/src/components/custom/Workout/RestTimer.stories.tsx +16 -4
- package/src/components/custom/Workout/RestTimer.tsx +4 -2
- package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
- package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
- package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
- package/src/components/custom/Workout/SegmentedBar.stories.tsx +21 -17
- package/src/components/custom/Workout/SegmentedBar.tsx +10 -5
- package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
- package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
- package/src/components/custom/Workout/SessionHeader.tsx +12 -12
- package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
- package/src/components/custom/Workout/SessionRail.tsx +7 -9
- package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
- package/src/components/custom/Workout/SetBar.test.tsx +49 -4
- package/src/components/custom/Workout/SetBar.tsx +38 -12
- package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
- package/src/components/custom/Workout/SetRow.test.tsx +16 -2
- package/src/components/custom/Workout/SetRow.tsx +61 -23
- package/src/components/custom/Workout/SetStrip.stories.tsx +63 -7
- package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
- package/src/components/custom/Workout/SetStrip.tsx +24 -4
- package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
- package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
- package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
- package/src/components/custom/Workout/SetsRepsLoad.tsx +24 -12
- package/src/components/custom/Workout/Sparkline.stories.tsx +14 -11
- package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
- package/src/components/custom/Workout/Sparkline.tsx +14 -18
- package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
- package/src/components/custom/Workout/StatusDot.tsx +93 -63
- package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
- package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
- package/src/components/custom/Workout/StatusPill.tsx +27 -38
- package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +11 -4
- package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
- package/src/components/custom/Workout/StrengthTrendChart.tsx +39 -36
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
- package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
- package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +26 -10
- package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
- package/src/components/custom/Workout/TempoDisplay.tsx +2 -0
- package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
- package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
- package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +10 -6
- package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +5 -2
- package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +44 -1
- package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
- package/src/components/custom/Workout/VelocityStrip.test.tsx +48 -6
- package/src/components/custom/Workout/VelocityStrip.tsx +26 -14
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
- package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
- package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
- package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
- package/src/components/custom/Workout/WeekRow.tsx +23 -16
- package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
- package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
- package/src/components/custom/Workout/WeightBadge.tsx +28 -27
- package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
- package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
- package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
- package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
- package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
- package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
- package/src/components/custom/Workout/ZoneTrack.stories.tsx +10 -7
- package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
- package/src/components/custom/Workout/exerciseRowState.ts +29 -0
- package/src/components/custom/Workout/index.ts +17 -2
- package/src/components/custom/Workout/metricText.stories.tsx +15 -13
- package/src/components/custom/Workout/metricText.tsx +8 -2
- package/src/components/custom/Workout/setHeadingKit.tsx +219 -36
- package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
- package/src/components/custom/charts/README.md +66 -0
- package/src/components/custom/charts/SetBarChart.test.tsx +46 -1
- package/src/components/custom/charts/SetBarChart.tsx +56 -9
- package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
- package/src/components/custom/charts/SparkBars.test.tsx +69 -0
- package/src/components/custom/charts/SparkBars.tsx +85 -0
- package/src/components/custom/charts/flatBarGeometry.test.ts +41 -0
- package/src/components/custom/charts/flatBarGeometry.ts +32 -0
- package/src/components/custom/charts/index.ts +3 -0
- package/src/components/custom/index.ts +3 -0
- package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
- package/src/components/custom/stepper/Stepper.test.tsx +1 -7
- package/src/components/custom/stepper/Stepper.tsx +21 -34
- package/src/components/icons/icons.stories.tsx +1 -1
- package/src/components/icons/icons.tsx +51 -0
- package/src/components/shell/AppShell.stories.tsx +150 -0
- package/src/components/shell/AppShell.test.tsx +70 -0
- package/src/components/shell/AppShell.tsx +90 -0
- package/src/components/shell/BrandLockup.stories.tsx +66 -5
- package/src/components/shell/BrandLockup.test.tsx +34 -1
- package/src/components/shell/BrandLockup.tsx +27 -11
- package/src/components/shell/NavItem.stories.tsx +4 -4
- package/src/components/shell/NavItem.test.tsx +17 -0
- package/src/components/shell/NavItem.tsx +17 -5
- package/src/components/shell/README.md +89 -26
- package/src/components/shell/SideNav.stories.tsx +38 -7
- package/src/components/shell/SideNav.test.tsx +16 -8
- package/src/components/shell/SideNav.tsx +17 -17
- package/src/components/shell/TopBar.stories.tsx +44 -19
- package/src/components/shell/TopBar.test.tsx +34 -12
- package/src/components/shell/TopBar.tsx +61 -40
- package/src/components/shell/brands.tsx +66 -0
- package/src/components/shell/index.ts +9 -8
- package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
- package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
- package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
- package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
- package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
- package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
- package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
- package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
- package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
- package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
- package/src/components/shell/workout/WorkoutShell.tsx +77 -0
- package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
- package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
- package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
- package/src/components/shell/workout/index.ts +9 -0
- package/src/components/shell/workout/workoutNavItems.tsx +16 -0
- package/src/components/ui/README.md +110 -0
- package/src/components/ui/alert/Alert.stories.tsx +15 -5
- package/src/components/ui/alert/Alert.tsx +24 -3
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
- package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
- package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
- package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
- package/src/components/ui/avatar/Avatar.tsx +2 -10
- package/src/components/ui/badge/Badge.stories.tsx +83 -28
- package/src/components/ui/badge/Badge.test.tsx +19 -3
- package/src/components/ui/badge/Badge.tsx +48 -55
- package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
- package/src/components/ui/button/Button.stories.tsx +46 -12
- package/src/components/ui/button/Button.tsx +44 -37
- package/src/components/ui/card/Card.stories.tsx +90 -94
- package/src/components/ui/card/Card.test.tsx +80 -6
- package/src/components/ui/card/Card.tsx +150 -203
- package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
- package/src/components/ui/checkbox/Checkbox.tsx +7 -27
- package/src/components/ui/chip/Chip.stories.tsx +37 -13
- package/src/components/ui/chip/Chip.test.tsx +10 -6
- package/src/components/ui/chip/Chip.tsx +76 -91
- package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
- package/src/components/ui/collapse/Collapse.tsx +6 -11
- package/src/components/ui/data-row/DataRow.stories.tsx +14 -3
- package/src/components/ui/data-row/DataRow.test.tsx +5 -15
- package/src/components/ui/data-row/DataRow.tsx +18 -7
- package/src/components/ui/divider/Divider.stories.tsx +1 -1
- package/src/components/ui/divider/Divider.tsx +1 -5
- package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
- package/src/components/ui/drawer/Drawer.tsx +13 -27
- package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
- package/src/components/ui/form-field/FormField.stories.tsx +6 -20
- package/src/components/ui/form-field/FormField.test.tsx +1 -5
- package/src/components/ui/form-field/FormField.tsx +10 -46
- package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
- package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
- package/src/components/ui/help-tip/HelpTip.tsx +21 -22
- package/src/components/ui/help-tip/index.ts +7 -1
- package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
- package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
- package/src/components/ui/icon-box/IconBox.tsx +10 -18
- package/src/components/ui/indicator/Indicator.stories.tsx +5 -4
- package/src/components/ui/indicator/Indicator.tsx +20 -14
- package/src/components/ui/input/Input.stories.tsx +3 -11
- package/src/components/ui/input/Input.test.tsx +2 -10
- package/src/components/ui/input/Input.tsx +10 -25
- package/src/components/ui/input/index.ts +7 -1
- package/src/components/ui/link/Link.stories.tsx +19 -7
- package/src/components/ui/list-item/ListItem.stories.tsx +17 -5
- package/src/components/ui/list-item/ListItem.tsx +2 -9
- package/src/components/ui/menu/Menu.stories.tsx +21 -15
- package/src/components/ui/menu/Menu.test.tsx +2 -11
- package/src/components/ui/menu/Menu.tsx +12 -14
- package/src/components/ui/menu/index.ts +8 -1
- package/src/components/ui/modal/Modal.stories.tsx +2 -2
- package/src/components/ui/modal/Modal.tsx +31 -19
- package/src/components/ui/pill/Pill.stories.tsx +111 -23
- package/src/components/ui/pill/Pill.test.tsx +101 -3
- package/src/components/ui/pill/Pill.tsx +168 -49
- package/src/components/ui/pill/index.ts +1 -1
- package/src/components/ui/popover/Popover.stories.tsx +6 -8
- package/src/components/ui/popover/Popover.test.tsx +1 -6
- package/src/components/ui/popover/Popover.tsx +20 -15
- package/src/components/ui/popover/index.ts +7 -1
- package/src/components/ui/progress/Progress.stories.tsx +3 -12
- package/src/components/ui/progress/Progress.test.tsx +1 -5
- package/src/components/ui/progress/Progress.tsx +9 -6
- package/src/components/ui/radio/Radio.stories.tsx +42 -21
- package/src/components/ui/radio/Radio.test.tsx +6 -2
- package/src/components/ui/radio/Radio.tsx +23 -22
- package/src/components/ui/section/Section.stories.tsx +12 -21
- package/src/components/ui/section/Section.test.tsx +1 -6
- package/src/components/ui/section/Section.tsx +1 -3
- package/src/components/ui/section/index.ts +1 -5
- package/src/components/ui/select/Select.stories.tsx +3 -13
- package/src/components/ui/select/Select.test.tsx +2 -11
- package/src/components/ui/select/Select.tsx +16 -15
- package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
- package/src/components/ui/skeleton/Skeleton.tsx +3 -14
- package/src/components/ui/skeleton/index.ts +1 -7
- package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
- package/src/components/ui/spinner/Spinner.tsx +4 -5
- package/src/components/ui/stack/Stack.stories.tsx +8 -8
- package/src/components/ui/stack/Stack.tsx +1 -1
- package/src/components/ui/surface/Surface.stories.tsx +92 -33
- package/src/components/ui/surface/Surface.test.tsx +88 -28
- package/src/components/ui/surface/Surface.tsx +37 -87
- package/src/components/ui/surface/SurfaceContext.ts +22 -62
- package/src/components/ui/surface/index.ts +8 -0
- package/src/components/ui/surface/resolveSurface.ts +98 -0
- package/src/components/ui/surface/surface.contract.test.ts +6 -1
- package/src/components/ui/switch/Switch.stories.tsx +1 -1
- package/src/components/ui/switch/Switch.tsx +7 -6
- package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
- package/src/components/ui/tabs/Tabs.tsx +8 -21
- package/src/components/ui/tabs/index.ts +1 -7
- package/src/components/ui/tile/Tile.stories.tsx +1 -1
- package/src/components/ui/tile/Tile.tsx +3 -0
- package/src/components/ui/toast/Toast.stories.tsx +1 -1
- package/src/components/ui/toast/Toast.test.tsx +2 -8
- package/src/components/ui/toast/Toast.tsx +49 -57
- package/src/components/ui/toast/index.ts +0 -1
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
- package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
- package/src/components/ui/toolbar-button/ToolbarButton.tsx +38 -49
- package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
- package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
- package/src/components/ui/tooltip/Tooltip.tsx +55 -36
- package/src/components/ui/tooltip/index.ts +1 -1
- package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
- package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
- package/src/components/ui/trigger/index.ts +2 -0
- package/src/stories/PresetShowcase.stories.tsx +101 -48
- package/src/test/no-device-internals.test.ts +3 -3
- package/src/test/no-raw-color.test.ts +39 -0
- package/src/theme/Alpha.stories.tsx +103 -0
- package/src/theme/ChoosingTokens.stories.tsx +48 -0
- package/src/theme/ColorPalettes.stories.tsx +62 -45
- package/src/theme/ColorPrimitives.stories.tsx +35 -35
- package/src/theme/Depth.stories.tsx +132 -65
- package/src/theme/DepthCalibration.stories.tsx +23 -21
- package/src/theme/ProposedTokensVW82.stories.tsx +414 -0
- package/src/theme/ThemeProvider.test.tsx +4 -4
- package/src/theme/barrel.ts +7 -6
- package/src/theme/color-stories.coverage.test.ts +1 -1
- package/src/theme/color-utils.ts +41 -29
- package/src/theme/config.completeness.test.ts +1 -1
- package/src/theme/config.ts +40 -0
- package/src/theme/elevation.test.ts +82 -56
- package/src/theme/elevation.ts +77 -561
- package/src/theme/global.css +45 -5
- package/src/theme/grey-ramp.test.ts +24 -8
- package/src/theme/lift.test.ts +39 -0
- package/src/theme/lift.ts +102 -0
- package/src/theme/materials.test.ts +5 -2
- package/src/theme/materials.ts +38 -4
- package/src/theme/native-theming-guard.test.ts +5 -5
- package/src/theme/presets/apply.ts +4 -0
- package/src/theme/presets/audiobook.ts +5 -2
- package/src/theme/presets/default.ts +4 -0
- package/src/theme/presets/index.ts +14 -1
- package/src/theme/presets/types.ts +1 -1
- package/src/theme/semantic-contrast.test.ts +13 -4
- package/src/theme/status-distinctness.test.ts +66 -0
- package/src/theme/subtle-tone-weight.test.ts +163 -0
- package/src/theme/surface-planes.test.ts +37 -0
- package/src/theme/surface-planes.ts +68 -0
- package/src/theme/tailwind-var-opacity.test.ts +163 -0
- package/src/theme/token-export-guard.test.ts +1 -3
- package/src/theme/tokens/primitives.test.ts +15 -7
- package/src/theme/tokens/primitives.ts +98 -33
- package/src/theme/tokens/semantic-hex-guard.test.ts +322 -0
- package/src/theme/tokens/semantic.ts +124 -54
- package/src/theme/wash-ladder.test.ts +58 -0
- package/src/theme/workout-tokens.ts +1 -7
- package/src/types/jest-axe.d.ts +2 -6
- package/src/types/raw-md.d.ts +5 -0
- package/src/utils/colors.alpha-adoption.test.ts +408 -0
- package/src/utils/colors.ts +4 -4
- package/src/utils/form.ts +1 -3
- package/src/utils/index.ts +2 -7
- package/src/utils/number-format.ts +17 -0
- package/src/utils/workout-format.ts +15 -6
- package/src/web-jsx/jsx-runtime.ts +1 -5
- package/tailwind.config.js +55 -9
- package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
- package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
- package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
- package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
- package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
- package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
- package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
- package/src/components/shell/DashboardShell.stories.tsx +0 -65
- package/src/components/shell/DashboardShell.tsx +0 -75
- package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
- package/src/theme/elevation.stories.tsx +0 -346
- package/src/utils/useTheme.ts +0 -72
- /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
- /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
- /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
- /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React, { isValidElement, cloneElement } from 'react'
|
|
2
|
+
import { Pressable, type AccessibilityState } from 'react-native'
|
|
3
|
+
|
|
4
|
+
type Handler = (...args: never[]) => void
|
|
5
|
+
type Handlers = Record<string, Handler | undefined>
|
|
6
|
+
|
|
7
|
+
export interface TriggerSurfaceProps {
|
|
8
|
+
/** Pressable handlers (onPress, onHoverIn, …) for whichever element owns the interaction. */
|
|
9
|
+
handlers: Handlers
|
|
10
|
+
/** Role for the wrapper when it is the one handling the interaction. */
|
|
11
|
+
accessibilityRole?: 'button'
|
|
12
|
+
/** Merged onto whichever element ends up owning the interaction. */
|
|
13
|
+
accessibilityState?: AccessibilityState
|
|
14
|
+
className?: string
|
|
15
|
+
children: React.ReactNode
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type ComposableChildProps = Handlers & { accessibilityState?: AccessibilityState }
|
|
19
|
+
|
|
20
|
+
function chain(childHandler: Handler | undefined, ownHandler: Handler | undefined): Handler {
|
|
21
|
+
return (...args: never[]) => {
|
|
22
|
+
childHandler?.(...args)
|
|
23
|
+
ownHandler?.(...args)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Give interaction handling to a composed child instead of wrapping it in a second Pressable.
|
|
29
|
+
*
|
|
30
|
+
* React Native Web lets only the innermost pressable in a chain handle a gesture:
|
|
31
|
+
* PressResponder calls `stopPropagation()` on the click that drives `onPress`,
|
|
32
|
+
* and `useHover` contains hover the same way. A trigger that wraps a `Pressable`
|
|
33
|
+
* child (a `Button`, say) in its own `Pressable` therefore never sees the
|
|
34
|
+
* interaction — in a browser the trigger looks completely dead.
|
|
35
|
+
*
|
|
36
|
+
* A component child may be a Pressable, so the handlers are cloned onto it and
|
|
37
|
+
* the wrapper drops the button role — that also leaves one `[role=button]`
|
|
38
|
+
* rather than an invalid button-inside-button pair. The wrapper stays a
|
|
39
|
+
* Pressable, out of the tab order, to still catch children that turn out not to
|
|
40
|
+
* be pressable. Host elements (`<button>`, `<span>`) cannot take these handlers
|
|
41
|
+
* and do not swallow the gesture, so for those the wrapper handles it.
|
|
42
|
+
*/
|
|
43
|
+
export function TriggerSurface({
|
|
44
|
+
handlers,
|
|
45
|
+
accessibilityRole,
|
|
46
|
+
accessibilityState,
|
|
47
|
+
className,
|
|
48
|
+
children,
|
|
49
|
+
}: TriggerSurfaceProps) {
|
|
50
|
+
const child = isValidElement(children) ? children : null
|
|
51
|
+
const childCanCompose = child !== null && typeof child.type !== 'string'
|
|
52
|
+
|
|
53
|
+
if (!childCanCompose) {
|
|
54
|
+
return (
|
|
55
|
+
<Pressable
|
|
56
|
+
accessibilityRole={accessibilityRole}
|
|
57
|
+
accessibilityState={accessibilityState}
|
|
58
|
+
className={className}
|
|
59
|
+
{...handlers}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
</Pressable>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const childElement = child as React.ReactElement<ComposableChildProps>
|
|
67
|
+
const composed: ComposableChildProps = {}
|
|
68
|
+
for (const [name, handler] of Object.entries(handlers)) {
|
|
69
|
+
composed[name] = chain(childElement.props[name], handler)
|
|
70
|
+
}
|
|
71
|
+
composed.accessibilityState = {
|
|
72
|
+
...childElement.props.accessibilityState,
|
|
73
|
+
...accessibilityState,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Pressable focusable={false} tabIndex={-1} className={className} {...handlers}>
|
|
78
|
+
{cloneElement(childElement, composed)}
|
|
79
|
+
</Pressable>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
@@ -70,9 +70,7 @@ function SideBySideShowcase() {
|
|
|
70
70
|
return (
|
|
71
71
|
<View className="gap-6 p-6 bg-background-default min-h-screen">
|
|
72
72
|
<View className="gap-2">
|
|
73
|
-
<Text className="text-3xl font-bold text-text-primary font-heading">
|
|
74
|
-
Preset Showcase
|
|
75
|
-
</Text>
|
|
73
|
+
<Text className="text-3xl font-bold text-text-primary font-heading">Preset Showcase</Text>
|
|
76
74
|
<Text className="text-text-secondary text-base">
|
|
77
75
|
Toggle between presets to see how the entire design system adapts.
|
|
78
76
|
</Text>
|
|
@@ -89,14 +87,14 @@ function SideBySideShowcase() {
|
|
|
89
87
|
Subheading (font-heading)
|
|
90
88
|
</Text>
|
|
91
89
|
<Text className="text-base text-text-primary font-body">
|
|
92
|
-
Body text using font-body. The quick brown fox jumps over the lazy dog. This
|
|
93
|
-
|
|
90
|
+
Body text using font-body. The quick brown fox jumps over the lazy dog. This demonstrates
|
|
91
|
+
how paragraph text renders under the current preset.
|
|
94
92
|
</Text>
|
|
95
93
|
<Text className="text-sm text-text-secondary font-body">
|
|
96
94
|
Secondary body text for captions and supporting content.
|
|
97
95
|
</Text>
|
|
98
96
|
<Text className="text-sm text-text-primary font-mono">
|
|
99
|
-
{
|
|
97
|
+
{"const monospace = 'font-mono rendering'"}
|
|
100
98
|
</Text>
|
|
101
99
|
</Section>
|
|
102
100
|
|
|
@@ -195,20 +193,40 @@ function SideBySideShowcase() {
|
|
|
195
193
|
{/* Toasts */}
|
|
196
194
|
<Section title="Toasts">
|
|
197
195
|
<View className="gap-3">
|
|
198
|
-
<Toast
|
|
199
|
-
|
|
196
|
+
<Toast
|
|
197
|
+
title="Operation successful"
|
|
198
|
+
description="Your changes have been saved."
|
|
199
|
+
status="success"
|
|
200
|
+
/>
|
|
201
|
+
<Toast
|
|
202
|
+
title="Something went wrong"
|
|
203
|
+
description="Please try again later."
|
|
204
|
+
status="error"
|
|
205
|
+
/>
|
|
200
206
|
<Toast title="Heads up" description="This action cannot be undone." status="warning" />
|
|
201
|
-
<Toast
|
|
207
|
+
<Toast
|
|
208
|
+
title="New update available"
|
|
209
|
+
description="Version 2.0 is ready to install."
|
|
210
|
+
status="info"
|
|
211
|
+
/>
|
|
202
212
|
</View>
|
|
203
213
|
</Section>
|
|
204
214
|
|
|
205
215
|
{/* Status Colors */}
|
|
206
216
|
<Section title="Status Colors">
|
|
207
217
|
<View className="flex-row gap-3 flex-wrap">
|
|
208
|
-
<Badge color="success" size="lg">
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
<Badge color="
|
|
218
|
+
<Badge color="success" size="lg">
|
|
219
|
+
Success
|
|
220
|
+
</Badge>
|
|
221
|
+
<Badge color="error" size="lg">
|
|
222
|
+
Error
|
|
223
|
+
</Badge>
|
|
224
|
+
<Badge color="warning" size="lg">
|
|
225
|
+
Warning
|
|
226
|
+
</Badge>
|
|
227
|
+
<Badge color="info" size="lg">
|
|
228
|
+
Info
|
|
229
|
+
</Badge>
|
|
212
230
|
</View>
|
|
213
231
|
</Section>
|
|
214
232
|
</View>
|
|
@@ -225,9 +243,7 @@ function TypographyShowcase() {
|
|
|
225
243
|
return (
|
|
226
244
|
<View className="gap-6 p-6 bg-background-default min-h-screen">
|
|
227
245
|
<View className="gap-2">
|
|
228
|
-
<Text className="text-3xl font-bold text-text-primary font-heading">
|
|
229
|
-
Typography
|
|
230
|
-
</Text>
|
|
246
|
+
<Text className="text-3xl font-bold text-text-primary font-heading">Typography</Text>
|
|
231
247
|
<Text className="text-text-secondary text-base">
|
|
232
248
|
How fonts and text styles change across presets.
|
|
233
249
|
</Text>
|
|
@@ -252,9 +268,9 @@ function TypographyShowcase() {
|
|
|
252
268
|
|
|
253
269
|
<Section title="Body Font (font-body)">
|
|
254
270
|
<Text className="text-base text-text-primary font-body">
|
|
255
|
-
Regular body text. Design systems provide a shared language for product teams.
|
|
256
|
-
|
|
257
|
-
|
|
271
|
+
Regular body text. Design systems provide a shared language for product teams. By
|
|
272
|
+
codifying decisions into reusable components and tokens, teams move faster while
|
|
273
|
+
maintaining visual consistency across every surface.
|
|
258
274
|
</Text>
|
|
259
275
|
<Text className="text-base font-semibold text-text-primary font-body">
|
|
260
276
|
Bold body text. Emphasis and hierarchy within paragraph content.
|
|
@@ -263,8 +279,8 @@ function TypographyShowcase() {
|
|
|
263
279
|
Italic body text. Used for quotations, citations, and emphasis.
|
|
264
280
|
</Text>
|
|
265
281
|
<Text className="text-sm text-text-secondary font-body">
|
|
266
|
-
Small / secondary text. Captions, labels, and supporting information
|
|
267
|
-
|
|
282
|
+
Small / secondary text. Captions, labels, and supporting information that supplements the
|
|
283
|
+
main content without competing for attention.
|
|
268
284
|
</Text>
|
|
269
285
|
<Text className="text-xs text-text-tertiary font-body">
|
|
270
286
|
Extra-small / tertiary text. Timestamps, metadata, fine print.
|
|
@@ -287,19 +303,14 @@ function TypographyShowcase() {
|
|
|
287
303
|
|
|
288
304
|
<Section title="Mixed Typography">
|
|
289
305
|
<Card className="p-5 gap-3">
|
|
290
|
-
<Text className="text-2xl font-bold text-text-primary font-heading">
|
|
291
|
-
Chapter One
|
|
292
|
-
</Text>
|
|
306
|
+
<Text className="text-2xl font-bold text-text-primary font-heading">Chapter One</Text>
|
|
293
307
|
<Text className="text-base text-text-secondary font-body">
|
|
294
|
-
It was a bright cold day in April, and the clocks were striking thirteen.
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
along with him.
|
|
299
|
-
</Text>
|
|
300
|
-
<Text className="text-xs text-text-tertiary font-mono">
|
|
301
|
-
George Orwell, 1984
|
|
308
|
+
It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith,
|
|
309
|
+
his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly
|
|
310
|
+
through the glass doors of Victory Mansions, though not quickly enough to prevent a
|
|
311
|
+
swirl of gritty dust from entering along with him.
|
|
302
312
|
</Text>
|
|
313
|
+
<Text className="text-xs text-text-tertiary font-mono">George Orwell, 1984</Text>
|
|
303
314
|
</Card>
|
|
304
315
|
</Section>
|
|
305
316
|
</View>
|
|
@@ -313,7 +324,7 @@ function TypographyShowcase() {
|
|
|
313
324
|
function ColorSwatch({
|
|
314
325
|
label,
|
|
315
326
|
className,
|
|
316
|
-
textClass = 'text-
|
|
327
|
+
textClass = 'text-on-brand-primary',
|
|
317
328
|
}: {
|
|
318
329
|
label: string
|
|
319
330
|
className: string
|
|
@@ -332,9 +343,7 @@ function ColorPaletteShowcase() {
|
|
|
332
343
|
return (
|
|
333
344
|
<View className="gap-6 p-6 bg-background-default min-h-screen">
|
|
334
345
|
<View className="gap-2">
|
|
335
|
-
<Text className="text-3xl font-bold text-text-primary font-heading">
|
|
336
|
-
Color Palette
|
|
337
|
-
</Text>
|
|
346
|
+
<Text className="text-3xl font-bold text-text-primary font-heading">Color Palette</Text>
|
|
338
347
|
<Text className="text-text-secondary text-base">
|
|
339
348
|
Semantic color tokens rendered as swatches. Toggle presets to compare palettes.
|
|
340
349
|
</Text>
|
|
@@ -347,13 +356,21 @@ function ColorPaletteShowcase() {
|
|
|
347
356
|
<ColorSwatch label="brand-primary" className="bg-brand-primary" />
|
|
348
357
|
<ColorSwatch label="brand-primary-light" className="bg-brand-primary-light" />
|
|
349
358
|
<ColorSwatch label="brand-primary-dark" className="bg-brand-primary-dark" />
|
|
350
|
-
<ColorSwatch
|
|
359
|
+
<ColorSwatch
|
|
360
|
+
label="brand-primary-subtle"
|
|
361
|
+
className="bg-brand-primary-subtle"
|
|
362
|
+
textClass="text-text-primary"
|
|
363
|
+
/>
|
|
351
364
|
</View>
|
|
352
365
|
<View className="flex-row gap-3 flex-wrap mt-2">
|
|
353
366
|
<ColorSwatch label="brand-secondary" className="bg-brand-secondary" />
|
|
354
367
|
<ColorSwatch label="brand-secondary-light" className="bg-brand-secondary-light" />
|
|
355
368
|
<ColorSwatch label="brand-secondary-dark" className="bg-brand-secondary-dark" />
|
|
356
|
-
<ColorSwatch
|
|
369
|
+
<ColorSwatch
|
|
370
|
+
label="brand-secondary-subtle"
|
|
371
|
+
className="bg-brand-secondary-subtle"
|
|
372
|
+
textClass="text-text-primary"
|
|
373
|
+
/>
|
|
357
374
|
</View>
|
|
358
375
|
</Section>
|
|
359
376
|
|
|
@@ -372,7 +389,9 @@ function ColorPaletteShowcase() {
|
|
|
372
389
|
<Text className="text-xs font-mono font-medium text-text-primary">text-primary</Text>
|
|
373
390
|
</View>
|
|
374
391
|
<View className="rounded-lg p-3 min-w-[120px] min-h-[60px] justify-end bg-surface-elevated border border-hairline">
|
|
375
|
-
<Text className="text-xs font-mono font-medium text-text-secondary">
|
|
392
|
+
<Text className="text-xs font-mono font-medium text-text-secondary">
|
|
393
|
+
text-secondary
|
|
394
|
+
</Text>
|
|
376
395
|
</View>
|
|
377
396
|
<View className="rounded-lg p-3 min-w-[120px] min-h-[60px] justify-end bg-surface-elevated border border-hairline">
|
|
378
397
|
<Text className="text-xs font-mono font-medium text-text-tertiary">text-tertiary</Text>
|
|
@@ -382,26 +401,60 @@ function ColorPaletteShowcase() {
|
|
|
382
401
|
|
|
383
402
|
<Section title="Surface Colors">
|
|
384
403
|
<View className="flex-row gap-3 flex-wrap">
|
|
385
|
-
<ColorSwatch
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
404
|
+
<ColorSwatch
|
|
405
|
+
label="surface-base"
|
|
406
|
+
className="bg-surface-base border border-hairline"
|
|
407
|
+
textClass="text-text-primary"
|
|
408
|
+
/>
|
|
409
|
+
<ColorSwatch
|
|
410
|
+
label="surface-elevated"
|
|
411
|
+
className="bg-surface-elevated border border-hairline"
|
|
412
|
+
textClass="text-text-primary"
|
|
413
|
+
/>
|
|
414
|
+
<ColorSwatch
|
|
415
|
+
label="surface-raised"
|
|
416
|
+
className="bg-surface-raised border border-hairline"
|
|
417
|
+
textClass="text-text-primary"
|
|
418
|
+
/>
|
|
419
|
+
<ColorSwatch
|
|
420
|
+
label="surface-overlay"
|
|
421
|
+
className="bg-surface-overlay border border-hairline"
|
|
422
|
+
textClass="text-text-primary"
|
|
423
|
+
/>
|
|
424
|
+
<ColorSwatch
|
|
425
|
+
label="surface-input"
|
|
426
|
+
className="bg-surface-input border border-hairline"
|
|
427
|
+
textClass="text-text-primary"
|
|
428
|
+
/>
|
|
390
429
|
</View>
|
|
391
430
|
</Section>
|
|
392
431
|
|
|
393
432
|
<Section title="Background Colors">
|
|
394
433
|
<View className="flex-row gap-3 flex-wrap">
|
|
395
|
-
<ColorSwatch
|
|
396
|
-
|
|
397
|
-
|
|
434
|
+
<ColorSwatch
|
|
435
|
+
label="background-base"
|
|
436
|
+
className="bg-background-base border border-hairline"
|
|
437
|
+
textClass="text-text-primary"
|
|
438
|
+
/>
|
|
439
|
+
<ColorSwatch
|
|
440
|
+
label="background-default"
|
|
441
|
+
className="bg-background-default border border-hairline"
|
|
442
|
+
textClass="text-text-primary"
|
|
443
|
+
/>
|
|
444
|
+
<ColorSwatch
|
|
445
|
+
label="background-subtle"
|
|
446
|
+
className="bg-background-subtle border border-hairline"
|
|
447
|
+
textClass="text-text-primary"
|
|
448
|
+
/>
|
|
398
449
|
</View>
|
|
399
450
|
</Section>
|
|
400
451
|
|
|
401
452
|
<Section title="Border Colors">
|
|
402
453
|
<View className="flex-row gap-3 flex-wrap">
|
|
403
454
|
<View className="rounded-lg p-3 min-w-[120px] min-h-[60px] justify-end bg-surface-base border-2 border-hairline-default">
|
|
404
|
-
<Text className="text-xs font-mono font-medium text-text-primary">
|
|
455
|
+
<Text className="text-xs font-mono font-medium text-text-primary">
|
|
456
|
+
hairline-default
|
|
457
|
+
</Text>
|
|
405
458
|
</View>
|
|
406
459
|
<View className="rounded-lg p-3 min-w-[120px] min-h-[60px] justify-end bg-surface-base border-2 border-hairline-subtle">
|
|
407
460
|
<Text className="text-xs font-mono font-medium text-text-primary">hairline-subtle</Text>
|
|
@@ -21,13 +21,13 @@ describe('no-device-internals', () => {
|
|
|
21
21
|
// Dimension and ratio strings: the `\b` guard before `0x` means a digit
|
|
22
22
|
// followed by `x` never reads as a hex literal. These exact strings
|
|
23
23
|
// tripped an earlier, looser sweep.
|
|
24
|
-
{ code:
|
|
25
|
-
{ code:
|
|
24
|
+
{ code: '// icons render at 20x20' },
|
|
25
|
+
{ code: '// 200x400 intrinsic -> ~160x320 px' },
|
|
26
26
|
// SVG path coordinates — digit-only runs are not byte frames.
|
|
27
27
|
{ code: 'const d = "M12 2 22 12 12 22 2 12Z"' },
|
|
28
28
|
{ code: 'const d = "M7 7 17 17 12 22 12 2 17 7 7 17"' },
|
|
29
29
|
// Timestamps — `-` and `:` are not byte separators.
|
|
30
|
-
{ code:
|
|
30
|
+
{ code: '// datetime // 2024-01-15 14:30' },
|
|
31
31
|
// "cascade" in its CSS sense is ordinary styling vocabulary.
|
|
32
32
|
{ code: "// RN doesn't cascade text color, so hand-color the text" },
|
|
33
33
|
// Plain numbers and durations.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RuleTester } from 'eslint'
|
|
2
|
+
import rule from '../../eslint-rules/no-raw-color'
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester({
|
|
5
|
+
languageOptions: {
|
|
6
|
+
ecmaVersion: 2022,
|
|
7
|
+
sourceType: 'module',
|
|
8
|
+
parserOptions: { ecmaFeatures: { jsx: true } },
|
|
9
|
+
},
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
describe('no-raw-color', () => {
|
|
13
|
+
it('skips false positives while still flagging real raw colour', () => {
|
|
14
|
+
ruleTester.run('no-raw-color', rule as never, {
|
|
15
|
+
valid: [
|
|
16
|
+
// (a) enum-typed prop value: a bare colour word passed as color/variant/tone.
|
|
17
|
+
{ code: '<Spinner color="white" />' },
|
|
18
|
+
// (a) the same enum's members listed in a Storybook argTypes options array.
|
|
19
|
+
{
|
|
20
|
+
code: "const meta = { argTypes: { color: { control: 'select', options: ['primary', 'white'] } } }",
|
|
21
|
+
},
|
|
22
|
+
// (b) { value, label } demo data reusing colour words as IDs.
|
|
23
|
+
{ code: "const colorOptions = [{ value: 'red', label: 'Red' }]" },
|
|
24
|
+
// (c) documentation text in a <Text> element's children.
|
|
25
|
+
{ code: '<Text>{`background-color: #3C3C3C;`}</Text>' },
|
|
26
|
+
],
|
|
27
|
+
invalid: [
|
|
28
|
+
// Positive control: a real raw hex in a style prop must still be flagged,
|
|
29
|
+
// including on a <Text> element — only its *children* are exempt.
|
|
30
|
+
{
|
|
31
|
+
code: "<Text style={{ backgroundColor: '#123456' }} />",
|
|
32
|
+
errors: [{ messageId: 'hex' }],
|
|
33
|
+
},
|
|
34
|
+
// Positive control: a bare colour word outside any exempt shape is still named.
|
|
35
|
+
{ code: "const bg = 'white'", errors: [{ messageId: 'named' }] },
|
|
36
|
+
],
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { View, Text } from 'react-native'
|
|
3
|
+
import { alpha } from '../utils/colors'
|
|
4
|
+
import { getSemanticColors } from './tokens/semantic'
|
|
5
|
+
import { primitiveColors } from './tokens/primitives'
|
|
6
|
+
import { SectionIntro, SectionTitle, SWATCH_BORDER } from './color-story-kit'
|
|
7
|
+
|
|
8
|
+
const t = getSemanticColors('dark')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Foundations/Color/Alpha — deriving a translucent colour from a token instead
|
|
12
|
+
* of hardcoding an `rgba(...)` triple.
|
|
13
|
+
*
|
|
14
|
+
* `alpha(color, opacity)` (`packages/ui/src/utils/colors.ts`) takes a RESOLVED
|
|
15
|
+
* colour — a hex string or an `rgb()`/`rgba()` string, e.g. a semantic token's
|
|
16
|
+
* value or a primitive — and returns it as `rgba(r, g, b, opacity)`. It does
|
|
17
|
+
* NOT take a token name: `alpha('brand-primary', 0.1)` would try to parse the
|
|
18
|
+
* literal string `'brand-primary'` as a colour and fail. Resolve the token
|
|
19
|
+
* first (`t['brand-primary']`, `primitiveColors.white`, …), then wrap it.
|
|
20
|
+
*
|
|
21
|
+
* The payoff over a hand-picked `rgba(255, 121, 0, 0.1)`: when a ramp gets
|
|
22
|
+
* re-spaced or a semantic mapping moves, every `alpha()` call built on that
|
|
23
|
+
* token moves with it. A literal triple silently drifts from the token it was
|
|
24
|
+
* copied from and stays wrong until someone notices — the failure mode VW-78
|
|
25
|
+
* was opened to burn down (see `eslint-rules/raw-color-baseline.json`,
|
|
26
|
+
* enforced by `no-raw-color`'s `functional` rule).
|
|
27
|
+
*/
|
|
28
|
+
const meta: Meta = {
|
|
29
|
+
title: 'Foundations/Color/Alpha',
|
|
30
|
+
tags: ['autodocs'],
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default meta
|
|
34
|
+
|
|
35
|
+
const EXAMPLES = [
|
|
36
|
+
{ name: 'brand-primary @ 0.12', value: alpha(t['brand-primary'], 0.12) },
|
|
37
|
+
{ name: 'status-success @ 0.15', value: alpha(t['status-success'], 0.15) },
|
|
38
|
+
{ name: 'status-warning @ 0.25', value: alpha(t['status-warning'], 0.25) },
|
|
39
|
+
{ name: 'status-error @ 0.3', value: alpha(t['status-error'], 0.3) },
|
|
40
|
+
{ name: 'primitiveColors.white @ 0.08', value: alpha(primitiveColors.white, 0.08) },
|
|
41
|
+
] as const
|
|
42
|
+
|
|
43
|
+
function AlphaSwatch({ name, value }: { name: string; value: string }) {
|
|
44
|
+
return (
|
|
45
|
+
<View style={{ alignItems: 'center', width: 96 }}>
|
|
46
|
+
<View
|
|
47
|
+
style={{
|
|
48
|
+
width: 96,
|
|
49
|
+
height: 64,
|
|
50
|
+
borderRadius: 8,
|
|
51
|
+
backgroundColor: t['surface-elevated'],
|
|
52
|
+
borderWidth: 1,
|
|
53
|
+
borderColor: SWATCH_BORDER,
|
|
54
|
+
overflow: 'hidden',
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
<View style={{ flex: 1, backgroundColor: value }} />
|
|
58
|
+
</View>
|
|
59
|
+
<Text className="text-text-secondary text-xs mt-1" style={{ textAlign: 'center' }}>
|
|
60
|
+
{name}
|
|
61
|
+
</Text>
|
|
62
|
+
<Text className="text-text-tertiary" style={{ fontSize: 9, marginTop: 1 }}>
|
|
63
|
+
{value}
|
|
64
|
+
</Text>
|
|
65
|
+
</View>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const Default: StoryObj = {
|
|
70
|
+
render: () => (
|
|
71
|
+
<View style={{ padding: 24 }}>
|
|
72
|
+
<Text className="text-2xl font-bold text-text-primary mb-2">Alpha</Text>
|
|
73
|
+
<SectionIntro>
|
|
74
|
+
`alpha(color, opacity)` derives a translucent colour from a RESOLVED token or primitive
|
|
75
|
+
instead of a hand-picked `rgba(...)` triple, so the wash tracks the token it came from. Each
|
|
76
|
+
swatch below is rendered over the elevated surface plane so the translucency is visible.
|
|
77
|
+
</SectionIntro>
|
|
78
|
+
|
|
79
|
+
<SectionTitle>Usage</SectionTitle>
|
|
80
|
+
<View
|
|
81
|
+
style={{
|
|
82
|
+
backgroundColor: t['surface-raised'],
|
|
83
|
+
borderRadius: 8,
|
|
84
|
+
padding: 12,
|
|
85
|
+
marginBottom: 20,
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
<Text className="text-text-secondary" style={{ fontFamily: 'monospace', fontSize: 12 }}>
|
|
89
|
+
{"import { alpha } from '@/utils/colors'\n\n"}
|
|
90
|
+
{"const t = getSemanticColors('dark')\n"}
|
|
91
|
+
{"const wash = alpha(t['brand-primary'], 0.12)"}
|
|
92
|
+
</Text>
|
|
93
|
+
</View>
|
|
94
|
+
|
|
95
|
+
<SectionTitle>Examples</SectionTitle>
|
|
96
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 16 }}>
|
|
97
|
+
{EXAMPLES.map((example) => (
|
|
98
|
+
<AlphaSwatch key={example.name} {...example} />
|
|
99
|
+
))}
|
|
100
|
+
</View>
|
|
101
|
+
</View>
|
|
102
|
+
),
|
|
103
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { View, Text } from 'react-native'
|
|
3
|
+
import tokensDoc from '../../TOKENS.md?raw'
|
|
4
|
+
import { Typography } from '../components/custom/Typography'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Rendered straight from `packages/ui/TOKENS.md` via Vite's `?raw`, deliberately
|
|
8
|
+
* as its markdown source rather than a hand-built React page. A prettier page
|
|
9
|
+
* would be a second copy of the rules that can drift from the file — and a token
|
|
10
|
+
* guide that disagrees with itself is worse than a plain one. The content is
|
|
11
|
+
* mostly aligned tables, which read fine in mono.
|
|
12
|
+
*/
|
|
13
|
+
function ChoosingTokens() {
|
|
14
|
+
return (
|
|
15
|
+
<View className="gap-4 p-6">
|
|
16
|
+
<Typography variant="h3" className="text-text-primary">
|
|
17
|
+
Choosing tokens
|
|
18
|
+
</Typography>
|
|
19
|
+
<Typography variant="body2" className="text-text-secondary">
|
|
20
|
+
The decision table to read before writing a component. Source of truth:{' '}
|
|
21
|
+
<Text className="font-mono text-text-primary">packages/ui/TOKENS.md</Text> — this page
|
|
22
|
+
renders that file, so the two cannot disagree.
|
|
23
|
+
</Typography>
|
|
24
|
+
<View className="rounded-lg bg-surface-raised p-4">
|
|
25
|
+
<Text className="font-mono text-xs leading-5 text-text-secondary">{tokensDoc}</Text>
|
|
26
|
+
</View>
|
|
27
|
+
</View>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const meta: Meta<typeof ChoosingTokens> = {
|
|
32
|
+
title: 'Foundations/Choosing Tokens',
|
|
33
|
+
component: ChoosingTokens,
|
|
34
|
+
parameters: {
|
|
35
|
+
layout: 'fullscreen',
|
|
36
|
+
docs: {
|
|
37
|
+
description: {
|
|
38
|
+
component:
|
|
39
|
+
'Which palette for which meaning, how to resolve a colour in code, and the type/spacing ' +
|
|
40
|
+
'scales. Rendered from `packages/ui/TOKENS.md`.',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
export default meta
|
|
46
|
+
type Story = StoryObj<typeof ChoosingTokens>
|
|
47
|
+
|
|
48
|
+
export const Default: Story = {}
|