@titan-design/react-ui 0.11.0 → 0.12.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 +173 -343
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +173 -343
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +24 -21
- package/dist/index.d.ts +24 -21
- package/dist/index.js +366 -561
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +360 -553
- package/dist/index.mjs.map +1 -1
- package/dist/pages.js +242 -407
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +242 -407
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +409 -415
- package/dist/theme/index.d.ts +409 -415
- package/dist/theme/index.js +234 -408
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +227 -399
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +141 -140
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +141 -140
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +1 -1
- package/src/arch/Architecture.stories.tsx +9 -9
- package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
- package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +3 -3
- package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
- package/src/components/custom/Fatigue/GhostSpark.stories.tsx +3 -3
- package/src/components/custom/Fatigue/LiveFatigueCard.tsx +1 -1
- package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +2 -2
- package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
- package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +4 -4
- package/src/components/custom/Fatigue/VelocityHero.stories.tsx +3 -3
- package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
- package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -12
- package/src/components/custom/Sidebar/Sidebar.tsx +4 -4
- package/src/components/custom/Table/Table.tsx +2 -2
- package/src/components/custom/Workout/ActiveWorkoutPage.tsx +3 -3
- package/src/components/custom/Workout/BaseBadge.test.tsx +6 -1
- package/src/components/custom/Workout/BaseBadge.tsx +1 -1
- package/src/components/custom/Workout/BodyMap.tsx +2 -2
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +2 -2
- package/src/components/custom/Workout/DeviationBar.test.tsx +2 -1
- package/src/components/custom/Workout/DeviationBar.tsx +3 -2
- package/src/components/custom/Workout/ExerciseCard.test.tsx +3 -3
- package/src/components/custom/Workout/ExerciseCard.tsx +2 -2
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +4 -4
- package/src/components/custom/Workout/InputBar.tsx +2 -2
- package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +1 -1
- package/src/components/custom/Workout/LiveAuraFrame.test.tsx +1 -1
- package/src/components/custom/Workout/LiveAuraFrame.tsx +3 -3
- package/src/components/custom/Workout/MesoCard.tsx +3 -1
- package/src/components/custom/Workout/MuscleGroupChip.tsx +4 -3
- package/src/components/custom/Workout/PrHistoryModal.tsx +2 -2
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +1 -1
- package/src/components/custom/Workout/ReadinessCheck.tsx +2 -2
- package/src/components/custom/Workout/RestTimer.tsx +2 -2
- package/src/components/custom/Workout/S3SetTypes.stories.tsx +3 -3
- package/src/components/custom/Workout/SessionHeader.stories.tsx +2 -2
- package/src/components/custom/Workout/SessionHeader.tsx +1 -1
- package/src/components/custom/Workout/SessionRail.stories.tsx +2 -2
- package/src/components/custom/Workout/SessionRail.tsx +13 -5
- package/src/components/custom/Workout/SetBar.tsx +3 -3
- package/src/components/custom/Workout/SetRow.test.tsx +6 -3
- package/src/components/custom/Workout/StatusDot.tsx +5 -4
- package/src/components/custom/Workout/StrengthTrendChart.tsx +1 -1
- package/src/components/custom/Workout/TrainingStatusPage.tsx +2 -2
- package/src/components/custom/Workout/VelocityStrip.test.tsx +5 -2
- package/src/components/custom/Workout/VelocityStrip.tsx +4 -4
- package/src/components/custom/Workout/VolumeLandmarkBar.tsx +3 -3
- package/src/components/custom/Workout/WeightBadge.test.tsx +6 -1
- package/src/components/custom/Workout/WeightBadge.tsx +2 -1
- package/src/components/custom/Workout/WorkoutCard.tsx +3 -1
- package/src/components/custom/Workout/WorkoutPill.tsx +5 -2
- package/src/components/custom/Workout/ZoneTrack.tsx +4 -4
- package/src/components/custom/Workout/setHeadingKit.tsx +14 -8
- package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
- package/src/components/custom/charts/SetBarChart.tsx +3 -3
- package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
- package/src/components/custom/stepper/Stepper.tsx +3 -3
- package/src/components/shell/DeviceMenu.tsx +2 -2
- package/src/components/shell/SideNav.tsx +1 -1
- package/src/components/shell/TopBar.tsx +1 -1
- package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
- package/src/components/ui/autocomplete/Autocomplete.tsx +1 -1
- package/src/components/ui/avatar/Avatar.tsx +2 -2
- package/src/components/ui/badge/Badge.tsx +2 -2
- package/src/components/ui/card/Card.tsx +3 -3
- package/src/components/ui/checkbox/Checkbox.tsx +1 -1
- package/src/components/ui/collapse/Collapse.tsx +1 -1
- package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
- package/src/components/ui/drawer/Drawer.tsx +3 -3
- package/src/components/ui/form-field/FormField.tsx +1 -1
- package/src/components/ui/help-tip/HelpTip.tsx +1 -1
- package/src/components/ui/menu/Menu.tsx +2 -2
- package/src/components/ui/pill/Pill.tsx +2 -2
- package/src/components/ui/popover/Popover.stories.tsx +2 -2
- package/src/components/ui/popover/Popover.tsx +1 -1
- package/src/components/ui/progress/Progress.tsx +3 -3
- package/src/components/ui/radio/Radio.stories.tsx +1 -1
- package/src/components/ui/radio/Radio.tsx +4 -4
- package/src/components/ui/select/Select.tsx +3 -3
- package/src/components/ui/surface/Surface.stories.tsx +3 -3
- package/src/components/ui/surface/Surface.test.tsx +32 -19
- package/src/components/ui/surface/Surface.tsx +3 -3
- package/src/components/ui/surface/SurfaceContext.ts +19 -29
- package/src/components/ui/surface/surface.contract.test.ts +57 -44
- package/src/components/ui/switch/Switch.tsx +1 -1
- package/src/components/ui/tabs/Tabs.tsx +2 -2
- package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +5 -5
- package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +1 -1
- package/src/components/ui/toolbar-button/ToolbarButton.tsx +36 -22
- package/src/stories/PresetShowcase.stories.tsx +21 -21
- package/src/theme/ColorPalettes.stories.tsx +41 -38
- package/src/theme/ColorPrimitives.stories.tsx +89 -41
- package/src/theme/Depth.stories.tsx +312 -0
- package/src/theme/DepthCalibration.stories.tsx +655 -0
- package/src/theme/ThemeProvider.tsx +1 -1
- package/src/theme/barrel.ts +7 -14
- package/src/theme/color-stories.coverage.test.ts +15 -20
- package/src/theme/color-story-kit.tsx +1 -1
- package/src/theme/color-utils.ts +197 -0
- package/src/theme/config.ts +0 -8
- package/src/theme/depth-calibration.test.tsx +97 -0
- package/src/theme/elevation.test.ts +62 -1
- package/src/theme/elevation.ts +34 -8
- package/src/theme/global.css +47 -53
- package/src/theme/grey-ramp.test.ts +166 -0
- package/src/theme/materials.test.ts +106 -0
- package/src/theme/materials.ts +211 -0
- package/src/theme/presets/audiobook.ts +4 -4
- package/src/theme/presets/types.ts +3 -3
- package/src/theme/semantic-contrast.test.ts +83 -0
- package/src/theme/tokens/primitives.ts +62 -115
- package/src/theme/tokens/semantic.ts +130 -82
- package/src/utils/colors.ts +1 -1
- package/tailwind.config.js +2 -5
- package/src/theme/bar-paper.ts +0 -59
- package/src/theme/shadows.stories.tsx +0 -523
- package/src/theme/shadows.ts +0 -439
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { View, Text } from 'react-native'
|
|
3
|
+
import { greyRamp } from './tokens/primitives'
|
|
4
|
+
import { getSemanticColors } from './tokens/semantic'
|
|
5
|
+
import {
|
|
6
|
+
getElevationSurface,
|
|
7
|
+
getElevationShadow,
|
|
8
|
+
getBaseSurfaceColor,
|
|
9
|
+
FLOATING_ELEVATION_MIN,
|
|
10
|
+
type ElevationLevel,
|
|
11
|
+
} from './elevation'
|
|
12
|
+
import { paperSheet, insetWell, barPaper } from './materials'
|
|
13
|
+
import { SectionIntro, SectionTitle } from './color-story-kit'
|
|
14
|
+
|
|
15
|
+
const t = getSemanticColors('dark')
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Foundations/Depth — how a surface says how far away it is.
|
|
19
|
+
*
|
|
20
|
+
* There are exactly three mechanisms, and which one applies is not a taste call:
|
|
21
|
+
*
|
|
22
|
+
* TONE how deep a plane sits — the grey ramp
|
|
23
|
+
* HAIRLINE where one plane ends — alpha, self-normalising
|
|
24
|
+
* MATERIAL what a plane is made of — paper, well
|
|
25
|
+
*
|
|
26
|
+
* Drop-shadow is deliberately not on that list for anything inline. This page
|
|
27
|
+
* exists because the system previously had a fourth mechanism — a neumorphic
|
|
28
|
+
* dual-opposing shadow — that could not work here and was removed in TD-07.16.
|
|
29
|
+
*/
|
|
30
|
+
const meta: Meta = {
|
|
31
|
+
title: 'Foundations/Depth',
|
|
32
|
+
tags: ['autodocs'],
|
|
33
|
+
}
|
|
34
|
+
export default meta
|
|
35
|
+
|
|
36
|
+
const CONTENT_LEVELS: ElevationLevel[] = [0, 1, 2, 3]
|
|
37
|
+
const FLOATING_LEVELS: ElevationLevel[] = [4, 5]
|
|
38
|
+
const base = getBaseSurfaceColor('dark')
|
|
39
|
+
|
|
40
|
+
function Swatch({
|
|
41
|
+
label,
|
|
42
|
+
note,
|
|
43
|
+
style,
|
|
44
|
+
}: {
|
|
45
|
+
label: string
|
|
46
|
+
note: string
|
|
47
|
+
style: Record<string, unknown>
|
|
48
|
+
}) {
|
|
49
|
+
return (
|
|
50
|
+
<View style={{ width: 190 }}>
|
|
51
|
+
<View
|
|
52
|
+
style={{
|
|
53
|
+
height: 92,
|
|
54
|
+
borderRadius: 10,
|
|
55
|
+
padding: 10,
|
|
56
|
+
justifyContent: 'flex-end',
|
|
57
|
+
...style,
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<Text className="text-text-primary" style={{ fontSize: 12, fontWeight: '600' }}>
|
|
61
|
+
{label}
|
|
62
|
+
</Text>
|
|
63
|
+
</View>
|
|
64
|
+
<Text className="text-text-tertiary" style={{ fontSize: 9, marginTop: 4, lineHeight: 13 }}>
|
|
65
|
+
{note}
|
|
66
|
+
</Text>
|
|
67
|
+
</View>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const Mechanisms: StoryObj = {
|
|
72
|
+
name: '1. The three mechanisms',
|
|
73
|
+
render: () => (
|
|
74
|
+
<View style={{ padding: 24, backgroundColor: greyRamp[975] }}>
|
|
75
|
+
<Text className="text-2xl font-bold text-text-primary mb-2">Depth</Text>
|
|
76
|
+
<SectionIntro>
|
|
77
|
+
Three mechanisms, in the order you should reach for them. A surface that needs to read as
|
|
78
|
+
deeper takes a TONE; one that needs an edge takes a HAIRLINE; one that needs to feel
|
|
79
|
+
physical takes a MATERIAL. Drop-shadow is not on the list for anything that is not
|
|
80
|
+
floating — see section 3 for why.
|
|
81
|
+
</SectionIntro>
|
|
82
|
+
|
|
83
|
+
<SectionTitle>Tone — the grey ramp</SectionTitle>
|
|
84
|
+
<Text className="text-text-secondary text-xs mb-3">
|
|
85
|
+
The primary cue and the only one that works identically on web and native. Every plane is
|
|
86
|
+
a ramp step.
|
|
87
|
+
</Text>
|
|
88
|
+
<View style={{ flexDirection: 'row', gap: 10, marginBottom: 22 }}>
|
|
89
|
+
{[975, 950, 925, 900, 875, 850].map((step) => (
|
|
90
|
+
<Swatch
|
|
91
|
+
key={step}
|
|
92
|
+
label={`grey-${step}`}
|
|
93
|
+
note=""
|
|
94
|
+
style={{ backgroundColor: greyRamp[step as keyof typeof greyRamp] }}
|
|
95
|
+
/>
|
|
96
|
+
))}
|
|
97
|
+
</View>
|
|
98
|
+
|
|
99
|
+
<SectionTitle>Hairline — where a plane ends</SectionTitle>
|
|
100
|
+
<Text className="text-text-secondary text-xs mb-3">
|
|
101
|
+
Alpha-white, so it composites toward white by the same amount on any background and holds
|
|
102
|
+
a near-constant ΔL* wherever it lands. A solid border swings wildly across the ramp; this
|
|
103
|
+
does not. It is the default separator, and it is what replaced the solid dark border
|
|
104
|
+
tokens.
|
|
105
|
+
</Text>
|
|
106
|
+
<View style={{ flexDirection: 'row', gap: 10, marginBottom: 22 }}>
|
|
107
|
+
{(['hairline-subtle', 'hairline-default', 'hairline-strong'] as const).map((token) => (
|
|
108
|
+
<Swatch
|
|
109
|
+
key={token}
|
|
110
|
+
label={token.replace('hairline-', '')}
|
|
111
|
+
note={t[token]}
|
|
112
|
+
style={{
|
|
113
|
+
backgroundColor: greyRamp[925],
|
|
114
|
+
borderWidth: 1,
|
|
115
|
+
borderColor: t[token],
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
118
|
+
))}
|
|
119
|
+
</View>
|
|
120
|
+
|
|
121
|
+
<SectionTitle>Material — what a plane is made of</SectionTitle>
|
|
122
|
+
<Text className="text-text-secondary text-xs mb-3">
|
|
123
|
+
Used sparingly. Paper is for HERO surfaces only and takes muted tones only — vivid colour
|
|
124
|
+
is ink ON paper, never the paper itself. There are no levels of paper; one treatment, or
|
|
125
|
+
the texture stops meaning anything.
|
|
126
|
+
</Text>
|
|
127
|
+
<View style={{ flexDirection: 'row', gap: 10, marginBottom: 8 }}>
|
|
128
|
+
<Swatch
|
|
129
|
+
label="paperSheet"
|
|
130
|
+
note="tonal fill (ΔL* ≤ 3) + grain + dither + rim + contact shadow. Hero surfaces."
|
|
131
|
+
style={paperSheet(greyRamp[875]) as Record<string, unknown>}
|
|
132
|
+
/>
|
|
133
|
+
<Swatch
|
|
134
|
+
label="insetWell"
|
|
135
|
+
note="inner top cut + a light line on the floor. The floor rim is the half that says 'below'."
|
|
136
|
+
style={insetWell(greyRamp[950]) as Record<string, unknown>}
|
|
137
|
+
/>
|
|
138
|
+
<Swatch
|
|
139
|
+
label="barPaper"
|
|
140
|
+
note="the same grain curve, tuned for a small saturated element."
|
|
141
|
+
style={{ ...(barPaper(t['status-info']) as Record<string, unknown>), backgroundColor: t['status-info'] }}
|
|
142
|
+
/>
|
|
143
|
+
</View>
|
|
144
|
+
<Text className="text-text-tertiary text-xs">
|
|
145
|
+
Materials are web/RNW only — `backgroundImage` and multi-layer `boxShadow` are ignored on
|
|
146
|
+
native. Every material keeps a solid `backgroundColor` underneath so a surface never
|
|
147
|
+
depends on one, and a material must never be the only thing carrying meaning.
|
|
148
|
+
</Text>
|
|
149
|
+
</View>
|
|
150
|
+
),
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export const Elevation: StoryObj = {
|
|
154
|
+
name: '2. Elevation — tone below, shadow only when floating',
|
|
155
|
+
render: () => (
|
|
156
|
+
<View style={{ padding: 24, backgroundColor: greyRamp[975] }}>
|
|
157
|
+
<Text className="text-2xl font-bold text-text-primary mb-2">Elevation</Text>
|
|
158
|
+
<SectionIntro>
|
|
159
|
+
Levels 0–3 are separated by TONE ALONE. They cast no shadow, because a dark-on-dark drop
|
|
160
|
+
shadow is inert — it costs a composite layer and shows nothing. From{' '}
|
|
161
|
+
<Text className="font-semibold">{FLOATING_ELEVATION_MIN}</Text> up the element is
|
|
162
|
+
genuinely floating over a backdrop, where a large soft shadow describes separation rather
|
|
163
|
+
than rank, and there the shadow returns.
|
|
164
|
+
</SectionIntro>
|
|
165
|
+
|
|
166
|
+
<SectionTitle>Content levels — tone only</SectionTitle>
|
|
167
|
+
<View style={{ flexDirection: 'row', gap: 10, marginBottom: 22 }}>
|
|
168
|
+
{CONTENT_LEVELS.map((lv) => (
|
|
169
|
+
<Swatch
|
|
170
|
+
key={lv}
|
|
171
|
+
label={`elevation ${lv}`}
|
|
172
|
+
note={`${getElevationSurface(base, lv, 'dark')} · no shadow`}
|
|
173
|
+
style={{
|
|
174
|
+
backgroundColor: getElevationSurface(base, lv, 'dark'),
|
|
175
|
+
borderWidth: 1,
|
|
176
|
+
borderColor: t['hairline-default'],
|
|
177
|
+
...(getElevationShadow(base, lv, 'dark') as Record<string, unknown>),
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
))}
|
|
181
|
+
</View>
|
|
182
|
+
|
|
183
|
+
<SectionTitle>Floating levels — shadow returns, always with a ring</SectionTitle>
|
|
184
|
+
<View style={{ flexDirection: 'row', gap: 24, marginBottom: 8 }}>
|
|
185
|
+
{FLOATING_LEVELS.map((lv) => (
|
|
186
|
+
<Swatch
|
|
187
|
+
key={lv}
|
|
188
|
+
label={`elevation ${lv}`}
|
|
189
|
+
note={`${getElevationSurface(base, lv, 'dark')} · casts a shadow`}
|
|
190
|
+
style={{
|
|
191
|
+
backgroundColor: getElevationSurface(base, lv, 'dark'),
|
|
192
|
+
borderWidth: 1,
|
|
193
|
+
borderColor: t['hairline-strong'],
|
|
194
|
+
...(getElevationShadow(base, lv, 'dark') as Record<string, unknown>),
|
|
195
|
+
}}
|
|
196
|
+
/>
|
|
197
|
+
))}
|
|
198
|
+
</View>
|
|
199
|
+
<Text className="text-text-tertiary text-xs">
|
|
200
|
+
A floating surface should carry a hairline ring as well as its shadow — the shadow places
|
|
201
|
+
it above the page, the ring gives it an edge that survives on a panel where the shadow is
|
|
202
|
+
washed out by glare.
|
|
203
|
+
</Text>
|
|
204
|
+
</View>
|
|
205
|
+
),
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export const WhyNotNeumorphism: StoryObj = {
|
|
209
|
+
name: '3. Why not neumorphism',
|
|
210
|
+
render: () => (
|
|
211
|
+
<View style={{ padding: 24, backgroundColor: greyRamp[975] }}>
|
|
212
|
+
<Text className="text-2xl font-bold text-text-primary mb-2">Why not neumorphism</Text>
|
|
213
|
+
<SectionIntro>
|
|
214
|
+
The system used to ship a neumorphic builder — a dark shadow bottom-right paired with a
|
|
215
|
+
light rim top-left. It was removed rather than retuned, and the reason is a lightness
|
|
216
|
+
budget rather than a preference, so it is worth being able to see.
|
|
217
|
+
</SectionIntro>
|
|
218
|
+
|
|
219
|
+
<Text className="text-text-secondary text-xs mb-4">
|
|
220
|
+
Neumorphism needs a MID-TONE ground (roughly 75–90% lightness) so the dark half has
|
|
221
|
+
somewhere to fall and the light half has somewhere to rise. Our surfaces sit near 10%.
|
|
222
|
+
Below them there is almost nothing left — so the dark half disappears and the treatment
|
|
223
|
+
collapses to a one-sided rim, which reads as a smudge rather than as depth.
|
|
224
|
+
</Text>
|
|
225
|
+
|
|
226
|
+
<View style={{ flexDirection: 'row', gap: 24 }}>
|
|
227
|
+
<View>
|
|
228
|
+
<Text className="text-text-secondary text-xs mb-2">
|
|
229
|
+
On a mid-tone ground — both halves have room
|
|
230
|
+
</Text>
|
|
231
|
+
<View
|
|
232
|
+
style={{
|
|
233
|
+
backgroundColor: greyRamp[300],
|
|
234
|
+
padding: 26,
|
|
235
|
+
borderRadius: 12,
|
|
236
|
+
flexDirection: 'row',
|
|
237
|
+
gap: 16,
|
|
238
|
+
}}
|
|
239
|
+
>
|
|
240
|
+
<View
|
|
241
|
+
style={
|
|
242
|
+
{
|
|
243
|
+
width: 110,
|
|
244
|
+
height: 66,
|
|
245
|
+
borderRadius: 10,
|
|
246
|
+
backgroundColor: greyRamp[300],
|
|
247
|
+
boxShadow: '3px 3px 6px rgba(0,0,0,0.35), -3px -3px 6px rgba(255,255,255,0.55)',
|
|
248
|
+
} as Record<string, unknown>
|
|
249
|
+
}
|
|
250
|
+
/>
|
|
251
|
+
</View>
|
|
252
|
+
</View>
|
|
253
|
+
|
|
254
|
+
<View>
|
|
255
|
+
<Text className="text-text-secondary text-xs mb-2">
|
|
256
|
+
On our ground — the dark half has nowhere to go
|
|
257
|
+
</Text>
|
|
258
|
+
<View
|
|
259
|
+
style={{
|
|
260
|
+
backgroundColor: greyRamp[925],
|
|
261
|
+
padding: 26,
|
|
262
|
+
borderRadius: 12,
|
|
263
|
+
flexDirection: 'row',
|
|
264
|
+
gap: 16,
|
|
265
|
+
}}
|
|
266
|
+
>
|
|
267
|
+
<View
|
|
268
|
+
style={
|
|
269
|
+
{
|
|
270
|
+
width: 110,
|
|
271
|
+
height: 66,
|
|
272
|
+
borderRadius: 10,
|
|
273
|
+
backgroundColor: greyRamp[925],
|
|
274
|
+
boxShadow: '3px 3px 6px rgba(0,0,0,0.35), -3px -3px 6px rgba(255,255,255,0.12)',
|
|
275
|
+
} as Record<string, unknown>
|
|
276
|
+
}
|
|
277
|
+
/>
|
|
278
|
+
</View>
|
|
279
|
+
</View>
|
|
280
|
+
|
|
281
|
+
<View>
|
|
282
|
+
<Text className="text-text-secondary text-xs mb-2">What we do instead</Text>
|
|
283
|
+
<View
|
|
284
|
+
style={{
|
|
285
|
+
backgroundColor: greyRamp[925],
|
|
286
|
+
padding: 26,
|
|
287
|
+
borderRadius: 12,
|
|
288
|
+
flexDirection: 'row',
|
|
289
|
+
gap: 16,
|
|
290
|
+
}}
|
|
291
|
+
>
|
|
292
|
+
<View
|
|
293
|
+
style={{
|
|
294
|
+
width: 110,
|
|
295
|
+
height: 66,
|
|
296
|
+
borderRadius: 10,
|
|
297
|
+
backgroundColor: greyRamp[900],
|
|
298
|
+
borderWidth: 1,
|
|
299
|
+
borderColor: t['hairline-default'],
|
|
300
|
+
}}
|
|
301
|
+
/>
|
|
302
|
+
</View>
|
|
303
|
+
</View>
|
|
304
|
+
</View>
|
|
305
|
+
|
|
306
|
+
<Text className="text-text-tertiary text-xs mt-4">
|
|
307
|
+
Same treatment, same offsets, different ground. The middle panel is the one that shipped.
|
|
308
|
+
The right panel is one tone step plus a hairline — cheaper, and it survives glare.
|
|
309
|
+
</Text>
|
|
310
|
+
</View>
|
|
311
|
+
),
|
|
312
|
+
}
|