@praxiis/ui 0.0.1 → 0.0.3
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/index.d.mts +3 -111
- package/dist/index.d.ts +3 -111
- package/dist/index.js +6 -200
- package/dist/index.mjs +6 -192
- package/package.json +11 -12
- package/src/README.md +688 -0
- package/src/components/CalendarStrip/CalendarStrip.a11y.ts +51 -0
- package/src/components/CalendarStrip/DayCard/DayCard.a11y.ts +52 -0
- package/src/components/EmptyState/EmptyState.a11y.ts +53 -0
- package/src/components/Header/Header.a11y.ts +82 -0
- package/src/components/ScheduleItem/ScheduleItem/ScheduleItem.a11y.ts +15 -0
- package/src/core/index.ts +1 -1
- package/src/core/restyle/index.ts +1 -1
- package/src/core/restyle/restylePresetRegistry.ts +7 -7
- package/src/index.tsx +2 -11
- package/src/primitives/actions/Button/Button.a11y.ts +38 -0
- package/src/primitives/actions/IconButton/IconButton.a11y.ts +55 -0
- package/src/primitives/content/Avatar/Avatar.a11y.ts +50 -0
- package/src/primitives/content/Badge/Badge.a11y.ts +83 -0
- package/src/primitives/content/Card/Card.a11y.ts +60 -0
- package/src/primitives/content/Chip/Chip.a11y.ts +101 -0
- package/src/primitives/content/Icon/Icon.a11y.ts +43 -0
- package/src/primitives/feedback/ProgressBar/ProgressBar.a11y.ts +68 -0
- package/src/primitives/feedback/Skeleton/Skeleton.a11y.ts +46 -0
- package/src/primitives/feedback/Spinner/Spinner.a11y.ts +47 -0
- package/src/primitives/feedback/Toast/Toast.a11y.ts +75 -0
- package/src/primitives/inputs/Checkbox/Checkbox.a11y.ts +47 -0
- package/src/primitives/inputs/RadioButton/RadioButton.a11y.ts +48 -0
- package/src/primitives/inputs/SegmentedControl/SegmentedControl.a11y.ts +59 -0
- package/src/primitives/inputs/SelectSheet/SelectSheet.a11y.ts +117 -0
- package/src/primitives/inputs/Switch/Switch.a11y.ts +29 -0
- package/src/primitives/inputs/TextInput/TextInput.a11y.ts +77 -0
- package/src/primitives/layout/Divider/Divider.a11y.ts +55 -0
- package/src/primitives/overlays/Modal/Modal.a11y.ts +64 -0
- package/src/providers/ThemeProvider/index.ts +0 -12
- package/src/providers/index.ts +0 -8
- package/src/providers/ThemeProvider/createTheme.ts +0 -304
package/src/README.md
ADDED
|
@@ -0,0 +1,688 @@
|
|
|
1
|
+
# Design System
|
|
2
|
+
|
|
3
|
+
A complete, production-ready design system for React Native (Expo). Built on top of [Shopify Restyle](https://github.com/Shopify/restyle) with full TypeScript support, light/dark theming, i18n, and a comprehensive component library.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Quick Start](#quick-start)
|
|
10
|
+
2. [Theming](#theming)
|
|
11
|
+
- [Built-in Presets](#built-in-presets)
|
|
12
|
+
- [Customizing with buildPair](#customizing-with-buildpair)
|
|
13
|
+
- [Single-mode Override](#single-mode-override)
|
|
14
|
+
- [Building from Scratch](#building-from-scratch)
|
|
15
|
+
3. [Components](#components)
|
|
16
|
+
- [Layout](#layout)
|
|
17
|
+
- [Typography](#typography)
|
|
18
|
+
- [Actions](#actions)
|
|
19
|
+
- [Content](#content)
|
|
20
|
+
- [Inputs](#inputs)
|
|
21
|
+
- [Feedback](#feedback)
|
|
22
|
+
- [Overlays](#overlays)
|
|
23
|
+
- [Composite Components](#composite-components)
|
|
24
|
+
4. [i18n / Labels](#i18n--labels)
|
|
25
|
+
5. [Tokens](#tokens)
|
|
26
|
+
6. [Hooks](#hooks)
|
|
27
|
+
7. [Utilities](#utilities)
|
|
28
|
+
8. [TypeScript Reference](#typescript-reference)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
Wrap your app with `DesignSystemProvider`. All components automatically pick up the active theme and color scheme.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { DesignSystemProvider } from "@design-system";
|
|
38
|
+
|
|
39
|
+
export default function App() {
|
|
40
|
+
return (
|
|
41
|
+
<DesignSystemProvider>
|
|
42
|
+
<YourApp />
|
|
43
|
+
</DesignSystemProvider>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### With language
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<DesignSystemProvider language="es">
|
|
52
|
+
<YourApp />
|
|
53
|
+
</DesignSystemProvider>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### With a custom theme
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { DesignSystemProvider, buildPair } from "@design-system";
|
|
60
|
+
import { myTheme } from "./theme";
|
|
61
|
+
|
|
62
|
+
<DesignSystemProvider
|
|
63
|
+
lightTheme={myTheme.light}
|
|
64
|
+
darkTheme={myTheme.dark}
|
|
65
|
+
>
|
|
66
|
+
<YourApp />
|
|
67
|
+
</DesignSystemProvider>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Theming
|
|
73
|
+
|
|
74
|
+
The design system ships with default light and dark themes. You can keep them, extend them with a few color overrides, or replace them entirely.
|
|
75
|
+
|
|
76
|
+
All theme building utilities are exported from `@design-system`.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Built-in Presets
|
|
81
|
+
|
|
82
|
+
Six ready-to-use theme pairs, all with light + dark modes:
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import { DesignSystemProvider, restylePresetThemes } from "@design-system";
|
|
86
|
+
|
|
87
|
+
// Available: horizon | sage | sunset | ocean | lavender | rose
|
|
88
|
+
const { light, dark } = restylePresetThemes.ocean;
|
|
89
|
+
|
|
90
|
+
<DesignSystemProvider lightTheme={light} darkTheme={dark}>
|
|
91
|
+
<YourApp />
|
|
92
|
+
</DesignSystemProvider>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Customizing with `buildPair`
|
|
98
|
+
|
|
99
|
+
**The recommended path.** Supply accent color overrides for light and dark modes. Everything else (backgrounds, surfaces, typography colors, feedback colors) is inherited from the defaults.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import {
|
|
103
|
+
buildPair,
|
|
104
|
+
DesignSystemProvider,
|
|
105
|
+
type DeepPartial,
|
|
106
|
+
type RestyleThemePair,
|
|
107
|
+
type ThemeColors,
|
|
108
|
+
} from "@design-system";
|
|
109
|
+
|
|
110
|
+
const myTheme: RestyleThemePair = buildPair(
|
|
111
|
+
// light mode overrides
|
|
112
|
+
{
|
|
113
|
+
accent: {
|
|
114
|
+
primary: "#1877F2",
|
|
115
|
+
primaryHover: "#166FE5",
|
|
116
|
+
primaryPressed: "#0E5FC2",
|
|
117
|
+
secondary: "#42A5F5",
|
|
118
|
+
secondaryHover: "#1877F2",
|
|
119
|
+
secondaryPressed: "#166FE5",
|
|
120
|
+
},
|
|
121
|
+
text: { link: "#1877F2" },
|
|
122
|
+
border: { focus: "#1877F2" },
|
|
123
|
+
} satisfies DeepPartial<ThemeColors>,
|
|
124
|
+
// dark mode overrides
|
|
125
|
+
{
|
|
126
|
+
accent: {
|
|
127
|
+
primary: "#2D88FF",
|
|
128
|
+
primaryHover: "#5BA3FF",
|
|
129
|
+
primaryPressed: "#1877F2",
|
|
130
|
+
secondary: "#1877F2",
|
|
131
|
+
secondaryHover: "#2D88FF",
|
|
132
|
+
secondaryPressed: "#166FE5",
|
|
133
|
+
},
|
|
134
|
+
text: { link: "#2D88FF" },
|
|
135
|
+
border: { focus: "#2D88FF" },
|
|
136
|
+
} satisfies DeepPartial<ThemeColors>,
|
|
137
|
+
);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### What you can override
|
|
141
|
+
|
|
142
|
+
`buildPair` accepts `DeepPartial<ThemeColors>` — override any subset:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
ThemeColors
|
|
146
|
+
├── background { primary, secondary, tertiary, inverse }
|
|
147
|
+
├── surface { primary, secondary, elevated, overlay }
|
|
148
|
+
├── text { primary, secondary, tertiary, disabled, inverse, link }
|
|
149
|
+
├── border { default, subtle, strong, focus }
|
|
150
|
+
├── accent { primary, primaryHover, primaryPressed,
|
|
151
|
+
│ secondary, secondaryHover, secondaryPressed }
|
|
152
|
+
├── interactive { default, hover, pressed, disabled }
|
|
153
|
+
├── feedback { success, successLight, successDark,
|
|
154
|
+
│ warning, warningLight, warningDark,
|
|
155
|
+
│ error, errorLight, errorDark,
|
|
156
|
+
│ info, infoLight, infoDark }
|
|
157
|
+
└── special { skeleton, divider, scrim }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### Single-mode Override
|
|
163
|
+
|
|
164
|
+
Use `buildRestyleThemeFromThemeColors` when you want full control over a single mode, merging overrides into your chosen base palette:
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import {
|
|
168
|
+
buildRestyleThemeFromThemeColors,
|
|
169
|
+
lightSemanticColors,
|
|
170
|
+
darkSemanticColors,
|
|
171
|
+
} from "@design-system";
|
|
172
|
+
|
|
173
|
+
const customLight = buildRestyleThemeFromThemeColors(lightSemanticColors, {
|
|
174
|
+
accent: { primary: "#E8836B", /* ... */ },
|
|
175
|
+
background: { primary: "#FFF9F5" },
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const customDark = buildRestyleThemeFromThemeColors(darkSemanticColors, {
|
|
179
|
+
accent: { primary: "#FF9B85", /* ... */ },
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### Building from Scratch
|
|
186
|
+
|
|
187
|
+
Use `buildRestyleTheme` when you want to define **every color yourself** with nothing inherited from defaults. Pass a complete `SemanticColorsInput` object.
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import {
|
|
191
|
+
buildRestyleTheme,
|
|
192
|
+
lightSemanticColors,
|
|
193
|
+
type SemanticColorsInput,
|
|
194
|
+
} from "@design-system";
|
|
195
|
+
|
|
196
|
+
const myLight = buildRestyleTheme({
|
|
197
|
+
...lightSemanticColors, // spread defaults, then override whole groups
|
|
198
|
+
background: {
|
|
199
|
+
primary: "#0D1117",
|
|
200
|
+
secondary: "#161B22",
|
|
201
|
+
tertiary: "#21262D",
|
|
202
|
+
inverse: "#F0F6FF",
|
|
203
|
+
},
|
|
204
|
+
accent: {
|
|
205
|
+
primary: "#58A6FF",
|
|
206
|
+
primaryHover: "#79BEFF",
|
|
207
|
+
primaryPressed: "#388BFD",
|
|
208
|
+
secondary: "#1F6FEB",
|
|
209
|
+
secondaryHover: "#388BFD",
|
|
210
|
+
secondaryPressed: "#0D4EA6",
|
|
211
|
+
},
|
|
212
|
+
} satisfies SemanticColorsInput);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Components
|
|
218
|
+
|
|
219
|
+
All components import from `@design-system`.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Layout
|
|
224
|
+
|
|
225
|
+
`Box` is the core layout primitive — a `View` with all Restyle spacing, color, and layout props.
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import { Box, AnimatedBox, ScrollView, FlatList, Pressable, Divider } from "@design-system";
|
|
229
|
+
|
|
230
|
+
<Box
|
|
231
|
+
flex={1}
|
|
232
|
+
backgroundColor="backgroundPrimary"
|
|
233
|
+
padding="lg"
|
|
234
|
+
borderRadius="md"
|
|
235
|
+
flexDirection="row"
|
|
236
|
+
alignItems="center"
|
|
237
|
+
gap="sm"
|
|
238
|
+
>
|
|
239
|
+
{children}
|
|
240
|
+
</Box>
|
|
241
|
+
|
|
242
|
+
<Divider orientation="horizontal" color="borderSubtle" />
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Spacing tokens:** `xs` · `sm` · `md` · `lg` · `xl` · `2xl` · `3xl` · `4xl`
|
|
246
|
+
|
|
247
|
+
**Border radius tokens:** `xs` · `sm` · `md` · `lg` · `xl` · `2xl` · `full`
|
|
248
|
+
|
|
249
|
+
**Common color tokens:** `backgroundPrimary` · `backgroundSecondary` · `surfacePrimary` · `surfaceElevated` · `textPrimary` · `textSecondary` · `accentPrimary` · `borderSubtle`
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### Typography
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
import { Text } from "@design-system";
|
|
257
|
+
|
|
258
|
+
<Text variant="headingLarge" color="textPrimary">Hello</Text>
|
|
259
|
+
<Text variant="bodyMedium" color="textSecondary">Subtitle</Text>
|
|
260
|
+
<Text variant="labelSmall" color="accentPrimary">BADGE</Text>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Available variants:**
|
|
264
|
+
|
|
265
|
+
| Scale | Variants |
|
|
266
|
+
|---|---|
|
|
267
|
+
| Display | `displayLarge` · `displayMedium` · `displaySmall` |
|
|
268
|
+
| Heading | `headingLarge` · `headingMedium` · `headingSmall` |
|
|
269
|
+
| Body | `bodyLarge` · `bodyMedium` · `bodySmall` |
|
|
270
|
+
| Label | `labelLarge` · `labelMedium` · `labelSmall` |
|
|
271
|
+
| Misc | `caption` · `captionSmall` · `overline` · `code` |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### Actions
|
|
276
|
+
|
|
277
|
+
```tsx
|
|
278
|
+
import { Button, IconButton } from "@design-system";
|
|
279
|
+
|
|
280
|
+
<Button title="Save" onPress={handleSave} />
|
|
281
|
+
<Button title="Delete" variant="destructive" size="sm" />
|
|
282
|
+
<Button title="Loading" isLoading />
|
|
283
|
+
<Button title="Ghost" variant="ghost" />
|
|
284
|
+
|
|
285
|
+
<IconButton name="close" onPress={handleClose} accessibilityLabel="Close" />
|
|
286
|
+
<IconButton name="settings" size="lg" color="textSecondary" />
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Button variants:** `primary` · `secondary` · `ghost` · `destructive`
|
|
290
|
+
**Button sizes:** `sm` · `md` · `lg`
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
### Content
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { Icon, Card, Avatar, Badge, Chip, getInitials } from "@design-system";
|
|
298
|
+
|
|
299
|
+
// Icon — Material Icons
|
|
300
|
+
<Icon name="home" size="lg" color="accentPrimary" />
|
|
301
|
+
<Icon name="check" accessibilityLabel="Confirmed" />
|
|
302
|
+
|
|
303
|
+
// Card
|
|
304
|
+
<Card variant="elevated" padding="lg">
|
|
305
|
+
<Text variant="bodyMedium">Card content</Text>
|
|
306
|
+
</Card>
|
|
307
|
+
|
|
308
|
+
// Avatar
|
|
309
|
+
<Avatar initials={getInitials("María García")} size="lg" />
|
|
310
|
+
<Avatar imageUri="https://..." size="md" status="online" />
|
|
311
|
+
|
|
312
|
+
// Badge
|
|
313
|
+
<Badge label={42} variant="filled" color="error" />
|
|
314
|
+
<Badge label="NEW" variant="outline" />
|
|
315
|
+
|
|
316
|
+
// Chip
|
|
317
|
+
<Chip label="React Native" variant="filled" onPress={handlePress} />
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Icon sizes:** `xs` · `sm` · `md` · `lg` · `xl` · `2xl` · `3xl`
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
### Inputs
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
import {
|
|
328
|
+
TextInput,
|
|
329
|
+
Checkbox,
|
|
330
|
+
RadioButton,
|
|
331
|
+
Switch,
|
|
332
|
+
SegmentedControl,
|
|
333
|
+
SelectSheet,
|
|
334
|
+
} from "@design-system";
|
|
335
|
+
|
|
336
|
+
<TextInput
|
|
337
|
+
label="Email"
|
|
338
|
+
placeholder="you@example.com"
|
|
339
|
+
value={email}
|
|
340
|
+
onChangeText={setEmail}
|
|
341
|
+
keyboardType="email-address"
|
|
342
|
+
leftIcon="mail"
|
|
343
|
+
/>
|
|
344
|
+
|
|
345
|
+
<Checkbox label="Accept terms" checked={accepted} onChange={setAccepted} />
|
|
346
|
+
|
|
347
|
+
<RadioButton
|
|
348
|
+
label="Option A"
|
|
349
|
+
selected={selected === "a"}
|
|
350
|
+
onSelect={() => setSelected("a")}
|
|
351
|
+
/>
|
|
352
|
+
|
|
353
|
+
<Switch label="Notifications" value={enabled} onValueChange={setEnabled} />
|
|
354
|
+
|
|
355
|
+
<SegmentedControl
|
|
356
|
+
options={[
|
|
357
|
+
{ label: "Day", value: "day" },
|
|
358
|
+
{ label: "Week", value: "week" },
|
|
359
|
+
{ label: "Month", value: "month" },
|
|
360
|
+
]}
|
|
361
|
+
selectedValue={period}
|
|
362
|
+
onChange={setPeriod}
|
|
363
|
+
/>
|
|
364
|
+
|
|
365
|
+
<SelectSheet
|
|
366
|
+
label="Country"
|
|
367
|
+
options={countries}
|
|
368
|
+
value={country}
|
|
369
|
+
onChange={setCountry}
|
|
370
|
+
placeholder="Select a country"
|
|
371
|
+
/>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### Feedback
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
import { Spinner, ProgressBar, Skeleton, ToastProvider, useToast } from "@design-system";
|
|
380
|
+
|
|
381
|
+
<Spinner size="md" color="accentPrimary" />
|
|
382
|
+
|
|
383
|
+
<ProgressBar progress={0.65} variant="determinate" />
|
|
384
|
+
|
|
385
|
+
<Skeleton width={200} height={16} borderRadius="sm" />
|
|
386
|
+
<Skeleton variant="circle" size="lg" />
|
|
387
|
+
|
|
388
|
+
// Wrap your app (or screen) with ToastProvider
|
|
389
|
+
<ToastProvider position="bottom">
|
|
390
|
+
<YourScreen />
|
|
391
|
+
</ToastProvider>
|
|
392
|
+
|
|
393
|
+
// Trigger toasts from any child
|
|
394
|
+
function MyComponent() {
|
|
395
|
+
const toast = useToast();
|
|
396
|
+
return (
|
|
397
|
+
<Button
|
|
398
|
+
title="Show toast"
|
|
399
|
+
onPress={() => toast.show({ message: "Saved!", variant: "success" })}
|
|
400
|
+
/>
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
### Overlays
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
import { Modal } from "@design-system";
|
|
411
|
+
|
|
412
|
+
<Modal
|
|
413
|
+
visible={isOpen}
|
|
414
|
+
onClose={() => setIsOpen(false)}
|
|
415
|
+
title="Confirm Delete"
|
|
416
|
+
>
|
|
417
|
+
<Text variant="bodyMedium">Are you sure?</Text>
|
|
418
|
+
<Button title="Delete" variant="destructive" onPress={handleDelete} />
|
|
419
|
+
</Modal>
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### Composite Components
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { Header, EmptyState, CalendarStrip, ScheduleItem } from "@design-system";
|
|
428
|
+
|
|
429
|
+
// Header — back button only shows when onBackPress is provided
|
|
430
|
+
<Header
|
|
431
|
+
title="Profile"
|
|
432
|
+
accessibilityLabel="Profile screen"
|
|
433
|
+
onBackPress={goBack} // omit on root screens
|
|
434
|
+
right={<IconButton name="edit" />}
|
|
435
|
+
/>
|
|
436
|
+
|
|
437
|
+
// EmptyState — types: "empty" | "error" | "offline" | "search"
|
|
438
|
+
<EmptyState
|
|
439
|
+
type="empty"
|
|
440
|
+
title="No results"
|
|
441
|
+
description="Try adjusting your search."
|
|
442
|
+
actionLabel="Clear filters"
|
|
443
|
+
onAction={clearFilters}
|
|
444
|
+
/>
|
|
445
|
+
|
|
446
|
+
// CalendarStrip
|
|
447
|
+
<CalendarStrip selectedDate={date} onDateSelect={setDate} />
|
|
448
|
+
|
|
449
|
+
// ScheduleItem
|
|
450
|
+
<ScheduleItem
|
|
451
|
+
data={{
|
|
452
|
+
title: "Morning run",
|
|
453
|
+
startTime: "07:00",
|
|
454
|
+
endTime: "08:00",
|
|
455
|
+
category: "fitness",
|
|
456
|
+
}}
|
|
457
|
+
onPress={handlePress}
|
|
458
|
+
/>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## i18n / Labels
|
|
464
|
+
|
|
465
|
+
Built-in English and Spanish label sets. Components use these internally for loading messages, error text, and accessibility strings.
|
|
466
|
+
|
|
467
|
+
### Switch language
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
<DesignSystemProvider language="es">
|
|
471
|
+
<YourApp />
|
|
472
|
+
</DesignSystemProvider>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Override specific labels
|
|
476
|
+
|
|
477
|
+
```tsx
|
|
478
|
+
<DesignSystemProvider
|
|
479
|
+
language="es"
|
|
480
|
+
overrides={{
|
|
481
|
+
designSystem: {
|
|
482
|
+
button: { loadingLabel: "Guardando..." },
|
|
483
|
+
},
|
|
484
|
+
}}
|
|
485
|
+
>
|
|
486
|
+
<YourApp />
|
|
487
|
+
</DesignSystemProvider>
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Read labels in a component
|
|
491
|
+
|
|
492
|
+
```tsx
|
|
493
|
+
import { useDesignSystem } from "@design-system";
|
|
494
|
+
|
|
495
|
+
const { labels } = useDesignSystem();
|
|
496
|
+
// labels.designSystem.button.loadingLabel
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Inspect the full label structure
|
|
500
|
+
|
|
501
|
+
```tsx
|
|
502
|
+
import { en } from "@design-system";
|
|
503
|
+
console.log(en); // full label tree — useful as a reference when extending
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## Tokens
|
|
509
|
+
|
|
510
|
+
All design tokens are exported for use in `StyleSheet.create` or any non-Restyle context.
|
|
511
|
+
|
|
512
|
+
```tsx
|
|
513
|
+
import {
|
|
514
|
+
spacing,
|
|
515
|
+
radii,
|
|
516
|
+
fontFamily,
|
|
517
|
+
fontSize,
|
|
518
|
+
fontWeight,
|
|
519
|
+
lineHeight,
|
|
520
|
+
duration,
|
|
521
|
+
easing,
|
|
522
|
+
iconSize,
|
|
523
|
+
lightSemanticColors,
|
|
524
|
+
} from "@design-system";
|
|
525
|
+
|
|
526
|
+
const styles = StyleSheet.create({
|
|
527
|
+
container: {
|
|
528
|
+
padding: spacing.lg,
|
|
529
|
+
borderRadius: radii.md,
|
|
530
|
+
},
|
|
531
|
+
label: {
|
|
532
|
+
fontFamily: fontFamily.primary,
|
|
533
|
+
fontSize: fontSize.md,
|
|
534
|
+
fontWeight: fontWeight.semibold,
|
|
535
|
+
lineHeight: lineHeight.md,
|
|
536
|
+
},
|
|
537
|
+
});
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
| Scale | Keys |
|
|
541
|
+
|---|---|
|
|
542
|
+
| Spacing | `xs` · `sm` · `md` · `lg` · `xl` · `2xl` · `3xl` · `4xl` |
|
|
543
|
+
| Radii | `xs` · `sm` · `md` · `lg` · `xl` · `2xl` · `full` |
|
|
544
|
+
| Font size | `xs` · `sm` · `md` · `lg` · `xl` · `2xl` · `3xl` · `4xl` |
|
|
545
|
+
| Duration (ms) | `instant` · `fast` · `normal` · `slow` · `slower` |
|
|
546
|
+
| Icon size (px) | `xs=12` · `sm=16` · `md=20` · `lg=24` · `xl=32` · `2xl=40` · `3xl=48` |
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## Hooks
|
|
551
|
+
|
|
552
|
+
### `useRestyleTheme`
|
|
553
|
+
|
|
554
|
+
Access raw theme tokens for dynamic styles.
|
|
555
|
+
|
|
556
|
+
```tsx
|
|
557
|
+
import { useRestyleTheme } from "@design-system";
|
|
558
|
+
|
|
559
|
+
const { colors, spacing } = useRestyleTheme();
|
|
560
|
+
// colors.accentPrimary, spacing.md, etc.
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### `useDesignSystem`
|
|
564
|
+
|
|
565
|
+
Access active i18n labels.
|
|
566
|
+
|
|
567
|
+
```tsx
|
|
568
|
+
import { useDesignSystem } from "@design-system";
|
|
569
|
+
|
|
570
|
+
const { labels } = useDesignSystem();
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### `useToast`
|
|
574
|
+
|
|
575
|
+
Trigger toasts imperatively from anywhere inside `ToastProvider`.
|
|
576
|
+
|
|
577
|
+
```tsx
|
|
578
|
+
import { useToast } from "@design-system";
|
|
579
|
+
|
|
580
|
+
const toast = useToast();
|
|
581
|
+
toast.show({ message: "Saved!", variant: "success" });
|
|
582
|
+
toast.show({ message: "Error", variant: "error", duration: 4000 });
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### `useReducedMotion`
|
|
586
|
+
|
|
587
|
+
```tsx
|
|
588
|
+
import { useReducedMotion } from "@design-system";
|
|
589
|
+
|
|
590
|
+
const reducedMotion = useReducedMotion(); // boolean
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### `useMotionSafeDuration`
|
|
594
|
+
|
|
595
|
+
Returns `0` when reduced motion is on, the given duration otherwise.
|
|
596
|
+
|
|
597
|
+
```tsx
|
|
598
|
+
import { useMotionSafeDuration, duration } from "@design-system";
|
|
599
|
+
|
|
600
|
+
const animDuration = useMotionSafeDuration(duration.normal); // 0 or 300
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Utilities
|
|
606
|
+
|
|
607
|
+
### Platform
|
|
608
|
+
|
|
609
|
+
```tsx
|
|
610
|
+
import { isIOS, isAndroid, platformSelect, getStatusBarHeight, MIN_TOUCH_TARGET } from "@design-system";
|
|
611
|
+
|
|
612
|
+
const shadow = platformSelect({
|
|
613
|
+
ios: { shadowColor: "#000", shadowOpacity: 0.1, shadowRadius: 4 },
|
|
614
|
+
android: { elevation: 4 },
|
|
615
|
+
});
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### Accessibility
|
|
619
|
+
|
|
620
|
+
```tsx
|
|
621
|
+
import {
|
|
622
|
+
buttonA11yProps,
|
|
623
|
+
checkboxA11yProps,
|
|
624
|
+
imageA11yProps,
|
|
625
|
+
getContrastRatio,
|
|
626
|
+
meetsContrastAA,
|
|
627
|
+
} from "@design-system";
|
|
628
|
+
|
|
629
|
+
<TouchableOpacity {...buttonA11yProps("Save changes")} />
|
|
630
|
+
|
|
631
|
+
const ratio = getContrastRatio("#1877F2", "#FFFFFF"); // → 4.56
|
|
632
|
+
const passes = meetsContrastAA(ratio); // → true
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Helpers
|
|
636
|
+
|
|
637
|
+
```tsx
|
|
638
|
+
import { getInitials, formatBadgeLabel } from "@design-system";
|
|
639
|
+
|
|
640
|
+
getInitials("María García"); // → "MG"
|
|
641
|
+
formatBadgeLabel(100); // → "99+"
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
## TypeScript Reference
|
|
647
|
+
|
|
648
|
+
### Theme utilities
|
|
649
|
+
|
|
650
|
+
| Export | Description |
|
|
651
|
+
|---|---|
|
|
652
|
+
| `buildPair(light, dark)` | Build a `RestyleThemePair` from partial color overrides — recommended |
|
|
653
|
+
| `buildRestyleThemeFromThemeColors(base, overrides)` | Build one mode by merging overrides into a base palette |
|
|
654
|
+
| `buildRestyleTheme(colors)` | Build one mode from a complete `SemanticColorsInput` — from scratch |
|
|
655
|
+
| `restylePresetThemes` | Map of 6 built-in `RestyleThemePair` objects |
|
|
656
|
+
| `lightSemanticColors` | Default light palette — use as base for `buildRestyleThemeFromThemeColors` |
|
|
657
|
+
| `darkSemanticColors` | Default dark palette |
|
|
658
|
+
|
|
659
|
+
### Key types
|
|
660
|
+
|
|
661
|
+
| Type | Description |
|
|
662
|
+
|---|---|
|
|
663
|
+
| `ThemeColors` | Full color map shape |
|
|
664
|
+
| `DeepPartial<ThemeColors>` | Partial overrides for `buildPair` |
|
|
665
|
+
| `SemanticColorsInput` | Complete color map with `string` values for `buildRestyleTheme` |
|
|
666
|
+
| `RestyleTheme` | Compiled Restyle theme object |
|
|
667
|
+
| `RestyleThemePair` | `{ light: RestyleTheme, dark: RestyleTheme }` |
|
|
668
|
+
| `DesignSystemLanguage` | `"en" \| "es"` |
|
|
669
|
+
| `DesignSystemLabels` | Complete label tree |
|
|
670
|
+
| `DesignSystemLabelsOverride` | `DeepPartial<DesignSystemLabels>` |
|
|
671
|
+
| `DesignSystemProviderProps` | All props for `DesignSystemProvider` |
|
|
672
|
+
| `IconName` | Union of all valid Material Icon names |
|
|
673
|
+
| `RestyleColor` | Union of all valid theme color token names |
|
|
674
|
+
|
|
675
|
+
### Component prop types
|
|
676
|
+
|
|
677
|
+
Every component exports its props type as `ComponentNameProps`:
|
|
678
|
+
|
|
679
|
+
```tsx
|
|
680
|
+
import type {
|
|
681
|
+
ButtonProps, IconButtonProps,
|
|
682
|
+
TextInputProps, CheckboxProps, RadioButtonProps,
|
|
683
|
+
SwitchProps, SegmentedControlProps, SelectSheetProps,
|
|
684
|
+
AvatarProps, BadgeProps, ChipProps, CardProps, IconProps,
|
|
685
|
+
SpinnerProps, ProgressBarProps, SkeletonProps, ToastProps, ModalProps,
|
|
686
|
+
HeaderProps, EmptyStateProps, CalendarStripProps, ScheduleItemProps,
|
|
687
|
+
} from "@design-system";
|
|
688
|
+
```
|