@titan-design/react-ui 0.9.2 → 0.10.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/dist/bodymap.js +78 -24
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +78 -24
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +215 -123
- package/dist/index.d.ts +215 -123
- package/dist/index.js +408 -259
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +258 -121
- package/dist/index.mjs.map +1 -1
- package/dist/pages.js +214 -157
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +214 -157
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +895 -795
- package/dist/theme/index.d.ts +895 -795
- package/dist/theme/index.js +101 -20
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +99 -22
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +88 -24
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +88 -24
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/custom/Workout/BaseBadge.tsx +5 -5
- package/src/components/custom/Workout/RowInventory.stories.tsx +5 -2
- package/src/components/custom/Workout/S3FullRail.stories.tsx +13 -1
- package/src/components/custom/Workout/SessionHeader.tsx +11 -13
- package/src/components/custom/Workout/SessionRail.stories.tsx +4 -1
- package/src/components/custom/Workout/SessionRail.tsx +16 -14
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +16 -25
- package/src/components/custom/Workout/SupersetWrapper.tsx +1 -1
- package/src/components/custom/Workout/TempoDisplay.tsx +3 -7
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +4 -1
- package/src/components/custom/Workout/WorkoutPill.tsx +2 -2
- package/src/components/shell/DashboardShell.tsx +6 -3
- package/src/components/ui/surface/Surface.stories.tsx +244 -1
- package/src/components/ui/surface/Surface.test.tsx +244 -1
- package/src/components/ui/surface/Surface.tsx +98 -20
- package/src/components/ui/surface/SurfaceContext.ts +126 -0
- package/src/components/ui/surface/index.ts +13 -0
- package/src/components/ui/surface/surface.contract.test.ts +283 -0
- package/src/test/nativewind-stub.ts +13 -0
- package/src/theme/ColorSystem.stories.tsx +232 -47
- package/src/theme/ThemeProvider.test.tsx +24 -0
- package/src/theme/ThemeProvider.tsx +23 -6
- package/src/theme/config.ts +12 -0
- package/src/theme/elevation.ts +90 -67
- package/src/theme/global.css +35 -9
- package/src/theme/tokens/primitives.ts +40 -0
- package/src/theme/tokens/semantic.ts +63 -14
- package/tailwind.config.js +8 -0
|
@@ -22,6 +22,9 @@ import { WeightBadge } from './WeightBadge'
|
|
|
22
22
|
import { PrBadge } from './PrBadge'
|
|
23
23
|
import { PlaceholderStrip } from './PlaceholderStrip'
|
|
24
24
|
import { SupersetWrapper } from './SupersetWrapper'
|
|
25
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
26
|
+
|
|
27
|
+
const t = getSemanticColors('dark')
|
|
25
28
|
|
|
26
29
|
// ----------------------------------------------------------------------------- gallery scaffold
|
|
27
30
|
class Boundary extends Component<{ children: ReactNode }, { err: string | null }> {
|
|
@@ -364,10 +367,10 @@ export const AllRows: Story = {
|
|
|
364
367
|
</Cell>
|
|
365
368
|
<Cell name="SupersetWrapper" entity="grouping bracket" expand="no">
|
|
366
369
|
<SupersetWrapper label="SS1" color="#FF7900">
|
|
367
|
-
<View style={{ padding: 10, backgroundColor: '
|
|
370
|
+
<View style={{ padding: 10, backgroundColor: t['surface-raised'], borderRadius: 8 }}>
|
|
368
371
|
<Text style={{ color: '#F3F4F6' }}>Exercise A</Text>
|
|
369
372
|
</View>
|
|
370
|
-
<View style={{ padding: 10, backgroundColor: '
|
|
373
|
+
<View style={{ padding: 10, backgroundColor: t['surface-raised'], borderRadius: 8 }}>
|
|
371
374
|
<Text style={{ color: '#F3F4F6' }}>Exercise B</Text>
|
|
372
375
|
</View>
|
|
373
376
|
</SupersetWrapper>
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
6
6
|
import { NavStub, Rail, Page, T_TERTIARY } from './setHeadingKit'
|
|
7
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
8
|
+
|
|
9
|
+
const t = getSemanticColors('dark')
|
|
7
10
|
|
|
8
11
|
type Args = { stripHeight: number }
|
|
9
12
|
const meta: Meta<Args> = {
|
|
@@ -25,7 +28,16 @@ export const NextToNav: Story = {
|
|
|
25
28
|
<div style={{ display: 'flex', alignItems: 'stretch', width: 'fit-content' }}>
|
|
26
29
|
<NavStub />
|
|
27
30
|
<Rail stripH={args.stripHeight} />
|
|
28
|
-
<div
|
|
31
|
+
<div
|
|
32
|
+
style={{
|
|
33
|
+
width: 140,
|
|
34
|
+
background: t['background-base'],
|
|
35
|
+
alignSelf: 'stretch',
|
|
36
|
+
display: 'flex',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
justifyContent: 'center',
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
29
41
|
<span style={{ fontSize: 10, color: T_TERTIARY, fontFamily: 'monospace' }}>stage</span>
|
|
30
42
|
</div>
|
|
31
43
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
2
|
import { View, Text, type ViewProps } from 'react-native'
|
|
3
|
-
import {
|
|
3
|
+
import { Surface, onSurfaceColors, useSurfaceMode } from '../../ui/surface'
|
|
4
4
|
import { Typography } from '../Typography'
|
|
5
5
|
import { TimerReadout } from '../TimerReadout'
|
|
6
6
|
import { SegmentedProgressBar } from './SegmentedProgressBar'
|
|
@@ -8,13 +8,10 @@ import { MetricTiles, type MetricTileData } from './MetricTiles'
|
|
|
8
8
|
import { ScheduleTiles } from './ScheduleTiles'
|
|
9
9
|
import { paceTone, paceToneColor } from './paceTone'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// (charcoal 800) sits raised off it. Previously charcoal 400 (#1F1F1F), which made the header
|
|
16
|
-
// the lightest rail surface and let it blend with the rows instead of anchoring to the nav.
|
|
17
|
-
const HEADER_BG = t['background-base'] // #101010 — matches SideNav bg-background-base
|
|
11
|
+
// The header shares the SideNav's `background-base` (warm-tapered ramp shell, #1C1916) so the
|
|
12
|
+
// nav and the rail header read as ONE continuous dark plane on the left — the sunk exercise list
|
|
13
|
+
// sits raised off it. A `<Surface level="background">` owns that plane so the header no
|
|
14
|
+
// longer hand-sets it, and its title/label text resolve on-surface colours from context.
|
|
18
15
|
|
|
19
16
|
// The chunked pace bar matches the SetStrip language but sits tighter than the default
|
|
20
17
|
// SetStrip gap (5) — the locked design uses a 3px gap and a 9px track.
|
|
@@ -73,21 +70,22 @@ export function SessionHeader({
|
|
|
73
70
|
}: SessionHeaderProps) {
|
|
74
71
|
const upcoming = next != null
|
|
75
72
|
const totalSets = plan.reduce((sum, e) => sum + e.sets, 0)
|
|
73
|
+
const onSurface = onSurfaceColors(useSurfaceMode())
|
|
76
74
|
|
|
77
75
|
const hasPace = !upcoming && budgetMs != null && elapsedMs != null
|
|
78
76
|
const target = hasPace ? (elapsedMs as number) / (budgetMs as number) : undefined
|
|
79
77
|
|
|
80
78
|
const setsLabel = upcoming ? `${totalSets} sets` : `${Math.floor(setsDone)}/${totalSets} sets`
|
|
81
79
|
const setsLabelColor = upcoming
|
|
82
|
-
?
|
|
80
|
+
? onSurface.secondary
|
|
83
81
|
: paceToneColor(paceTone(totalSets > 0 ? setsDone / totalSets : 0, target))
|
|
84
82
|
|
|
85
83
|
return (
|
|
86
|
-
<
|
|
84
|
+
<Surface
|
|
85
|
+
level="background"
|
|
87
86
|
className={className}
|
|
88
87
|
style={[
|
|
89
88
|
{
|
|
90
|
-
backgroundColor: HEADER_BG,
|
|
91
89
|
paddingTop: 11,
|
|
92
90
|
paddingRight: 12,
|
|
93
91
|
paddingBottom: 12,
|
|
@@ -106,7 +104,7 @@ export function SessionHeader({
|
|
|
106
104
|
lineHeight: 18,
|
|
107
105
|
fontWeight: '700',
|
|
108
106
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
109
|
-
color:
|
|
107
|
+
color: onSurface.primary,
|
|
110
108
|
marginBottom: 10,
|
|
111
109
|
}}
|
|
112
110
|
testID="session-rail-title"
|
|
@@ -148,6 +146,6 @@ export function SessionHeader({
|
|
|
148
146
|
/>
|
|
149
147
|
</View>
|
|
150
148
|
</View>
|
|
151
|
-
</
|
|
149
|
+
</Surface>
|
|
152
150
|
)
|
|
153
151
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import { View, Text } from 'react-native'
|
|
3
3
|
import { primitiveRamps } from '../../../theme/tokens/primitives'
|
|
4
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
4
5
|
import { SessionRail, type SessionRailExercise } from './SessionRail'
|
|
5
6
|
|
|
7
|
+
const t = getSemanticColors('dark')
|
|
8
|
+
|
|
6
9
|
/**
|
|
7
10
|
* `SessionRail` (shell organism) — the live-workout exercise list: a flat raised
|
|
8
11
|
* `SessionHeader` glance (title, stat tiles, chunked pace bar) over a sunk, inset list
|
|
@@ -20,7 +23,7 @@ const meta: Meta<typeof SessionRail> = {
|
|
|
20
23
|
},
|
|
21
24
|
decorators: [
|
|
22
25
|
(Story) => (
|
|
23
|
-
<View className="min-h-screen flex-row" style={{ backgroundColor: '
|
|
26
|
+
<View className="min-h-screen flex-row" style={{ backgroundColor: t['background-base'] }}>
|
|
24
27
|
<Story />
|
|
25
28
|
<View className="flex-1 items-center justify-center">
|
|
26
29
|
<Text style={{ color: '#6B7280', fontSize: 12 }}>main viewport</Text>
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
import { View, type ViewProps } from 'react-native'
|
|
3
3
|
import { primitiveColors } from '../../../theme/tokens/primitives'
|
|
4
4
|
import { neumorphicShadows } from '../../../theme/shadows'
|
|
5
|
+
import { Surface } from '../../ui/surface'
|
|
5
6
|
import { ExerciseCardHeading } from './ExerciseCardHeading'
|
|
6
7
|
import { SessionHeader } from './SessionHeader'
|
|
7
8
|
import type { MetricTileData } from './MetricTiles'
|
|
8
9
|
import type { SetStripSet } from './SetStrip'
|
|
9
10
|
import type { ExerciseIndicatorKind } from './ExerciseIndicator'
|
|
10
11
|
|
|
11
|
-
//
|
|
12
|
-
// ONE dark plane (
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
const
|
|
18
|
-
const DIVIDER = primitiveColors.charcoal[300] // #2C2C2C — row divider (raised to read on #191919)
|
|
12
|
+
// Warm-tapered ramp surfaces (the locked S3 shell shades): the nav + the heading plane read as
|
|
13
|
+
// ONE dark plane (background shell, #1C1916, owned by SessionHeader's `<Surface level="background">`).
|
|
14
|
+
// The exercise list is a LIGHTER inset panel — `<Surface level="elevated">` (#2A2827) —
|
|
15
|
+
// recessed via its inner shadow yet paler than the header, so the transparent
|
|
16
|
+
// exercise headings on it never blend into the header plane. Surface owns both backgrounds,
|
|
17
|
+
// so the rail no longer hand-sets them.
|
|
18
|
+
const DIVIDER = primitiveColors.charcoal[300] // #2C2C2C — row divider (raised to read on surface-elevated #2A2827)
|
|
19
19
|
|
|
20
20
|
const DEFAULT_WIDTH = 246
|
|
21
21
|
|
|
@@ -87,9 +87,10 @@ export function SessionRail({
|
|
|
87
87
|
...props
|
|
88
88
|
}: SessionRailProps) {
|
|
89
89
|
return (
|
|
90
|
-
<
|
|
90
|
+
<Surface
|
|
91
|
+
level="elevated"
|
|
91
92
|
className={className}
|
|
92
|
-
style={[{ width, flexDirection: 'column'
|
|
93
|
+
style={[{ width, flexDirection: 'column' }, style]}
|
|
93
94
|
testID="session-rail"
|
|
94
95
|
{...props}
|
|
95
96
|
>
|
|
@@ -104,8 +105,9 @@ export function SessionRail({
|
|
|
104
105
|
next={next}
|
|
105
106
|
/>
|
|
106
107
|
|
|
107
|
-
<
|
|
108
|
-
|
|
108
|
+
<Surface
|
|
109
|
+
level="elevated"
|
|
110
|
+
style={[{ flex: 1 }, neumorphicShadows.charcoal.pressed.subtle]}
|
|
109
111
|
testID="session-rail-list"
|
|
110
112
|
>
|
|
111
113
|
{exercises.map((ex, i) => (
|
|
@@ -131,7 +133,7 @@ export function SessionRail({
|
|
|
131
133
|
/>
|
|
132
134
|
</View>
|
|
133
135
|
))}
|
|
134
|
-
</
|
|
135
|
-
</
|
|
136
|
+
</Surface>
|
|
137
|
+
</Surface>
|
|
136
138
|
)
|
|
137
139
|
}
|
|
@@ -2,6 +2,9 @@ import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
|
2
2
|
import { View, Text } from 'react-native'
|
|
3
3
|
import { SupersetWrapper } from './SupersetWrapper'
|
|
4
4
|
import { ExerciseCard } from './ExerciseCard'
|
|
5
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
6
|
+
|
|
7
|
+
const t = getSemanticColors('dark')
|
|
5
8
|
|
|
6
9
|
const meta: Meta<typeof SupersetWrapper> = {
|
|
7
10
|
title: 'Workout/SupersetWrapper',
|
|
@@ -9,7 +12,7 @@ const meta: Meta<typeof SupersetWrapper> = {
|
|
|
9
12
|
tags: ['autodocs'],
|
|
10
13
|
decorators: [
|
|
11
14
|
(Story) => (
|
|
12
|
-
<View style={{ maxWidth: 400, padding: 16, backgroundColor: '
|
|
15
|
+
<View style={{ maxWidth: 400, padding: 16, backgroundColor: t['background-base'] }}>
|
|
13
16
|
<Story />
|
|
14
17
|
</View>
|
|
15
18
|
),
|
|
@@ -26,24 +29,20 @@ export const Default: Story = {
|
|
|
26
29
|
<View
|
|
27
30
|
style={{
|
|
28
31
|
padding: 12,
|
|
29
|
-
backgroundColor: '
|
|
32
|
+
backgroundColor: t['surface-raised'],
|
|
30
33
|
borderRadius: 8,
|
|
31
34
|
}}
|
|
32
35
|
>
|
|
33
|
-
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>
|
|
34
|
-
Exercise A
|
|
35
|
-
</Text>
|
|
36
|
+
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>Exercise A</Text>
|
|
36
37
|
</View>
|
|
37
38
|
<View
|
|
38
39
|
style={{
|
|
39
40
|
padding: 12,
|
|
40
|
-
backgroundColor: '
|
|
41
|
+
backgroundColor: t['surface-raised'],
|
|
41
42
|
borderRadius: 8,
|
|
42
43
|
}}
|
|
43
44
|
>
|
|
44
|
-
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>
|
|
45
|
-
Exercise B
|
|
46
|
-
</Text>
|
|
45
|
+
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>Exercise B</Text>
|
|
47
46
|
</View>
|
|
48
47
|
</>
|
|
49
48
|
),
|
|
@@ -58,24 +57,20 @@ export const CustomLabel: Story = {
|
|
|
58
57
|
<View
|
|
59
58
|
style={{
|
|
60
59
|
padding: 12,
|
|
61
|
-
backgroundColor: '
|
|
60
|
+
backgroundColor: t['surface-raised'],
|
|
62
61
|
borderRadius: 8,
|
|
63
62
|
}}
|
|
64
63
|
>
|
|
65
|
-
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>
|
|
66
|
-
Exercise A1
|
|
67
|
-
</Text>
|
|
64
|
+
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>Exercise A1</Text>
|
|
68
65
|
</View>
|
|
69
66
|
<View
|
|
70
67
|
style={{
|
|
71
68
|
padding: 12,
|
|
72
|
-
backgroundColor: '
|
|
69
|
+
backgroundColor: t['surface-raised'],
|
|
73
70
|
borderRadius: 8,
|
|
74
71
|
}}
|
|
75
72
|
>
|
|
76
|
-
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>
|
|
77
|
-
Exercise A2
|
|
78
|
-
</Text>
|
|
73
|
+
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>Exercise A2</Text>
|
|
79
74
|
</View>
|
|
80
75
|
</>
|
|
81
76
|
),
|
|
@@ -90,24 +85,20 @@ export const CustomColor: Story = {
|
|
|
90
85
|
<View
|
|
91
86
|
style={{
|
|
92
87
|
padding: 12,
|
|
93
|
-
backgroundColor: '
|
|
88
|
+
backgroundColor: t['surface-raised'],
|
|
94
89
|
borderRadius: 8,
|
|
95
90
|
}}
|
|
96
91
|
>
|
|
97
|
-
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>
|
|
98
|
-
Exercise A
|
|
99
|
-
</Text>
|
|
92
|
+
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>Exercise A</Text>
|
|
100
93
|
</View>
|
|
101
94
|
<View
|
|
102
95
|
style={{
|
|
103
96
|
padding: 12,
|
|
104
|
-
backgroundColor: '
|
|
97
|
+
backgroundColor: t['surface-raised'],
|
|
105
98
|
borderRadius: 8,
|
|
106
99
|
}}
|
|
107
100
|
>
|
|
108
|
-
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>
|
|
109
|
-
Exercise B
|
|
110
|
-
</Text>
|
|
101
|
+
<Text style={{ color: '#F3F4F6', fontFamily: 'Inter, sans-serif' }}>Exercise B</Text>
|
|
111
102
|
</View>
|
|
112
103
|
</>
|
|
113
104
|
),
|
|
@@ -12,7 +12,7 @@ export interface SupersetWrapperProps {
|
|
|
12
12
|
const DEFAULTS = {
|
|
13
13
|
label: 'SS',
|
|
14
14
|
color: getSemanticColors('dark')['brand-primary'],
|
|
15
|
-
bgBase: '
|
|
15
|
+
bgBase: getSemanticColors('dark')['background-base'],
|
|
16
16
|
} as const
|
|
17
17
|
|
|
18
18
|
export function SupersetWrapper({
|
|
@@ -84,11 +84,7 @@ function activeNumberTone(elapsedMs: number, targetMs: number | null): string {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/** The active number: `countup` elapsed (→ target) or `countdown` remaining (→ 0.0, then −). */
|
|
87
|
-
function liveReadoutText(
|
|
88
|
-
elapsedMs: number,
|
|
89
|
-
targetMs: number,
|
|
90
|
-
readout: TempoLiveReadout,
|
|
91
|
-
): string {
|
|
87
|
+
function liveReadoutText(elapsedMs: number, targetMs: number, readout: TempoLiveReadout): string {
|
|
92
88
|
const seconds = readout === 'countup' ? elapsedMs / 1000 : (targetMs - elapsedMs) / 1000
|
|
93
89
|
return seconds.toFixed(1)
|
|
94
90
|
}
|
|
@@ -308,7 +304,7 @@ export function TempoDisplay({
|
|
|
308
304
|
style={{
|
|
309
305
|
flexDirection: 'row',
|
|
310
306
|
alignItems: 'center',
|
|
311
|
-
backgroundColor: '
|
|
307
|
+
backgroundColor: t['surface-raised'],
|
|
312
308
|
paddingHorizontal: chromePadX,
|
|
313
309
|
paddingVertical: chromePadY,
|
|
314
310
|
borderRadius: chromeRadius,
|
|
@@ -378,7 +374,7 @@ export function TempoDisplay({
|
|
|
378
374
|
>
|
|
379
375
|
<View
|
|
380
376
|
style={{
|
|
381
|
-
backgroundColor: '
|
|
377
|
+
backgroundColor: t['surface-overlay'],
|
|
382
378
|
borderRadius: 6,
|
|
383
379
|
paddingVertical: 8,
|
|
384
380
|
paddingHorizontal: 12,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import { View } from 'react-native'
|
|
3
3
|
import { VolumeLandmarkBar } from './VolumeLandmarkBar'
|
|
4
|
+
import { getSemanticColors } from '../../../theme/tokens/semantic'
|
|
5
|
+
|
|
6
|
+
const t = getSemanticColors('dark')
|
|
4
7
|
|
|
5
8
|
const meta: Meta<typeof VolumeLandmarkBar> = {
|
|
6
9
|
title: 'Workout/DataViz/VolumeLandmarkBar',
|
|
@@ -28,7 +31,7 @@ const meta: Meta<typeof VolumeLandmarkBar> = {
|
|
|
28
31
|
},
|
|
29
32
|
decorators: [
|
|
30
33
|
(Story) => (
|
|
31
|
-
<View style={{ padding: 24, paddingBottom: 40, backgroundColor: '
|
|
34
|
+
<View style={{ padding: 24, paddingBottom: 40, backgroundColor: t['background-base'] }}>
|
|
32
35
|
<Story />
|
|
33
36
|
</View>
|
|
34
37
|
),
|
|
@@ -26,7 +26,7 @@ const statusBgColors: Record<WorkoutPillStatus, string> = {
|
|
|
26
26
|
completed: 'rgba(46,213,115,0.15)',
|
|
27
27
|
current: 'rgba(255,121,0,0.15)',
|
|
28
28
|
next: 'transparent',
|
|
29
|
-
upcoming: '
|
|
29
|
+
upcoming: t['surface-raised'],
|
|
30
30
|
missed: 'rgba(209,67,67,0.1)',
|
|
31
31
|
deload: 'rgba(186,41,150,0.15)',
|
|
32
32
|
}
|
|
@@ -72,7 +72,7 @@ function usePulse(enabled: boolean) {
|
|
|
72
72
|
easing: Easing.inOut(Easing.ease),
|
|
73
73
|
useNativeDriver: true,
|
|
74
74
|
}),
|
|
75
|
-
])
|
|
75
|
+
])
|
|
76
76
|
)
|
|
77
77
|
animation.start()
|
|
78
78
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
2
|
import { View, Text } from 'react-native'
|
|
3
3
|
import { cn } from '../../utils/cn'
|
|
4
|
+
import { Surface } from '../ui/surface'
|
|
4
5
|
import { SideNav, type SideNavItem } from './SideNav'
|
|
5
6
|
import { TopBar } from './TopBar'
|
|
6
7
|
import { type Device } from './DeviceRow'
|
|
@@ -60,13 +61,15 @@ export function DashboardShell({
|
|
|
60
61
|
return (
|
|
61
62
|
// Column: the TopBar spans the FULL width across the top, and the SideNav sits BELOW it
|
|
62
63
|
// in the content row (not a full-height left rail). This keeps the brand/status band
|
|
63
|
-
// unbroken edge-to-edge and lets the nav align under it.
|
|
64
|
-
|
|
64
|
+
// unbroken edge-to-edge and lets the nav align under it. The shell is the outermost
|
|
65
|
+
// Surface — it owns the base plane and seeds the on-surface colour context (mode) for
|
|
66
|
+
// the whole dashboard tree.
|
|
67
|
+
<Surface level="base" className={cn('flex-1', className)}>
|
|
65
68
|
<TopBar state={state} devices={devices} subtitle={subtitle} onSelectDevice={onSelectDevice} />
|
|
66
69
|
<View className="flex-1 flex-row">
|
|
67
70
|
<SideNav activeKey={activeKey} items={navItems} liveKey={liveKey} onNavigate={onNavigate} />
|
|
68
71
|
<View className="flex-1">{children ?? <ContentPlaceholder />}</View>
|
|
69
72
|
</View>
|
|
70
|
-
</
|
|
73
|
+
</Surface>
|
|
71
74
|
)
|
|
72
75
|
}
|