@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.
Files changed (56) hide show
  1. package/COMPONENTS.md +654 -0
  2. package/LICENSE +21 -0
  3. package/README.md +151 -0
  4. package/dist/index.d.mts +309 -3
  5. package/dist/index.d.ts +309 -3
  6. package/dist/index.js +1477 -57
  7. package/dist/index.mjs +1424 -57
  8. package/package.json +27 -5
  9. package/src/components/Accordion/Accordion.tsx +161 -0
  10. package/src/components/Accordion/index.ts +2 -0
  11. package/src/components/Alert/Alert.tsx +57 -0
  12. package/src/components/Alert/index.ts +2 -0
  13. package/src/components/Avatar/Avatar.tsx +67 -0
  14. package/src/components/Avatar/index.ts +2 -0
  15. package/src/components/Badge/Badge.tsx +48 -0
  16. package/src/components/Badge/index.ts +2 -0
  17. package/src/components/Button/Button.tsx +78 -45
  18. package/src/components/Card/Card.tsx +109 -0
  19. package/src/components/Card/index.ts +9 -0
  20. package/src/components/Checkbox/Checkbox.tsx +70 -0
  21. package/src/components/Checkbox/index.ts +2 -0
  22. package/src/components/EmptyState/EmptyState.tsx +69 -0
  23. package/src/components/EmptyState/index.ts +2 -0
  24. package/src/components/Input/Input.tsx +26 -41
  25. package/src/components/Progress/Progress.tsx +53 -0
  26. package/src/components/Progress/index.ts +2 -0
  27. package/src/components/RadioGroup/RadioGroup.tsx +105 -0
  28. package/src/components/RadioGroup/index.ts +2 -0
  29. package/src/components/Select/Select.tsx +185 -0
  30. package/src/components/Select/index.ts +2 -0
  31. package/src/components/Separator/Separator.tsx +33 -0
  32. package/src/components/Separator/index.ts +2 -0
  33. package/src/components/Sheet/Sheet.tsx +108 -0
  34. package/src/components/Sheet/index.ts +2 -0
  35. package/src/components/Skeleton/Skeleton.tsx +40 -0
  36. package/src/components/Skeleton/index.ts +2 -0
  37. package/src/components/Slider/Slider.tsx +142 -0
  38. package/src/components/Slider/index.ts +2 -0
  39. package/src/components/Spinner/Spinner.tsx +27 -0
  40. package/src/components/Spinner/index.ts +2 -0
  41. package/src/components/Switch/Switch.tsx +82 -0
  42. package/src/components/Switch/index.ts +2 -0
  43. package/src/components/Tabs/Tabs.tsx +145 -0
  44. package/src/components/Tabs/index.ts +2 -0
  45. package/src/components/Text/Text.tsx +10 -4
  46. package/src/components/Textarea/Textarea.tsx +70 -0
  47. package/src/components/Textarea/index.ts +2 -0
  48. package/src/components/Toast/Toast.tsx +164 -0
  49. package/src/components/Toast/index.ts +2 -0
  50. package/src/components/Toggle/Toggle.tsx +80 -0
  51. package/src/components/Toggle/index.ts +2 -0
  52. package/src/index.ts +26 -0
  53. package/src/theme/ThemeProvider.tsx +47 -0
  54. package/src/theme/colors.ts +41 -0
  55. package/src/theme/index.ts +4 -0
  56. 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.