@retray-dev/ui-kit 0.1.0 → 1.0.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/COMPONENTS.md +654 -0
- package/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/index.d.mts +309 -3
- package/dist/index.d.ts +309 -3
- package/dist/index.js +1477 -57
- package/dist/index.mjs +1424 -57
- package/package.json +27 -5
- package/src/components/Accordion/Accordion.tsx +161 -0
- package/src/components/Accordion/index.ts +2 -0
- package/src/components/Alert/Alert.tsx +57 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/Avatar/Avatar.tsx +67 -0
- package/src/components/Avatar/index.ts +2 -0
- package/src/components/Badge/Badge.tsx +48 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Button/Button.tsx +78 -45
- package/src/components/Card/Card.tsx +109 -0
- package/src/components/Card/index.ts +9 -0
- package/src/components/Checkbox/Checkbox.tsx +70 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/EmptyState/EmptyState.tsx +69 -0
- package/src/components/EmptyState/index.ts +2 -0
- package/src/components/Input/Input.tsx +26 -41
- package/src/components/Progress/Progress.tsx +53 -0
- package/src/components/Progress/index.ts +2 -0
- package/src/components/RadioGroup/RadioGroup.tsx +105 -0
- package/src/components/RadioGroup/index.ts +2 -0
- package/src/components/Select/Select.tsx +185 -0
- package/src/components/Select/index.ts +2 -0
- package/src/components/Separator/Separator.tsx +33 -0
- package/src/components/Separator/index.ts +2 -0
- package/src/components/Sheet/Sheet.tsx +108 -0
- package/src/components/Sheet/index.ts +2 -0
- package/src/components/Skeleton/Skeleton.tsx +40 -0
- package/src/components/Skeleton/index.ts +2 -0
- package/src/components/Slider/Slider.tsx +142 -0
- package/src/components/Slider/index.ts +2 -0
- package/src/components/Spinner/Spinner.tsx +27 -0
- package/src/components/Spinner/index.ts +2 -0
- package/src/components/Switch/Switch.tsx +82 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Tabs/Tabs.tsx +145 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Text/Text.tsx +10 -4
- package/src/components/Textarea/Textarea.tsx +70 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Toast/Toast.tsx +164 -0
- package/src/components/Toast/index.ts +2 -0
- package/src/components/Toggle/Toggle.tsx +80 -0
- package/src/components/Toggle/index.ts +2 -0
- package/src/index.ts +26 -0
- package/src/theme/ThemeProvider.tsx +47 -0
- package/src/theme/colors.ts +41 -0
- package/src/theme/index.ts +4 -0
- package/src/theme/types.ts +31 -0
package/COMPONENTS.md
ADDED
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
# @retray-dev/ui-kit — Component Reference
|
|
2
|
+
|
|
3
|
+
This file is the AI reference for this package. It is shipped inside the npm package so consuming projects can import it into their `CLAUDE.md` with:
|
|
4
|
+
|
|
5
|
+
```markdown
|
|
6
|
+
## UI Components
|
|
7
|
+
@./node_modules/@retray-dev/ui-kit/COMPONENTS.md
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Setup (Required)
|
|
13
|
+
|
|
14
|
+
Wrap your app root with both providers. `ThemeProvider` enables theming; `ToastProvider` enables the toast notification system.
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { ThemeProvider, ToastProvider } from '@retray-dev/ui-kit'
|
|
18
|
+
|
|
19
|
+
export default function RootLayout({ children }) {
|
|
20
|
+
return (
|
|
21
|
+
<ThemeProvider colorScheme="system">
|
|
22
|
+
<ToastProvider>
|
|
23
|
+
{children}
|
|
24
|
+
</ToastProvider>
|
|
25
|
+
</ThemeProvider>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### ThemeProvider Props
|
|
31
|
+
|
|
32
|
+
| Prop | Type | Default | Notes |
|
|
33
|
+
|------|------|---------|-------|
|
|
34
|
+
| colorScheme | `'light' \| 'dark' \| 'system'` | `'system'` | `'system'` auto-detects the device setting and updates when it changes |
|
|
35
|
+
| theme | `{ light?: Partial<ThemeColors>, dark?: Partial<ThemeColors> }` | — | Override any subset of color tokens per scheme |
|
|
36
|
+
|
|
37
|
+
**Custom theme example:**
|
|
38
|
+
```tsx
|
|
39
|
+
const myTheme = {
|
|
40
|
+
light: { primary: '#6366f1', primaryForeground: '#ffffff' },
|
|
41
|
+
dark: { primary: '#818cf8', primaryForeground: '#ffffff' },
|
|
42
|
+
}
|
|
43
|
+
<ThemeProvider theme={myTheme} colorScheme="system">
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### useTheme Hook
|
|
47
|
+
|
|
48
|
+
Access the active color tokens and scheme inside any component:
|
|
49
|
+
```tsx
|
|
50
|
+
import { useTheme } from '@retray-dev/ui-kit'
|
|
51
|
+
|
|
52
|
+
function MyComponent() {
|
|
53
|
+
const { colors, colorScheme } = useTheme()
|
|
54
|
+
return <View style={{ backgroundColor: colors.background }} />
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Theme Tokens
|
|
61
|
+
|
|
62
|
+
All 18 tokens are available via `useTheme().colors`.
|
|
63
|
+
|
|
64
|
+
| Token | Light | Dark | Semantic Role |
|
|
65
|
+
|-------|-------|------|---------------|
|
|
66
|
+
| `background` | `#ffffff` | `#171717` | Screen / page background |
|
|
67
|
+
| `foreground` | `#171717` | `#fafafa` | Primary text color |
|
|
68
|
+
| `card` | `#ffffff` | `#1f1f1f` | Card / surface background |
|
|
69
|
+
| `cardForeground` | `#171717` | `#fafafa` | Text on cards |
|
|
70
|
+
| `primary` | `#1a1a1a` | `#fafafa` | Primary action (buttons, selected states) |
|
|
71
|
+
| `primaryForeground` | `#fafafa` | `#1a1a1a` | Text/icon on primary background |
|
|
72
|
+
| `secondary` | `#f5f5f5` | `#2a2a2a` | Secondary surfaces |
|
|
73
|
+
| `secondaryForeground` | `#1a1a1a` | `#fafafa` | Text on secondary |
|
|
74
|
+
| `muted` | `#f5f5f5` | `#2a2a2a` | Muted backgrounds, skeleton fills, track fills |
|
|
75
|
+
| `mutedForeground` | `#737373` | `#a3a3a3` | Placeholder text, helper text, captions |
|
|
76
|
+
| `accent` | `#f5f5f5` | `#2a2a2a` | Hover / pressed state fills |
|
|
77
|
+
| `accentForeground` | `#1a1a1a` | `#fafafa` | Text on accent |
|
|
78
|
+
| `destructive` | `#ef4444` | `#dc2626` | Error / danger / delete actions |
|
|
79
|
+
| `destructiveForeground` | `#fafafa` | `#fafafa` | Text on destructive |
|
|
80
|
+
| `border` | `#e5e5e5` | `#2a2a2a` | Borders and dividers |
|
|
81
|
+
| `input` | `#e5e5e5` | `#2a2a2a` | Input field border color |
|
|
82
|
+
| `ring` | `#a3a3a3` | `#d4d4d4` | Focus ring color |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Components
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### Text
|
|
91
|
+
|
|
92
|
+
**Import:** `import { Text } from '@retray-dev/ui-kit'`
|
|
93
|
+
**When to use:** All text in the app. Replaces React Native's `Text` with semantic variants.
|
|
94
|
+
**Extends:** `TextProps` from React Native.
|
|
95
|
+
|
|
96
|
+
| Prop | Type | Default | Notes |
|
|
97
|
+
|------|------|---------|-------|
|
|
98
|
+
| variant | `'h1' \| 'h2' \| 'h3' \| 'body' \| 'caption' \| 'label'` | `'body'` | Sets font size, weight, and line height |
|
|
99
|
+
| color | `string` | — | Override the color. Defaults to `foreground`, except `caption` which defaults to `mutedForeground` |
|
|
100
|
+
|
|
101
|
+
**Sizes:**
|
|
102
|
+
- `h1`: 32px / 700 weight
|
|
103
|
+
- `h2`: 24px / 700 weight
|
|
104
|
+
- `h3`: 20px / 600 weight
|
|
105
|
+
- `body`: 16px / 400 weight
|
|
106
|
+
- `label`: 14px / 500 weight
|
|
107
|
+
- `caption`: 12px / 400 weight / `mutedForeground` color by default
|
|
108
|
+
|
|
109
|
+
**Example:**
|
|
110
|
+
```tsx
|
|
111
|
+
<Text variant="h2">Welcome back</Text>
|
|
112
|
+
<Text variant="body">Your account is ready.</Text>
|
|
113
|
+
<Text variant="caption">Last updated 2 hours ago</Text>
|
|
114
|
+
<Text variant="label" color="#6366f1">Pro plan</Text>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### Button
|
|
120
|
+
|
|
121
|
+
**Import:** `import { Button } from '@retray-dev/ui-kit'`
|
|
122
|
+
**When to use:** Any interactive action. Use `variant` to communicate intent.
|
|
123
|
+
**Extends:** `TouchableOpacityProps` — all RN TouchableOpacity props pass through.
|
|
124
|
+
|
|
125
|
+
| Prop | Type | Default | Notes |
|
|
126
|
+
|------|------|---------|-------|
|
|
127
|
+
| label | `string` | required | Button text |
|
|
128
|
+
| variant | `'primary' \| 'secondary' \| 'outline' \| 'ghost'` | `'primary'` | Visual style |
|
|
129
|
+
| size | `'sm' \| 'md' \| 'lg'` | `'md'` | — |
|
|
130
|
+
| loading | `boolean` | `false` | Replaces label with spinner and forces disabled |
|
|
131
|
+
| fullWidth | `boolean` | `false` | Stretches to container width |
|
|
132
|
+
| disabled | `boolean` | — | Reduces opacity to 0.45 |
|
|
133
|
+
|
|
134
|
+
**Variants:**
|
|
135
|
+
- `primary`: filled with `primary` token — main actions
|
|
136
|
+
- `secondary`: filled with `secondary` token — less prominent actions
|
|
137
|
+
- `outline`: transparent with `border` — alternative/secondary without fill
|
|
138
|
+
- `ghost`: fully transparent — in-context or low-emphasis actions
|
|
139
|
+
|
|
140
|
+
**Example:**
|
|
141
|
+
```tsx
|
|
142
|
+
<Button label="Save changes" onPress={handleSave} />
|
|
143
|
+
<Button label="Cancel" variant="ghost" onPress={onCancel} />
|
|
144
|
+
<Button label="Delete" variant="outline" size="sm" />
|
|
145
|
+
<Button label="Submitting..." loading fullWidth />
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### Input
|
|
151
|
+
|
|
152
|
+
**Import:** `import { Input } from '@retray-dev/ui-kit'`
|
|
153
|
+
**When to use:** Single-line text entry. Includes built-in label, error, and hint support.
|
|
154
|
+
**Extends:** `TextInputProps` from React Native.
|
|
155
|
+
|
|
156
|
+
| Prop | Type | Default | Notes |
|
|
157
|
+
|------|------|---------|-------|
|
|
158
|
+
| label | `string` | — | Label above the input |
|
|
159
|
+
| error | `string` | — | Shows error text below; turns border red |
|
|
160
|
+
| hint | `string` | — | Helper text below (hidden when error is set) |
|
|
161
|
+
|
|
162
|
+
**Example:**
|
|
163
|
+
```tsx
|
|
164
|
+
<Input label="Email" placeholder="you@example.com" keyboardType="email-address" />
|
|
165
|
+
<Input label="Password" secureTextEntry error="Incorrect password" />
|
|
166
|
+
<Input label="Username" hint="Must be at least 4 characters" />
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### Textarea
|
|
172
|
+
|
|
173
|
+
**Import:** `import { Textarea } from '@retray-dev/ui-kit'`
|
|
174
|
+
**When to use:** Multi-line text entry. Same API as Input plus `rows`.
|
|
175
|
+
**Extends:** `TextInputProps` from React Native.
|
|
176
|
+
|
|
177
|
+
| Prop | Type | Default | Notes |
|
|
178
|
+
|------|------|---------|-------|
|
|
179
|
+
| label | `string` | — | Label above |
|
|
180
|
+
| error | `string` | — | Error text below; red border |
|
|
181
|
+
| hint | `string` | — | Helper text below |
|
|
182
|
+
| rows | `number` | `4` | Sets minimum height (each row ≈ 24px) |
|
|
183
|
+
|
|
184
|
+
**Example:**
|
|
185
|
+
```tsx
|
|
186
|
+
<Textarea label="Bio" placeholder="Tell us about yourself" rows={5} />
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### Badge
|
|
192
|
+
|
|
193
|
+
**Import:** `import { Badge } from '@retray-dev/ui-kit'`
|
|
194
|
+
**When to use:** Status labels, tags, counts.
|
|
195
|
+
|
|
196
|
+
| Prop | Type | Default | Notes |
|
|
197
|
+
|------|------|---------|-------|
|
|
198
|
+
| label | `string` | required | — |
|
|
199
|
+
| variant | `'default' \| 'secondary' \| 'destructive' \| 'outline'` | `'default'` | — |
|
|
200
|
+
|
|
201
|
+
**Example:**
|
|
202
|
+
```tsx
|
|
203
|
+
<Badge label="New" />
|
|
204
|
+
<Badge label="Error" variant="destructive" />
|
|
205
|
+
<Badge label="Draft" variant="secondary" />
|
|
206
|
+
<Badge label="Beta" variant="outline" />
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### Avatar
|
|
212
|
+
|
|
213
|
+
**Import:** `import { Avatar } from '@retray-dev/ui-kit'`
|
|
214
|
+
**When to use:** User profile pictures with automatic fallback to initials.
|
|
215
|
+
|
|
216
|
+
| Prop | Type | Default | Notes |
|
|
217
|
+
|------|------|---------|-------|
|
|
218
|
+
| src | `string` | — | Image URI |
|
|
219
|
+
| fallback | `string` | — | Text for fallback (first 2 chars shown, uppercased) |
|
|
220
|
+
| size | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | sm=24, md=32, lg=48, xl=64 |
|
|
221
|
+
|
|
222
|
+
**Example:**
|
|
223
|
+
```tsx
|
|
224
|
+
<Avatar src="https://..." fallback="JC" size="lg" />
|
|
225
|
+
<Avatar fallback="AN" size="md" />
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
### Separator
|
|
231
|
+
|
|
232
|
+
**Import:** `import { Separator } from '@retray-dev/ui-kit'`
|
|
233
|
+
**When to use:** Visual dividers between sections.
|
|
234
|
+
|
|
235
|
+
| Prop | Type | Default | Notes |
|
|
236
|
+
|------|------|---------|-------|
|
|
237
|
+
| orientation | `'horizontal' \| 'vertical'` | `'horizontal'` | Vertical requires a parent with defined height |
|
|
238
|
+
|
|
239
|
+
**Example:**
|
|
240
|
+
```tsx
|
|
241
|
+
<Separator />
|
|
242
|
+
<View style={{ flexDirection: 'row', height: 40 }}>
|
|
243
|
+
<Text>Left</Text>
|
|
244
|
+
<Separator orientation="vertical" style={{ marginHorizontal: 12 }} />
|
|
245
|
+
<Text>Right</Text>
|
|
246
|
+
</View>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
### Spinner
|
|
252
|
+
|
|
253
|
+
**Import:** `import { Spinner } from '@retray-dev/ui-kit'`
|
|
254
|
+
**When to use:** Loading state indicator.
|
|
255
|
+
|
|
256
|
+
| Prop | Type | Default | Notes |
|
|
257
|
+
|------|------|---------|-------|
|
|
258
|
+
| size | `'sm' \| 'md' \| 'lg'` | `'md'` | sm/md map to RN `'small'`, lg maps to `'large'` |
|
|
259
|
+
| color | `string` | `primary` token | Override spinner color |
|
|
260
|
+
|
|
261
|
+
**Example:**
|
|
262
|
+
```tsx
|
|
263
|
+
<Spinner />
|
|
264
|
+
<Spinner size="lg" color="#6366f1" />
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
### Skeleton
|
|
270
|
+
|
|
271
|
+
**Import:** `import { Skeleton } from '@retray-dev/ui-kit'`
|
|
272
|
+
**When to use:** Placeholder while content is loading. Pulses with animation.
|
|
273
|
+
|
|
274
|
+
| Prop | Type | Default | Notes |
|
|
275
|
+
|------|------|---------|-------|
|
|
276
|
+
| width | `number \| string` | `'100%'` | — |
|
|
277
|
+
| height | `number` | `16` | — |
|
|
278
|
+
| borderRadius | `number` | `6` | — |
|
|
279
|
+
|
|
280
|
+
**Example:**
|
|
281
|
+
```tsx
|
|
282
|
+
<Skeleton height={20} width="60%" />
|
|
283
|
+
<Skeleton height={80} borderRadius={10} />
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### Progress
|
|
289
|
+
|
|
290
|
+
**Import:** `import { Progress } from '@retray-dev/ui-kit'`
|
|
291
|
+
**When to use:** Show completion percentage for a task or upload.
|
|
292
|
+
|
|
293
|
+
| Prop | Type | Default | Notes |
|
|
294
|
+
|------|------|---------|-------|
|
|
295
|
+
| value | `number` | `0` | Current value |
|
|
296
|
+
| max | `number` | `100` | Maximum value |
|
|
297
|
+
|
|
298
|
+
**Example:**
|
|
299
|
+
```tsx
|
|
300
|
+
<Progress value={60} />
|
|
301
|
+
<Progress value={3} max={10} />
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
### Card
|
|
307
|
+
|
|
308
|
+
**Import:** `import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@retray-dev/ui-kit'`
|
|
309
|
+
**When to use:** Grouped content with a surface background, border, and shadow.
|
|
310
|
+
|
|
311
|
+
All sub-components accept a `style` prop for overrides.
|
|
312
|
+
|
|
313
|
+
**Example:**
|
|
314
|
+
```tsx
|
|
315
|
+
<Card>
|
|
316
|
+
<CardHeader>
|
|
317
|
+
<CardTitle>Account</CardTitle>
|
|
318
|
+
<CardDescription>Manage your profile settings</CardDescription>
|
|
319
|
+
</CardHeader>
|
|
320
|
+
<CardContent>
|
|
321
|
+
<Input label="Name" />
|
|
322
|
+
</CardContent>
|
|
323
|
+
<CardFooter>
|
|
324
|
+
<Button label="Save" fullWidth />
|
|
325
|
+
</CardFooter>
|
|
326
|
+
</Card>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Notes:** `CardHeader` and `CardContent` have `padding: 24`. `CardFooter` has `paddingTop: 0` so it connects naturally to `CardContent`.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
### Alert
|
|
334
|
+
|
|
335
|
+
**Import:** `import { Alert } from '@retray-dev/ui-kit'`
|
|
336
|
+
**When to use:** Inline feedback messages (info, success, warning, error). Not for toasts.
|
|
337
|
+
|
|
338
|
+
| Prop | Type | Default | Notes |
|
|
339
|
+
|------|------|---------|-------|
|
|
340
|
+
| title | `string` | — | Bold heading |
|
|
341
|
+
| description | `string` | — | Detail text |
|
|
342
|
+
| variant | `'default' \| 'destructive'` | `'default'` | `destructive` turns border and text red |
|
|
343
|
+
| icon | `ReactNode` | — | Icon placed to the left |
|
|
344
|
+
|
|
345
|
+
**Example:**
|
|
346
|
+
```tsx
|
|
347
|
+
<Alert title="Success" description="Your profile has been updated." />
|
|
348
|
+
<Alert variant="destructive" title="Error" description="Failed to save. Try again." />
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### EmptyState
|
|
354
|
+
|
|
355
|
+
**Import:** `import { EmptyState } from '@retray-dev/ui-kit'`
|
|
356
|
+
**When to use:** When a list or section has no content yet.
|
|
357
|
+
|
|
358
|
+
| Prop | Type | Default | Notes |
|
|
359
|
+
|------|------|---------|-------|
|
|
360
|
+
| title | `string` | required | — |
|
|
361
|
+
| description | `string` | — | — |
|
|
362
|
+
| icon | `ReactNode` | — | Shown in a muted square above the text |
|
|
363
|
+
| action | `ReactNode` | — | Usually a `Button`, placed below the text |
|
|
364
|
+
|
|
365
|
+
**Example:**
|
|
366
|
+
```tsx
|
|
367
|
+
<EmptyState
|
|
368
|
+
title="No notifications"
|
|
369
|
+
description="You're all caught up!"
|
|
370
|
+
action={<Button label="Refresh" variant="outline" size="sm" />}
|
|
371
|
+
/>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### Checkbox
|
|
377
|
+
|
|
378
|
+
**Import:** `import { Checkbox } from '@retray-dev/ui-kit'`
|
|
379
|
+
|
|
380
|
+
| Prop | Type | Default | Notes |
|
|
381
|
+
|------|------|---------|-------|
|
|
382
|
+
| checked | `boolean` | `false` | — |
|
|
383
|
+
| onCheckedChange | `(checked: boolean) => void` | — | — |
|
|
384
|
+
| label | `string` | — | Text to the right of the box |
|
|
385
|
+
| disabled | `boolean` | — | — |
|
|
386
|
+
|
|
387
|
+
**Example:**
|
|
388
|
+
```tsx
|
|
389
|
+
const [accepted, setAccepted] = useState(false)
|
|
390
|
+
<Checkbox checked={accepted} onCheckedChange={setAccepted} label="I agree to the terms" />
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
### Switch
|
|
396
|
+
|
|
397
|
+
**Import:** `import { Switch } from '@retray-dev/ui-kit'`
|
|
398
|
+
**When to use:** Binary on/off settings. Animated thumb.
|
|
399
|
+
|
|
400
|
+
| Prop | Type | Default | Notes |
|
|
401
|
+
|------|------|---------|-------|
|
|
402
|
+
| checked | `boolean` | `false` | — |
|
|
403
|
+
| onCheckedChange | `(checked: boolean) => void` | — | — |
|
|
404
|
+
| disabled | `boolean` | — | — |
|
|
405
|
+
|
|
406
|
+
**Example:**
|
|
407
|
+
```tsx
|
|
408
|
+
<Switch checked={notifications} onCheckedChange={setNotifications} />
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
### Toggle
|
|
414
|
+
|
|
415
|
+
**Import:** `import { Toggle } from '@retray-dev/ui-kit'`
|
|
416
|
+
**When to use:** Toggleable button (e.g., bold/italic in a toolbar). Unlike Switch, it looks like a button.
|
|
417
|
+
|
|
418
|
+
| Prop | Type | Default | Notes |
|
|
419
|
+
|------|------|---------|-------|
|
|
420
|
+
| pressed | `boolean` | `false` | — |
|
|
421
|
+
| onPressedChange | `(pressed: boolean) => void` | — | — |
|
|
422
|
+
| variant | `'default' \| 'outline'` | `'default'` | `outline` adds a border when unpressed |
|
|
423
|
+
| size | `'sm' \| 'md' \| 'lg'` | `'md'` | — |
|
|
424
|
+
| label | `string` | — | Text label |
|
|
425
|
+
| icon | `ReactNode` | — | Icon (can be combined with label) |
|
|
426
|
+
|
|
427
|
+
**Example:**
|
|
428
|
+
```tsx
|
|
429
|
+
<Toggle pressed={bold} onPressedChange={setBold} label="Bold" variant="outline" />
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
### RadioGroup
|
|
435
|
+
|
|
436
|
+
**Import:** `import { RadioGroup } from '@retray-dev/ui-kit'`
|
|
437
|
+
|
|
438
|
+
| Prop | Type | Default | Notes |
|
|
439
|
+
|------|------|---------|-------|
|
|
440
|
+
| options | `RadioOption[]` | required | Each option: `{ label, value, disabled? }` |
|
|
441
|
+
| value | `string` | — | Selected value |
|
|
442
|
+
| onValueChange | `(value: string) => void` | — | — |
|
|
443
|
+
| orientation | `'vertical' \| 'horizontal'` | `'vertical'` | — |
|
|
444
|
+
|
|
445
|
+
**Example:**
|
|
446
|
+
```tsx
|
|
447
|
+
<RadioGroup
|
|
448
|
+
options={[
|
|
449
|
+
{ label: 'Free', value: 'free' },
|
|
450
|
+
{ label: 'Pro', value: 'pro' },
|
|
451
|
+
{ label: 'Enterprise', value: 'enterprise', disabled: true },
|
|
452
|
+
]}
|
|
453
|
+
value={plan}
|
|
454
|
+
onValueChange={setPlan}
|
|
455
|
+
/>
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
### Select
|
|
461
|
+
|
|
462
|
+
**Import:** `import { Select } from '@retray-dev/ui-kit'`
|
|
463
|
+
**When to use:** Dropdown picker. Tapping the trigger opens a modal with a scrollable list.
|
|
464
|
+
|
|
465
|
+
| Prop | Type | Default | Notes |
|
|
466
|
+
|------|------|---------|-------|
|
|
467
|
+
| options | `SelectOption[]` | required | Each option: `{ label, value, disabled? }` |
|
|
468
|
+
| value | `string` | — | Selected value |
|
|
469
|
+
| onValueChange | `(value: string) => void` | — | — |
|
|
470
|
+
| placeholder | `string` | `'Select an option'` | — |
|
|
471
|
+
| label | `string` | — | Label above the trigger |
|
|
472
|
+
| error | `string` | — | Error text below |
|
|
473
|
+
| disabled | `boolean` | — | — |
|
|
474
|
+
|
|
475
|
+
**Example:**
|
|
476
|
+
```tsx
|
|
477
|
+
<Select
|
|
478
|
+
label="Country"
|
|
479
|
+
options={[{ label: 'Argentina', value: 'AR' }, { label: 'Spain', value: 'ES' }]}
|
|
480
|
+
value={country}
|
|
481
|
+
onValueChange={setCountry}
|
|
482
|
+
placeholder="Pick a country"
|
|
483
|
+
/>
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
### Slider
|
|
489
|
+
|
|
490
|
+
**Import:** `import { Slider } from '@retray-dev/ui-kit'`
|
|
491
|
+
**When to use:** Select a numeric value within a range by dragging.
|
|
492
|
+
|
|
493
|
+
| Prop | Type | Default | Notes |
|
|
494
|
+
|------|------|---------|-------|
|
|
495
|
+
| value | `number` | `0` | — |
|
|
496
|
+
| minimumValue | `number` | `0` | — |
|
|
497
|
+
| maximumValue | `number` | `1` | — |
|
|
498
|
+
| step | `number` | `0` | `0` means continuous |
|
|
499
|
+
| onValueChange | `(value: number) => void` | — | Fires while dragging |
|
|
500
|
+
| onSlidingComplete | `(value: number) => void` | — | Fires on release |
|
|
501
|
+
| disabled | `boolean` | — | — |
|
|
502
|
+
|
|
503
|
+
**Example:**
|
|
504
|
+
```tsx
|
|
505
|
+
<Slider value={volume} minimumValue={0} maximumValue={100} step={1} onValueChange={setVolume} />
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
### Tabs
|
|
513
|
+
|
|
514
|
+
**Import:** `import { Tabs, TabsContent } from '@retray-dev/ui-kit'`
|
|
515
|
+
**When to use:** Switching between categorized sections on the same screen.
|
|
516
|
+
|
|
517
|
+
| Prop | Type | Default | Notes |
|
|
518
|
+
|------|------|---------|-------|
|
|
519
|
+
| tabs | `TabItem[]` | required | Each item: `{ label, value }` |
|
|
520
|
+
| value | `string` | — | Controlled active tab |
|
|
521
|
+
| onValueChange | `(value: string) => void` | — | — |
|
|
522
|
+
| children | `ReactNode` | — | `TabsContent` components |
|
|
523
|
+
|
|
524
|
+
**`TabsContent` Props:**
|
|
525
|
+
|
|
526
|
+
| Prop | Type | Notes |
|
|
527
|
+
|------|------|-------|
|
|
528
|
+
| value | `string` | Must match a tab value |
|
|
529
|
+
| activeValue | `string` | Pass the current active tab value |
|
|
530
|
+
| children | `ReactNode` | — |
|
|
531
|
+
|
|
532
|
+
**Example:**
|
|
533
|
+
```tsx
|
|
534
|
+
const [tab, setTab] = useState('profile')
|
|
535
|
+
|
|
536
|
+
<Tabs
|
|
537
|
+
tabs={[{ label: 'Profile', value: 'profile' }, { label: 'Security', value: 'security' }]}
|
|
538
|
+
value={tab}
|
|
539
|
+
onValueChange={setTab}
|
|
540
|
+
>
|
|
541
|
+
<TabsContent value="profile" activeValue={tab}>
|
|
542
|
+
<Text>Profile content</Text>
|
|
543
|
+
</TabsContent>
|
|
544
|
+
<TabsContent value="security" activeValue={tab}>
|
|
545
|
+
<Text>Security content</Text>
|
|
546
|
+
</TabsContent>
|
|
547
|
+
</Tabs>
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
### Accordion
|
|
553
|
+
|
|
554
|
+
**Import:** `import { Accordion } from '@retray-dev/ui-kit'`
|
|
555
|
+
**When to use:** FAQs, collapsible sections. Animated expand/collapse.
|
|
556
|
+
|
|
557
|
+
| Prop | Type | Default | Notes |
|
|
558
|
+
|------|------|---------|-------|
|
|
559
|
+
| items | `AccordionItem[]` | required | Each: `{ value, trigger: string, content: ReactNode }` |
|
|
560
|
+
| type | `'single' \| 'multiple'` | `'single'` | `single`: only one open at a time. `multiple`: many can be open |
|
|
561
|
+
| defaultValue | `string \| string[]` | — | Initially open item(s) |
|
|
562
|
+
|
|
563
|
+
**Example:**
|
|
564
|
+
```tsx
|
|
565
|
+
<Accordion
|
|
566
|
+
type="single"
|
|
567
|
+
items={[
|
|
568
|
+
{ value: 'q1', trigger: 'What is this?', content: <Text>It's a UI kit.</Text> },
|
|
569
|
+
{ value: 'q2', trigger: 'Is it free?', content: <Text>Yes.</Text> },
|
|
570
|
+
]}
|
|
571
|
+
/>
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
### Sheet
|
|
579
|
+
|
|
580
|
+
**Import:** `import { Sheet, BottomSheetModalProvider } from '@retray-dev/ui-kit'`
|
|
581
|
+
**When to use:** Bottom sheet with physics-based gestures, rubber-band overscroll, and snap points. Powered by `@gorhom/bottom-sheet`.
|
|
582
|
+
|
|
583
|
+
**Setup:** Wrap your app root with `BottomSheetModalProvider` (alongside `ThemeProvider`):
|
|
584
|
+
```tsx
|
|
585
|
+
import { ThemeProvider, BottomSheetModalProvider } from '@retray-dev/ui-kit'
|
|
586
|
+
|
|
587
|
+
<ThemeProvider>
|
|
588
|
+
<BottomSheetModalProvider>
|
|
589
|
+
{/* rest of app */}
|
|
590
|
+
</BottomSheetModalProvider>
|
|
591
|
+
</ThemeProvider>
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
**Peer dependencies** (install in your app):
|
|
595
|
+
```bash
|
|
596
|
+
pnpm add @gorhom/bottom-sheet react-native-reanimated react-native-gesture-handler
|
|
597
|
+
```
|
|
598
|
+
Add `react-native-reanimated/plugin` to your `babel.config.js` plugins.
|
|
599
|
+
|
|
600
|
+
| Prop | Type | Default | Notes |
|
|
601
|
+
|------|------|---------|-------|
|
|
602
|
+
| open | `boolean` | required | — |
|
|
603
|
+
| onClose | `() => void` | required | Called on swipe-dismiss or backdrop press |
|
|
604
|
+
| snapPoints | `(string \| number)[]` | `['50%']` | Snap positions, e.g. `['40%', '80%']` |
|
|
605
|
+
| title | `string` | — | — |
|
|
606
|
+
| description | `string` | — | — |
|
|
607
|
+
| children | `ReactNode` | — | — |
|
|
608
|
+
|
|
609
|
+
**Example:**
|
|
610
|
+
```tsx
|
|
611
|
+
<Sheet open={open} onClose={() => setOpen(false)} title="Filters" snapPoints={['50%']}>
|
|
612
|
+
<RadioGroup options={sortOptions} value={sort} onValueChange={setSort} />
|
|
613
|
+
</Sheet>
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
### Toast / useToast
|
|
621
|
+
|
|
622
|
+
**Import:** `import { ToastProvider, useToast } from '@retray-dev/ui-kit'`
|
|
623
|
+
**When to use:** Ephemeral feedback messages (save success, network error, copy confirmation).
|
|
624
|
+
|
|
625
|
+
**Setup:** `ToastProvider` must be in the app root (see Setup section above).
|
|
626
|
+
|
|
627
|
+
```tsx
|
|
628
|
+
import { useToast } from '@retray-dev/ui-kit'
|
|
629
|
+
|
|
630
|
+
function MyComponent() {
|
|
631
|
+
const { toast, dismiss } = useToast()
|
|
632
|
+
|
|
633
|
+
return (
|
|
634
|
+
<Button
|
|
635
|
+
label="Save"
|
|
636
|
+
onPress={async () => {
|
|
637
|
+
await save()
|
|
638
|
+
toast({ title: 'Saved', description: 'Your changes were saved.', variant: 'success' })
|
|
639
|
+
}}
|
|
640
|
+
/>
|
|
641
|
+
)
|
|
642
|
+
}
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
**`toast()` options:**
|
|
646
|
+
|
|
647
|
+
| Field | Type | Default | Notes |
|
|
648
|
+
|-------|------|---------|-------|
|
|
649
|
+
| title | `string` | — | Bold heading |
|
|
650
|
+
| description | `string` | — | Detail text |
|
|
651
|
+
| variant | `'default' \| 'destructive' \| 'success'` | `'default'` | `default`: dark background. `destructive`: red. `success`: green |
|
|
652
|
+
| duration | `number` (ms) | `3000` | Auto-dismiss after this delay |
|
|
653
|
+
|
|
654
|
+
**Notes:** Max 3 toasts shown simultaneously. Toasts appear at the top of the screen. `dismiss(id)` dismisses programmatically (the `id` is returned by `toast()`... track it if needed).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Julian Camilo Cruz Sanchez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|