@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
|
@@ -12,8 +12,21 @@ import {
|
|
|
12
12
|
useSurfaceMode,
|
|
13
13
|
} from './SurfaceContext'
|
|
14
14
|
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
15
|
+
import { greyRamp, primitiveColors } from '../../../theme/tokens/primitives'
|
|
15
16
|
import { getPressedRecessShadow } from '../../../theme/elevation'
|
|
16
17
|
|
|
18
|
+
// Planes by RAMP STEP, never by literal bytes: a re-space of the grey ramp
|
|
19
|
+
// should move these expectations with it, not break them. Which step backs
|
|
20
|
+
// which plane is still asserted — that mapping is the behaviour.
|
|
21
|
+
const FRAME = greyRamp[975]
|
|
22
|
+
const BACKGROUND = greyRamp[950]
|
|
23
|
+
const BASE = greyRamp[925]
|
|
24
|
+
const ELEVATED = greyRamp[900]
|
|
25
|
+
const RAISED = greyRamp[875]
|
|
26
|
+
const OVERLAY = greyRamp[850]
|
|
27
|
+
const LIGHT_BASE = primitiveColors.white
|
|
28
|
+
const LIGHT_TEXT_PRIMARY = getSemanticColors('light')['text-primary']
|
|
29
|
+
|
|
17
30
|
// A descendant probe that renders the on-surface colour + mode it resolves from
|
|
18
31
|
// context, so tests can assert what a nested consumer would actually paint.
|
|
19
32
|
function Probe({ role = 'primary' as const, label = 'probe' }) {
|
|
@@ -72,11 +85,56 @@ describe('Surface (card model)', () => {
|
|
|
72
85
|
expect(screen.getByTestId('my-surface')).toBeInTheDocument()
|
|
73
86
|
})
|
|
74
87
|
|
|
75
|
-
it('
|
|
88
|
+
it('sits flat on the inherited plane by default (dark base, no treatment)', () => {
|
|
76
89
|
render(<Surface testID="s" />)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
expect(
|
|
90
|
+
const el = screen.getByTestId('s')
|
|
91
|
+
expect(el).toHaveStyle({ backgroundColor: BASE })
|
|
92
|
+
expect(el.style.boxShadow).toBe('')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('lifts onto ramp planes with rim + shadow: elevation 2 from the page is the card plane', () => {
|
|
96
|
+
render(<Surface elevation={2} testID="s" />)
|
|
97
|
+
const el = screen.getByTestId('s')
|
|
98
|
+
expect(el).toHaveStyle({ backgroundColor: RAISED })
|
|
99
|
+
expect(el.style.boxShadow).toContain('inset 0 1px 0')
|
|
100
|
+
expect(el.style.boxShadow).toMatch(/, 0 \d+px \d+px rgba\(0,0,0/)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('raise is relative: one step up from an elevated host lands on raised', () => {
|
|
104
|
+
render(
|
|
105
|
+
<Surface level="elevated">
|
|
106
|
+
<Surface raise={1} testID="s" />
|
|
107
|
+
</Surface>
|
|
108
|
+
)
|
|
109
|
+
expect(screen.getByTestId('s')).toHaveStyle({ backgroundColor: RAISED })
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('clamps at overlay so raised-on-raised cannot leave the ramp', () => {
|
|
113
|
+
render(
|
|
114
|
+
<Surface level="overlay">
|
|
115
|
+
<Surface raise={2} testID="s" />
|
|
116
|
+
</Surface>
|
|
117
|
+
)
|
|
118
|
+
expect(screen.getByTestId('s')).toHaveStyle({ backgroundColor: OVERLAY })
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('floats on the overlay plane with a larger shadow and no ring', () => {
|
|
122
|
+
render(<Surface elevation={4} testID="s" />)
|
|
123
|
+
const el = screen.getByTestId('s')
|
|
124
|
+
expect(el).toHaveStyle({ backgroundColor: OVERLAY })
|
|
125
|
+
expect(el.style.boxShadow.split(', ').length).toBe(4)
|
|
126
|
+
expect(el.style.borderWidth).toBe('')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('lets a caller switch the lift off on a raised plane, or on for a named one', () => {
|
|
130
|
+
render(
|
|
131
|
+
<>
|
|
132
|
+
<Surface raise={1} lift={false} testID="flat" />
|
|
133
|
+
<Surface level="raised" lift testID="lifted" />
|
|
134
|
+
</>
|
|
135
|
+
)
|
|
136
|
+
expect(screen.getByTestId('flat').style.boxShadow).toBe('')
|
|
137
|
+
expect(screen.getByTestId('lifted').style.boxShadow).toContain('inset 0 1px 0')
|
|
80
138
|
})
|
|
81
139
|
|
|
82
140
|
describe('accessibility', () => {
|
|
@@ -94,10 +152,10 @@ describe('Surface (card model)', () => {
|
|
|
94
152
|
|
|
95
153
|
describe('Surface (named plane)', () => {
|
|
96
154
|
it.each([
|
|
97
|
-
['background',
|
|
98
|
-
['base',
|
|
99
|
-
['elevated',
|
|
100
|
-
['raised',
|
|
155
|
+
['background', BACKGROUND],
|
|
156
|
+
['base', BASE],
|
|
157
|
+
['elevated', ELEVATED],
|
|
158
|
+
['raised', RAISED],
|
|
101
159
|
] as const)('maps level %s to the surface-ramp token %s', (level, hex) => {
|
|
102
160
|
render(<Surface level={level} testID="s" />)
|
|
103
161
|
expect(screen.getByTestId('s')).toHaveStyle({ backgroundColor: hex })
|
|
@@ -105,7 +163,7 @@ describe('Surface (named plane)', () => {
|
|
|
105
163
|
|
|
106
164
|
it('resolves the light-mode background when theme is overridden', () => {
|
|
107
165
|
render(<Surface level="base" theme="light" testID="s" />)
|
|
108
|
-
expect(screen.getByTestId('s')).toHaveStyle({ backgroundColor:
|
|
166
|
+
expect(screen.getByTestId('s')).toHaveStyle({ backgroundColor: LIGHT_BASE })
|
|
109
167
|
})
|
|
110
168
|
|
|
111
169
|
it('lets a caller style override the owned background', () => {
|
|
@@ -134,12 +192,12 @@ function lstar(hex: string): number {
|
|
|
134
192
|
|
|
135
193
|
describe('Surface (pressed well)', () => {
|
|
136
194
|
it.each([
|
|
137
|
-
// TD-surface-tokens S-3 re-space
|
|
138
|
-
//
|
|
139
|
-
['overlay',
|
|
140
|
-
['raised',
|
|
141
|
-
['elevated',
|
|
142
|
-
['base',
|
|
195
|
+
// TD-surface-tokens S-3 re-space widened the top steps; base and
|
|
196
|
+
// background were unchanged. The pairs below are ramp-adjacent by index.
|
|
197
|
+
['overlay', OVERLAY, RAISED], // → raised
|
|
198
|
+
['raised', RAISED, ELEVATED], // → elevated
|
|
199
|
+
['elevated', ELEVATED, BASE], // → base
|
|
200
|
+
['base', BASE, BACKGROUND], // → background
|
|
143
201
|
] as const)(
|
|
144
202
|
'in a %s parent renders one ramp step down (%s → %s), darker than its parent',
|
|
145
203
|
(parent, parentHex, pressedHex) => {
|
|
@@ -155,7 +213,7 @@ describe('Surface (pressed well)', () => {
|
|
|
155
213
|
|
|
156
214
|
it('with no enclosing Surface (default base) presses to the background plane', () => {
|
|
157
215
|
render(<Surface pressed testID="well" />)
|
|
158
|
-
expect(screen.getByTestId('well')).toHaveStyle({ backgroundColor:
|
|
216
|
+
expect(screen.getByTestId('well')).toHaveStyle({ backgroundColor: BACKGROUND })
|
|
159
217
|
})
|
|
160
218
|
|
|
161
219
|
it('clamps at the frame floor: pressed directly in background does not underflow', () => {
|
|
@@ -164,8 +222,8 @@ describe('Surface (pressed well)', () => {
|
|
|
164
222
|
<Surface pressed testID="well" />
|
|
165
223
|
</Surface>
|
|
166
224
|
)
|
|
167
|
-
// background
|
|
168
|
-
expect(screen.getByTestId('well')).toHaveStyle({ backgroundColor:
|
|
225
|
+
// background steps down to the frame floor, the bezel.
|
|
226
|
+
expect(screen.getByTestId('well')).toHaveStyle({ backgroundColor: FRAME })
|
|
169
227
|
})
|
|
170
228
|
|
|
171
229
|
it('does not step below the floor: pressed within a floor-pressed well stays at frame', () => {
|
|
@@ -176,7 +234,7 @@ describe('Surface (pressed well)', () => {
|
|
|
176
234
|
</Surface>
|
|
177
235
|
</Surface>
|
|
178
236
|
)
|
|
179
|
-
expect(screen.getByTestId('deeper')).toHaveStyle({ backgroundColor:
|
|
237
|
+
expect(screen.getByTestId('deeper')).toHaveStyle({ backgroundColor: FRAME })
|
|
180
238
|
})
|
|
181
239
|
|
|
182
240
|
it('publishes the stepped-down level to descendants so a nested press steps again', () => {
|
|
@@ -209,8 +267,8 @@ describe('Surface (pressed well)', () => {
|
|
|
209
267
|
<Surface pressed testID="well" style={{ boxShadow: undefined }} />
|
|
210
268
|
</Surface>
|
|
211
269
|
)
|
|
212
|
-
expect(screen.getByTestId('well')).toHaveStyle({ backgroundColor:
|
|
213
|
-
expect(lstar(
|
|
270
|
+
expect(screen.getByTestId('well')).toHaveStyle({ backgroundColor: BACKGROUND })
|
|
271
|
+
expect(lstar(BACKGROUND)).toBeLessThan(lstar(BASE))
|
|
214
272
|
})
|
|
215
273
|
|
|
216
274
|
it('rounds the well by default and honours an explicit rounded override', () => {
|
|
@@ -240,7 +298,7 @@ describe('pressedLevel helper', () => {
|
|
|
240
298
|
|
|
241
299
|
describe('getPressedRecessShadow', () => {
|
|
242
300
|
it('returns an inset recess tuned to the fill colour on the web path', () => {
|
|
243
|
-
const style = getPressedRecessShadow(
|
|
301
|
+
const style = getPressedRecessShadow(BACKGROUND, 'dark') as { boxShadow?: string }
|
|
244
302
|
expect(style.boxShadow).toContain('inset')
|
|
245
303
|
})
|
|
246
304
|
})
|
|
@@ -262,7 +320,9 @@ describe('Surface on-surface colour context', () => {
|
|
|
262
320
|
|
|
263
321
|
it('resolves dark on-surface colours even with no enclosing Surface', () => {
|
|
264
322
|
render(<Probe role="primary" label="p" />)
|
|
265
|
-
expect(screen.getByTestId('p')).toHaveStyle({
|
|
323
|
+
expect(screen.getByTestId('p')).toHaveStyle({
|
|
324
|
+
color: getSemanticColors('dark')['text-primary'],
|
|
325
|
+
})
|
|
266
326
|
})
|
|
267
327
|
|
|
268
328
|
it('flows an overridden theme to descendant text', () => {
|
|
@@ -271,7 +331,7 @@ describe('Surface on-surface colour context', () => {
|
|
|
271
331
|
<Probe role="primary" label="p" />
|
|
272
332
|
</Surface>
|
|
273
333
|
)
|
|
274
|
-
expect(screen.getByTestId('p')).toHaveStyle({ color:
|
|
334
|
+
expect(screen.getByTestId('p')).toHaveStyle({ color: LIGHT_TEXT_PRIMARY })
|
|
275
335
|
expect(screen.getByTestId('p')).toHaveTextContent('light')
|
|
276
336
|
})
|
|
277
337
|
|
|
@@ -283,15 +343,15 @@ describe('Surface on-surface colour context', () => {
|
|
|
283
343
|
</Surface>
|
|
284
344
|
</Surface>
|
|
285
345
|
)
|
|
286
|
-
expect(screen.getByTestId('p')).toHaveStyle({ color:
|
|
346
|
+
expect(screen.getByTestId('p')).toHaveStyle({ color: LIGHT_TEXT_PRIMARY })
|
|
287
347
|
})
|
|
288
348
|
})
|
|
289
349
|
|
|
290
350
|
describe('surface colour helpers', () => {
|
|
291
351
|
it('surfaceBackground returns literal hex per level + mode', () => {
|
|
292
|
-
expect(surfaceBackground('elevated', 'dark')).toBe(
|
|
293
|
-
expect(surfaceBackground('background', 'dark')).toBe(
|
|
294
|
-
expect(surfaceBackground('base', 'light')).toBe(
|
|
352
|
+
expect(surfaceBackground('elevated', 'dark')).toBe(ELEVATED)
|
|
353
|
+
expect(surfaceBackground('background', 'dark')).toBe(BACKGROUND)
|
|
354
|
+
expect(surfaceBackground('base', 'light')).toBe(LIGHT_BASE)
|
|
295
355
|
})
|
|
296
356
|
|
|
297
357
|
it('resolves the frame floor from its own semantic token', () => {
|
|
@@ -1,57 +1,14 @@
|
|
|
1
1
|
import React, { useMemo } from 'react'
|
|
2
|
-
import { View, type ViewProps
|
|
2
|
+
import { View, type ViewProps } from 'react-native'
|
|
3
3
|
import { cn } from '../../../utils/cn'
|
|
4
|
-
import { type
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
getElevationSurface,
|
|
8
|
-
getElevationShadow,
|
|
9
|
-
getPressedRecessShadow,
|
|
10
|
-
getBaseSurfaceColor,
|
|
11
|
-
type GlowIntensity,
|
|
12
|
-
getGlowShadow,
|
|
13
|
-
} from '../../../theme/elevation'
|
|
14
|
-
import {
|
|
15
|
-
SurfaceContext,
|
|
16
|
-
surfaceBackground,
|
|
17
|
-
pressedLevel,
|
|
18
|
-
useSurface,
|
|
19
|
-
type SurfaceContextValue,
|
|
20
|
-
type SurfaceLevel,
|
|
21
|
-
} from './SurfaceContext'
|
|
4
|
+
import { type GlowIntensity, getGlowShadow } from '../../../theme/elevation'
|
|
5
|
+
import { SurfaceContext, type SurfaceContextValue } from './SurfaceContext'
|
|
6
|
+
import { useResolvedSurface, type SurfaceDepthProps } from './resolveSurface'
|
|
22
7
|
|
|
23
|
-
export interface SurfaceProps extends ViewProps {
|
|
24
|
-
/**
|
|
25
|
-
* Numeric depth → a computed lighten + shadow (the raised-card model). The
|
|
26
|
-
* background is derived from the base surface by lightening. Ignored for the
|
|
27
|
-
* background when `level` is set. Default 0 (flat card).
|
|
28
|
-
*/
|
|
29
|
-
elevation?: ElevationLevel
|
|
30
|
-
/**
|
|
31
|
-
* Named grey plane (shell / rail / stage). Sets the background directly
|
|
32
|
-
* from a semantic surface token — reaching the darker nav/page planes the
|
|
33
|
-
* lighten model can't — and drops the default rounding + auto shadow so the
|
|
34
|
-
* plane reads full-bleed. Composable with `elevation`'s glow.
|
|
35
|
-
*/
|
|
36
|
-
level?: SurfaceLevel
|
|
37
|
-
/**
|
|
38
|
-
* Sunken "well": render ONE ramp step DOWN from the parent surface's level —
|
|
39
|
-
* the symmetric twin of a raised surface stepping up — and add an inner-shadow
|
|
40
|
-
* recess so the surface reads pressed (darker fill + inset shadow). Relative to
|
|
41
|
-
* the enclosing Surface's level (not this surface's own `level`), and clamped
|
|
42
|
-
* at the ramp's `inset` floor so it never underflows. One level of depth only.
|
|
43
|
-
*/
|
|
44
|
-
pressed?: boolean
|
|
8
|
+
export interface SurfaceProps extends ViewProps, SurfaceDepthProps {
|
|
45
9
|
glowColor?: string
|
|
46
10
|
glowIntensity?: GlowIntensity
|
|
47
|
-
/**
|
|
48
|
-
* Theme mode. Also seeds the on-surface colour CONTEXT so descendant text /
|
|
49
|
-
* icons resolve their colour from this surface instead of a `text-*` className
|
|
50
|
-
* that silently fails to black on raw RN. Inherits the nearest Surface /
|
|
51
|
-
* ThemeProvider when omitted (default dark — the wall).
|
|
52
|
-
*/
|
|
53
|
-
theme?: ThemeMode
|
|
54
|
-
/** Round the corners. Defaults on for the card model, off for a `level` plane. */
|
|
11
|
+
/** Round the corners. Defaults on for a lifted or pressed surface, off for an absolute plane. */
|
|
55
12
|
rounded?: boolean
|
|
56
13
|
className?: string
|
|
57
14
|
children?: React.ReactNode
|
|
@@ -59,17 +16,23 @@ export interface SurfaceProps extends ViewProps {
|
|
|
59
16
|
|
|
60
17
|
/**
|
|
61
18
|
* A container that OWNS its background and establishes an on-surface colour
|
|
62
|
-
* context.
|
|
63
|
-
* - `
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
19
|
+
* context. Depth is relative to the enclosing Surface:
|
|
20
|
+
* - `raise` / positive `elevation`: step up the ramp and wear the lift
|
|
21
|
+
* treatment (rim-light + ambient shadow). Clamps at `overlay`.
|
|
22
|
+
* - `pressed` / negative `elevation`: step down with an inner-shadow recess.
|
|
23
|
+
* - `level` (absolute): a flat grey plane straight from a token, for shell
|
|
24
|
+
* roots only (shell = background, page = base). No lift.
|
|
25
|
+
* - nothing: sit flat on the inherited plane.
|
|
26
|
+
* Descendants read the surface via {@link useOnSurfaceColor} / {@link useSurfaceMode}
|
|
27
|
+
* rather than hard-coding `getSemanticColors('dark')`.
|
|
68
28
|
*/
|
|
69
29
|
export function Surface({
|
|
70
|
-
elevation
|
|
30
|
+
elevation,
|
|
71
31
|
level,
|
|
32
|
+
raise,
|
|
72
33
|
pressed = false,
|
|
34
|
+
lift,
|
|
35
|
+
liftOptions,
|
|
73
36
|
glowColor,
|
|
74
37
|
glowIntensity,
|
|
75
38
|
theme,
|
|
@@ -79,39 +42,21 @@ export function Surface({
|
|
|
79
42
|
children,
|
|
80
43
|
...props
|
|
81
44
|
}: SurfaceProps) {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const baseColor = getBaseSurfaceColor(mode)
|
|
92
|
-
const resolvedLevel = pressed ? pressedLevel(inherited.level) : (level ?? inherited.level)
|
|
93
|
-
|
|
94
|
-
let backgroundColor: string
|
|
95
|
-
let shadowStyle: ViewStyle
|
|
96
|
-
if (pressed) {
|
|
97
|
-
backgroundColor = surfaceBackground(resolvedLevel, mode)
|
|
98
|
-
shadowStyle = getPressedRecessShadow(backgroundColor, mode)
|
|
99
|
-
} else if (isPlane) {
|
|
100
|
-
backgroundColor = surfaceBackground(level, mode)
|
|
101
|
-
// Planes own a flat full-bleed background — no depth shadow.
|
|
102
|
-
shadowStyle = {}
|
|
103
|
-
} else {
|
|
104
|
-
backgroundColor = getElevationSurface(baseColor, elevation, mode)
|
|
105
|
-
shadowStyle = getElevationShadow(baseColor, elevation, mode)
|
|
106
|
-
}
|
|
107
|
-
|
|
45
|
+
const resolved = useResolvedSurface({
|
|
46
|
+
elevation,
|
|
47
|
+
level,
|
|
48
|
+
raise,
|
|
49
|
+
pressed,
|
|
50
|
+
lift,
|
|
51
|
+
liftOptions,
|
|
52
|
+
theme,
|
|
53
|
+
})
|
|
108
54
|
const glowStyle = glowColor ? getGlowShadow(glowColor, glowIntensity) : {}
|
|
109
|
-
|
|
110
|
-
const applyRounded = rounded ?? (pressed || !isPlane)
|
|
55
|
+
const applyRounded = rounded ?? (pressed || level == null)
|
|
111
56
|
|
|
112
57
|
const value = useMemo<SurfaceContextValue>(
|
|
113
|
-
() => ({ mode, level:
|
|
114
|
-
[mode,
|
|
58
|
+
() => ({ mode: resolved.mode, level: resolved.plane }),
|
|
59
|
+
[resolved.mode, resolved.plane]
|
|
115
60
|
)
|
|
116
61
|
|
|
117
62
|
return (
|
|
@@ -119,7 +64,12 @@ export function Surface({
|
|
|
119
64
|
<View
|
|
120
65
|
className={cn(applyRounded && 'rounded-2xl', className)}
|
|
121
66
|
// backgroundColor first so a caller `style` can still override it.
|
|
122
|
-
style={[
|
|
67
|
+
style={[
|
|
68
|
+
{ backgroundColor: resolved.backgroundColor },
|
|
69
|
+
resolved.depthStyle,
|
|
70
|
+
glowStyle,
|
|
71
|
+
style,
|
|
72
|
+
]}
|
|
123
73
|
{...props}
|
|
124
74
|
>
|
|
125
75
|
{children}
|
|
@@ -1,52 +1,31 @@
|
|
|
1
1
|
// On-surface colour context (TD-05.12).
|
|
2
2
|
//
|
|
3
|
-
// A <Surface> owns a background from
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// A <Surface> owns a background from the surface ramp AND publishes the current
|
|
4
|
+
// theme mode so descendant text/icons resolve their colour from "what surface am
|
|
5
|
+
// I on" instead of a `text-*` className. Those classNames silently fail to black
|
|
6
|
+
// when the tree renders as raw RN in the standalone wall SPA (no global.css, no
|
|
7
|
+
// nativewind), which is the bug class this primitive retires.
|
|
8
8
|
import { createContext, useContext } from 'react'
|
|
9
9
|
import { getSemanticColors, type ThemeMode } from '../../../theme/tokens/semantic'
|
|
10
|
+
import type { SurfaceLevel } from '../../../theme/surface-planes'
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
// The plane vocabulary lives in the theme so `elevation.ts` can resolve levels
|
|
13
|
+
// to planes without importing a component. Re-exported here for callers that
|
|
14
|
+
// reached it through the Surface module.
|
|
15
|
+
export {
|
|
16
|
+
SURFACE_LEVEL_TOKEN,
|
|
17
|
+
PLANE_ORDER,
|
|
18
|
+
surfaceBackground,
|
|
19
|
+
pressedLevel,
|
|
20
|
+
raisedLevel,
|
|
21
|
+
type SurfaceLevel,
|
|
22
|
+
} from '../../../theme/surface-planes'
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
* A Surface's depth on the dark surface ramp. Each addressable level maps to an
|
|
15
|
-
* EXISTING semantic surface/background token (already grounded in the derived
|
|
16
|
-
* surface ramp — TD-surface-tokens S-1 — and theme-aware) — Surface introduces
|
|
17
|
-
* no new hexes. Darkest → lightest:
|
|
18
|
-
* inset (#13100D) < background (#1C1916) < base (#252321) < elevated (#2A2827) < raised (#2D2C2B) < overlay (#302F2E)
|
|
19
|
-
*
|
|
20
|
-
* `frame` is the bezel the ramp sits inside — the top bar / side nav chrome —
|
|
21
|
-
* and the floor a `<Surface pressed>` clamps at (see {@link pressedLevel}).
|
|
22
|
-
*
|
|
23
|
-
* It replaced a separate `inset` level in TD-07.14. That level was RETIRED, not
|
|
24
|
-
* renamed: at ΔE 1.10 from the frame it was an imperceptible duplicate, which is
|
|
25
|
-
* exactly why pressed (surface − 1) kept collapsing into it.
|
|
26
|
-
*/
|
|
27
|
-
export type SurfaceLevel = 'frame' | 'background' | 'base' | 'elevated' | 'raised' | 'overlay'
|
|
24
|
+
type ColorToken = keyof ReturnType<typeof getSemanticColors>
|
|
28
25
|
|
|
29
26
|
/** On-surface neutral text roles, resolved for the current surface + theme. */
|
|
30
27
|
export type OnSurfaceRole = 'primary' | 'secondary' | 'tertiary'
|
|
31
28
|
|
|
32
|
-
// Which semantic token backs each level. Values live in `semantic.ts` and stay
|
|
33
|
-
// in sync with the grey ramp — this map never carries literal hexes. Every level
|
|
34
|
-
// is present now: swapping `inset` (which had no token) for `frame` (which does)
|
|
35
|
-
// is what made this a total map and removed `surfaceBackground`'s special case.
|
|
36
|
-
export const SURFACE_LEVEL_TOKEN = {
|
|
37
|
-
frame: 'background-frame',
|
|
38
|
-
background: 'background-base',
|
|
39
|
-
base: 'surface-base',
|
|
40
|
-
elevated: 'surface-elevated',
|
|
41
|
-
raised: 'surface-raised',
|
|
42
|
-
overlay: 'surface-overlay',
|
|
43
|
-
} as const satisfies Record<SurfaceLevel, ColorToken>
|
|
44
|
-
|
|
45
|
-
// Darkest → lightest. A `<Surface pressed>` renders one index DOWN from its
|
|
46
|
-
// parent's level and clamps at `frame` (index 0). Kept in lockstep with the grey
|
|
47
|
-
// ramp and the surface.contract.test PLANE_ORDER.
|
|
48
|
-
const PRESSED_RAMP = ['frame', 'background', 'base', 'elevated', 'raised', 'overlay'] as const
|
|
49
|
-
|
|
50
29
|
const ON_SURFACE_TOKEN = {
|
|
51
30
|
primary: 'text-primary',
|
|
52
31
|
secondary: 'text-secondary',
|
|
@@ -56,7 +35,7 @@ const ON_SURFACE_TOKEN = {
|
|
|
56
35
|
export interface SurfaceContextValue {
|
|
57
36
|
/** Active theme mode. Defaults to dark (the wall). */
|
|
58
37
|
mode: ThemeMode
|
|
59
|
-
/**
|
|
38
|
+
/** Plane of the nearest enclosing Surface. */
|
|
60
39
|
level: SurfaceLevel
|
|
61
40
|
}
|
|
62
41
|
|
|
@@ -78,9 +57,9 @@ export function useSurfaceMode(): ThemeMode {
|
|
|
78
57
|
|
|
79
58
|
/**
|
|
80
59
|
* Literal-hex on-surface neutral text colours for a theme mode. Uses
|
|
81
|
-
* `getSemanticColors` (literal hex
|
|
82
|
-
*
|
|
83
|
-
*
|
|
60
|
+
* `getSemanticColors` (literal hex), never `resolveColor` (which returns `var()`
|
|
61
|
+
* under the RNW vitest alias), so values stay real in tested component code and
|
|
62
|
+
* on raw-RN surfaces alike.
|
|
84
63
|
*/
|
|
85
64
|
export function onSurfaceColors(mode: ThemeMode): Record<OnSurfaceRole, string> {
|
|
86
65
|
const c = getSemanticColors(mode)
|
|
@@ -95,22 +74,3 @@ export function onSurfaceColors(mode: ThemeMode): Record<OnSurfaceRole, string>
|
|
|
95
74
|
export function useOnSurfaceColor(role: OnSurfaceRole = 'primary'): string {
|
|
96
75
|
return getSemanticColors(useSurfaceMode())[ON_SURFACE_TOKEN[role]]
|
|
97
76
|
}
|
|
98
|
-
|
|
99
|
-
/** The background hex for a surface level under a theme mode (literal hex). */
|
|
100
|
-
export function surfaceBackground(level: SurfaceLevel, mode: ThemeMode): string {
|
|
101
|
-
return getSemanticColors(mode)[SURFACE_LEVEL_TOKEN[level]]
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* The level a `<Surface pressed>` resolves to: its parent's level stepped one
|
|
106
|
-
* index DOWN the ramp — the symmetric twin of a raised surface stepping up —
|
|
107
|
-
* clamped at the `frame` floor so a pressed surface never underflows the bezel.
|
|
108
|
-
* overlay→raised, raised→elevated, elevated→base, base→background,
|
|
109
|
-
* background→frame, frame→frame (clamped).
|
|
110
|
-
* Pressed exposes ONE level of depth only (no pressed-2).
|
|
111
|
-
*/
|
|
112
|
-
export function pressedLevel(parent: SurfaceLevel): SurfaceLevel {
|
|
113
|
-
const index = PRESSED_RAMP.indexOf(parent)
|
|
114
|
-
const down = Math.max(0, index - 1)
|
|
115
|
-
return PRESSED_RAMP[down]
|
|
116
|
-
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export { Surface, type SurfaceProps } from './Surface'
|
|
2
|
+
export {
|
|
3
|
+
resolveSurfaceDepth,
|
|
4
|
+
useResolvedSurface,
|
|
5
|
+
type SurfaceDepthProps,
|
|
6
|
+
type ResolvedSurface,
|
|
7
|
+
} from './resolveSurface'
|
|
2
8
|
export {
|
|
3
9
|
SurfaceContext,
|
|
4
10
|
useSurface,
|
|
@@ -7,7 +13,9 @@ export {
|
|
|
7
13
|
onSurfaceColors,
|
|
8
14
|
surfaceBackground,
|
|
9
15
|
pressedLevel,
|
|
16
|
+
raisedLevel,
|
|
10
17
|
SURFACE_LEVEL_TOKEN,
|
|
18
|
+
PLANE_ORDER,
|
|
11
19
|
type SurfaceLevel,
|
|
12
20
|
type OnSurfaceRole,
|
|
13
21
|
type SurfaceContextValue,
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// How a container decides which plane it sits on and what it wears there.
|
|
2
|
+
//
|
|
3
|
+
// One resolution path shared by <Surface> and <Card>, so the two can never
|
|
4
|
+
// disagree about depth. Everything is RELATIVE to the enclosing Surface unless
|
|
5
|
+
// an absolute `level` names a shell root.
|
|
6
|
+
import { useMemo } from 'react'
|
|
7
|
+
import type { ViewStyle } from 'react-native'
|
|
8
|
+
import {
|
|
9
|
+
FLOATING_ELEVATION_MIN,
|
|
10
|
+
getPressedRecessShadow,
|
|
11
|
+
type ElevationLevel,
|
|
12
|
+
} from '../../../theme/elevation'
|
|
13
|
+
import { liftStyle, type LiftOptions, type LiftStep } from '../../../theme/lift'
|
|
14
|
+
import {
|
|
15
|
+
pressedLevel,
|
|
16
|
+
raisedLevel,
|
|
17
|
+
surfaceBackground,
|
|
18
|
+
type SurfaceLevel,
|
|
19
|
+
} from '../../../theme/surface-planes'
|
|
20
|
+
import type { ThemeMode } from '../../../theme/tokens/semantic'
|
|
21
|
+
import { useSurface, type SurfaceContextValue } from './SurfaceContext'
|
|
22
|
+
|
|
23
|
+
export interface SurfaceDepthProps {
|
|
24
|
+
/** Absolute plane, for shell roots (shell = background, page = base). No lift. */
|
|
25
|
+
level?: SurfaceLevel
|
|
26
|
+
/** Planes to step UP from the enclosing Surface, with the lift treatment. */
|
|
27
|
+
raise?: 1 | 2 | 3
|
|
28
|
+
/**
|
|
29
|
+
* Numeric depth relative to the enclosing Surface: negative recesses, 0 sits
|
|
30
|
+
* flat on the same plane, 1–3 lift, 4–5 float on the overlay plane.
|
|
31
|
+
*/
|
|
32
|
+
elevation?: ElevationLevel
|
|
33
|
+
/** One plane DOWN with an inner-shadow recess. */
|
|
34
|
+
pressed?: boolean
|
|
35
|
+
/** Force the lift treatment on or off regardless of the step taken. */
|
|
36
|
+
lift?: boolean
|
|
37
|
+
/** Tune the lift (rim alpha). Specimens and hero surfaces only. */
|
|
38
|
+
liftOptions?: LiftOptions
|
|
39
|
+
/** Override the inherited theme mode. */
|
|
40
|
+
theme?: ThemeMode
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface ResolvedSurface {
|
|
44
|
+
mode: ThemeMode
|
|
45
|
+
plane: SurfaceLevel
|
|
46
|
+
backgroundColor: string
|
|
47
|
+
/** Recess or lift, to compose after `backgroundColor`. */
|
|
48
|
+
depthStyle: ViewStyle
|
|
49
|
+
/** Planes stepped up (0 when flat, pressed, or an absolute plane). */
|
|
50
|
+
step: number
|
|
51
|
+
lifted: boolean
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function recessDepth(inherited: SurfaceContextValue, planesDown: number, mode: ThemeMode) {
|
|
55
|
+
let plane = inherited.level
|
|
56
|
+
for (let i = 0; i < planesDown; i++) plane = pressedLevel(plane)
|
|
57
|
+
const backgroundColor = surfaceBackground(plane, mode)
|
|
58
|
+
return { plane, backgroundColor, depthStyle: getPressedRecessShadow(backgroundColor, mode) }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Pure resolution: the plane, its hex, and the treatment. */
|
|
62
|
+
export function resolveSurfaceDepth(
|
|
63
|
+
inherited: SurfaceContextValue,
|
|
64
|
+
props: SurfaceDepthProps
|
|
65
|
+
): ResolvedSurface {
|
|
66
|
+
const mode = props.theme ?? inherited.mode
|
|
67
|
+
const elevation = props.elevation ?? 0
|
|
68
|
+
if (props.pressed || elevation < 0) {
|
|
69
|
+
const down = props.pressed ? 1 : -elevation
|
|
70
|
+
return { mode, step: 0, lifted: false, ...recessDepth(inherited, down, mode) }
|
|
71
|
+
}
|
|
72
|
+
const step = props.level != null ? 0 : (props.raise ?? elevation)
|
|
73
|
+
const floating = step >= FLOATING_ELEVATION_MIN
|
|
74
|
+
const plane = props.level ?? (floating ? 'overlay' : raisedLevel(inherited.level, step))
|
|
75
|
+
const lifted = props.lift ?? step > 0
|
|
76
|
+
const liftStep = Math.max(1, Math.min(5, step)) as LiftStep
|
|
77
|
+
const depthStyle = lifted ? liftStyle(liftStep, mode, props.liftOptions) : {}
|
|
78
|
+
return { mode, plane, backgroundColor: surfaceBackground(plane, mode), depthStyle, step, lifted }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The resolved depth of a container at this point in the tree. */
|
|
82
|
+
export function useResolvedSurface(props: SurfaceDepthProps): ResolvedSurface {
|
|
83
|
+
const inherited = useSurface()
|
|
84
|
+
const { level, raise, elevation, pressed, lift, liftOptions, theme } = props
|
|
85
|
+
return useMemo(
|
|
86
|
+
() =>
|
|
87
|
+
resolveSurfaceDepth(inherited, {
|
|
88
|
+
level,
|
|
89
|
+
raise,
|
|
90
|
+
elevation,
|
|
91
|
+
pressed,
|
|
92
|
+
lift,
|
|
93
|
+
liftOptions,
|
|
94
|
+
theme,
|
|
95
|
+
}),
|
|
96
|
+
[inherited, level, raise, elevation, pressed, lift, liftOptions, theme]
|
|
97
|
+
)
|
|
98
|
+
}
|
|
@@ -8,7 +8,8 @@ import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
|
8
8
|
* palette locks its eligibility mask with a value-level test.
|
|
9
9
|
*
|
|
10
10
|
* Scope: DARK mode only. The north-star diagnosis
|
|
11
|
-
* (sources/design/surface-system-north-star.md
|
|
11
|
+
* (`sources/design/surface-system-north-star.md`, in the `voltras-workspace`
|
|
12
|
+
* active-work initiative rather than this repo) measured and
|
|
12
13
|
* fixed the dark ramp specifically; light mode has its own latent collisions
|
|
13
14
|
* (e.g. `surface-overlay` === `surface-base`, both `#FFFFFF`) that were never
|
|
14
15
|
* part of this investigation — flagged as a follow-up, not silently patched
|
|
@@ -91,6 +92,10 @@ describe('surface ramp contract (dark) — token-value guardrails', () => {
|
|
|
91
92
|
// Locked values from surface-system-north-star.md (re-spaced S-3) — see
|
|
92
93
|
// surfaceRampDark in primitives.ts for the derivation this must match
|
|
93
94
|
// byte-for-byte. background/base are unchanged by the re-space.
|
|
95
|
+
//
|
|
96
|
+
// The literal hexes are the POINT of this one test: it pins the bytes, so a
|
|
97
|
+
// re-space has to come here and say so. Every other test in the suite
|
|
98
|
+
// references the ramp instead.
|
|
94
99
|
expect(dark['background-frame']).toBe('#100D0A')
|
|
95
100
|
expect(dark['background-base']).toBe('#1C1916')
|
|
96
101
|
expect(dark['surface-base']).toBe('#252321')
|