@retray-dev/ui-kit 5.2.0 → 5.4.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/EXAMPLES.md ADDED
@@ -0,0 +1,666 @@
1
+ # @retray-dev/ui-kit — Composition Examples
2
+
3
+ This file contains full-code examples of complete app screens built by composing multiple UI kit components. These are working examples from the `example/` app, demonstrating real-world component patterns, state management, and navigation.
4
+
5
+ **For AI agents:** Use these examples as reference patterns when building screens with this UI kit. They show proper imports, state management, navigation, haptics integration, and component composition.
6
+
7
+ ---
8
+
9
+ ## Example 1: Finance Dashboard
10
+
11
+ **Use case:** Personal finance app home screen with budget tracking, transaction list, and expense breakdown.
12
+
13
+ **Components used:** MonthPicker, CurrencyDisplay, Progress, CategoryStrip, ListItem, DetailRow, Card, Button, Text, Icon
14
+
15
+ **Features:**
16
+ - Month selection with locale support
17
+ - Hero balance display with auto-scaling
18
+ - Budget progress tracking with visual indicator
19
+ - Category filtering with horizontal scrollable tabs
20
+ - Transaction list with custom icons and color-coded amounts
21
+ - Expense breakdown with separator hierarchy
22
+ - Export action with success toast
23
+
24
+ ### State Setup
25
+
26
+ ```tsx
27
+ const [financeMonth, setFinanceMonth] = useState({ month: 5, year: 2026 })
28
+ const [financeCategory, setFinanceCategory] = useState('all')
29
+
30
+ const FINANCE_CATEGORIES = [
31
+ { label: 'Todo', value: 'all', icon: 'layers' },
32
+ { label: 'Comida', value: 'food', icon: 'coffee' },
33
+ { label: 'Transporte', value: 'transport', icon: 'truck' },
34
+ { label: 'Salud', value: 'health', icon: 'heart' },
35
+ ]
36
+ ```
37
+
38
+ ### Implementation
39
+
40
+ ```tsx
41
+ import { View, ScrollView, StyleSheet } from 'react-native'
42
+ import {
43
+ Card,
44
+ CardContent,
45
+ MonthPicker,
46
+ CurrencyDisplay,
47
+ Progress,
48
+ CategoryStrip,
49
+ ListItem,
50
+ DetailRow,
51
+ Separator,
52
+ Button,
53
+ Text,
54
+ useTheme,
55
+ useToast,
56
+ } from '@retray-dev/ui-kit'
57
+
58
+ function FinanceDashboard() {
59
+ const { colors } = useTheme()
60
+ const { toast } = useToast()
61
+
62
+ return (
63
+ <View style={[styles.fullScreen, { backgroundColor: colors.background }]}>
64
+ {/* Header */}
65
+ <View style={[styles.screenHeader, { backgroundColor: colors.card, borderBottomColor: colors.border }]}>
66
+ <Button
67
+ label="Volver"
68
+ variant="text"
69
+ size="sm"
70
+ iconName="arrow-left"
71
+ onPress={() => {/* navigate back */}}
72
+ />
73
+ <Text variant="title-sm">Resumen financiero</Text>
74
+ <View style={{ width: 70 }} />
75
+ </View>
76
+
77
+ {/* Content */}
78
+ <ScrollView contentContainerStyle={styles.screenContent}>
79
+ {/* Month Selector */}
80
+ <MonthPicker value={financeMonth} onChange={setFinanceMonth} locale="es" />
81
+ <View style={{ height: 16 }} />
82
+
83
+ {/* Balance Card */}
84
+ <Card>
85
+ <CardContent>
86
+ <Text variant="caption" color={colors.foregroundMuted}>Gastos del mes</Text>
87
+ <CurrencyDisplay value={1250000} variant="hero" autoScale />
88
+ <View style={{ height: 8 }} />
89
+ <Progress value={78} variant="destructive" />
90
+ <Text variant="caption-sm" color={colors.foregroundMuted}>
91
+ 78% del presupuesto · $1.600.000
92
+ </Text>
93
+ </CardContent>
94
+ </Card>
95
+ <View style={{ height: 12 }} />
96
+
97
+ {/* Category Filter */}
98
+ <CategoryStrip
99
+ categories={FINANCE_CATEGORIES}
100
+ value={financeCategory}
101
+ onValueChange={(v) => setFinanceCategory(Array.isArray(v) ? v[0] ?? 'all' : v)}
102
+ />
103
+ <View style={{ height: 16 }} />
104
+
105
+ {/* Transaction List */}
106
+ <Text variant="caption" style={{ marginBottom: 8 }}>Movimientos recientes</Text>
107
+ <ListItem
108
+ title="Rappi"
109
+ subtitle="Comida · 12 may"
110
+ leftRender={
111
+ <View style={[styles.txIcon, { backgroundColor: '#fff3f0' }]}>
112
+ <Text>🛵</Text>
113
+ </View>
114
+ }
115
+ rightRender={<Text variant="title-sm" color={colors.destructive}>−$45.000</Text>}
116
+ showSeparator
117
+ onPress={() => {}}
118
+ />
119
+ <ListItem
120
+ title="Metro"
121
+ subtitle="Transporte · 11 may"
122
+ leftRender={
123
+ <View style={[styles.txIcon, { backgroundColor: '#f0f4ff' }]}>
124
+ <Text>🚇</Text>
125
+ </View>
126
+ }
127
+ rightRender={<Text variant="title-sm" color={colors.destructive}>−$5.200</Text>}
128
+ showSeparator
129
+ onPress={() => {}}
130
+ />
131
+ <ListItem
132
+ title="Nómina"
133
+ subtitle="Ingreso · 1 may"
134
+ leftRender={
135
+ <View style={[styles.txIcon, { backgroundColor: '#f0fdf4' }]}>
136
+ <Text>💼</Text>
137
+ </View>
138
+ }
139
+ rightRender={<Text variant="title-sm" color={colors.success}>+$3.500.000</Text>}
140
+ onPress={() => {}}
141
+ />
142
+ <View style={{ height: 16 }} />
143
+
144
+ {/* Expense Breakdown */}
145
+ <Text variant="caption" style={{ marginBottom: 8 }}>Desglose</Text>
146
+ <View style={{ gap: 8 }}>
147
+ <DetailRow label="Comida & bebida" value="$380.000" leftIconName="coffee" />
148
+ <DetailRow label="Transporte" value="$95.000" leftIconName="truck" />
149
+ <DetailRow label="Entretenimiento" value="$210.000" leftIconName="music" />
150
+ <DetailRow label="Salud" value="$85.000" leftIconName="heart" />
151
+ <DetailRow label="Otros" value="$480.000" leftIconName="more-horizontal" />
152
+ <Separator />
153
+ <DetailRow label="Total" value="$1.250.000" labelWeight="bold" separator="none" rightIconName="trending-up" />
154
+ </View>
155
+ <View style={{ height: 24 }} />
156
+
157
+ {/* Export Action */}
158
+ <Button
159
+ label="Exportar reporte"
160
+ fullWidth
161
+ iconName="download"
162
+ onPress={() => {
163
+ toast({ title: 'Reporte exportado', variant: 'success' })
164
+ }}
165
+ />
166
+ <View style={{ height: 32 }} />
167
+ </ScrollView>
168
+ </View>
169
+ )
170
+ }
171
+
172
+ const styles = StyleSheet.create({
173
+ fullScreen: {
174
+ flex: 1,
175
+ },
176
+ screenHeader: {
177
+ flexDirection: 'row',
178
+ alignItems: 'center',
179
+ justifyContent: 'space-between',
180
+ paddingHorizontal: 8,
181
+ paddingVertical: 8,
182
+ borderBottomWidth: StyleSheet.hairlineWidth,
183
+ },
184
+ screenContent: {
185
+ padding: 16,
186
+ paddingBottom: 48,
187
+ },
188
+ txIcon: {
189
+ width: 40,
190
+ height: 40,
191
+ borderRadius: 12,
192
+ alignItems: 'center',
193
+ justifyContent: 'center',
194
+ },
195
+ })
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Example 2: Edit Profile
201
+
202
+ **Use case:** User profile settings editor with avatar, form fields, toggles, and verification status.
203
+
204
+ **Components used:** Avatar, Badge, Input, Select, Switch, Card, AlertBanner, Button, Text, Separator
205
+
206
+ **Features:**
207
+ - Avatar with online status indicator
208
+ - Membership tier badge
209
+ - Form fields with prefix icons and proper keyboard types
210
+ - Country selection dropdown
211
+ - Toggle switches for preferences
212
+ - Success banner for verification status
213
+ - Save/cancel navigation with toast feedback
214
+
215
+ ### State Setup
216
+
217
+ ```tsx
218
+ const [profileName, setProfileName] = useState('Julian Cruz')
219
+ const [profileEmail, setProfileEmail] = useState('julian@email.com')
220
+ const [switchOn, setSwitchOn] = useState(false)
221
+ const [darkMode, setDarkMode] = useState(false)
222
+ ```
223
+
224
+ ### Implementation
225
+
226
+ ```tsx
227
+ import { View, ScrollView, StyleSheet } from 'react-native'
228
+ import {
229
+ Avatar,
230
+ Badge,
231
+ Input,
232
+ Select,
233
+ Switch,
234
+ Card,
235
+ CardContent,
236
+ Separator,
237
+ AlertBanner,
238
+ Button,
239
+ Text,
240
+ useTheme,
241
+ useToast,
242
+ } from '@retray-dev/ui-kit'
243
+
244
+ function EditProfile() {
245
+ const { colors } = useTheme()
246
+ const { toast } = useToast()
247
+
248
+ return (
249
+ <View style={[styles.fullScreen, { backgroundColor: colors.background }]}>
250
+ {/* Header */}
251
+ <View style={[styles.screenHeader, { backgroundColor: colors.card, borderBottomColor: colors.border }]}>
252
+ <Button
253
+ label="Cancelar"
254
+ variant="text"
255
+ size="sm"
256
+ onPress={() => {/* navigate back */}}
257
+ />
258
+ <Text variant="title-sm">Editar perfil</Text>
259
+ <Button
260
+ label="Guardar"
261
+ variant="text"
262
+ size="sm"
263
+ onPress={() => {
264
+ toast({ title: 'Perfil actualizado', variant: 'success' })
265
+ }}
266
+ />
267
+ </View>
268
+
269
+ {/* Content */}
270
+ <ScrollView contentContainerStyle={styles.screenContent} keyboardShouldPersistTaps="handled">
271
+ {/* Avatar Section */}
272
+ <View style={{ alignItems: 'center', marginBottom: 24 }}>
273
+ <Avatar fallbackText={profileName || 'Usuario'} size={80} status="online" />
274
+ <View style={{ height: 12 }} />
275
+ <Badge label="Pro Member" variant="success" iconName="check-circle" />
276
+ </View>
277
+
278
+ {/* Form Fields */}
279
+ <Input
280
+ label="Nombre completo"
281
+ value={profileName}
282
+ onChangeText={setProfileName}
283
+ prefixIcon="user"
284
+ placeholder="Tu nombre"
285
+ />
286
+ <View style={{ height: 12 }} />
287
+ <Input
288
+ label="Email"
289
+ value={profileEmail}
290
+ onChangeText={setProfileEmail}
291
+ prefixIcon="mail"
292
+ placeholder="tu@email.com"
293
+ keyboardType="email-address"
294
+ autoCapitalize="none"
295
+ />
296
+ <View style={{ height: 12 }} />
297
+ <Select
298
+ label="País"
299
+ value="CO"
300
+ onValueChange={() => {}}
301
+ options={[
302
+ { label: 'Colombia', value: 'CO' },
303
+ { label: 'México', value: 'MX' },
304
+ { label: 'Argentina', value: 'AR' },
305
+ ]}
306
+ />
307
+ <View style={{ height: 20 }} />
308
+
309
+ {/* Preferences Card */}
310
+ <Text variant="caption" style={{ marginBottom: 8 }}>Preferencias</Text>
311
+ <Card>
312
+ <CardContent>
313
+ <View style={{ gap: 12 }}>
314
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
315
+ <Text variant="body-sm">Notificaciones</Text>
316
+ <Switch checked={switchOn} onCheckedChange={setSwitchOn} />
317
+ </View>
318
+ <Separator />
319
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
320
+ <Text variant="body-sm">Modo oscuro</Text>
321
+ <Switch checked={darkMode} onCheckedChange={setDarkMode} />
322
+ </View>
323
+ </View>
324
+ </CardContent>
325
+ </Card>
326
+ <View style={{ height: 16 }} />
327
+
328
+ {/* Verification Banner */}
329
+ <AlertBanner
330
+ variant="success"
331
+ title="Cuenta verificada"
332
+ description="Tu email ha sido verificado correctamente."
333
+ iconName="shield"
334
+ />
335
+ <View style={{ height: 32 }} />
336
+ </ScrollView>
337
+ </View>
338
+ )
339
+ }
340
+
341
+ const styles = StyleSheet.create({
342
+ fullScreen: {
343
+ flex: 1,
344
+ },
345
+ screenHeader: {
346
+ flexDirection: 'row',
347
+ alignItems: 'center',
348
+ justifyContent: 'space-between',
349
+ paddingHorizontal: 8,
350
+ paddingVertical: 8,
351
+ borderBottomWidth: StyleSheet.hairlineWidth,
352
+ },
353
+ screenContent: {
354
+ padding: 16,
355
+ paddingBottom: 48,
356
+ },
357
+ })
358
+ ```
359
+
360
+ ---
361
+
362
+ ## Example 3: Onboarding Flow
363
+
364
+ **Use case:** Multi-step wizard for user onboarding with progress tracking and conditional rendering.
365
+
366
+ **Components used:** Badge, Progress, Input, RadioGroup, EmptyState, Button, Text
367
+
368
+ **Features:**
369
+ - 3-step wizard with step indicator and progress bar
370
+ - Conditional rendering per step
371
+ - Name input with icon
372
+ - Goal selection with radio options
373
+ - Success state with illustration
374
+ - Contextual navigation (back/continue/start)
375
+ - Completion toast with dynamic message
376
+
377
+ ### State Setup
378
+
379
+ ```tsx
380
+ const [onboardingStep, setOnboardingStep] = useState(0)
381
+ const [onboardingName, setOnboardingName] = useState('')
382
+ const [onboardingGoal, setOnboardingGoal] = useState('save')
383
+ ```
384
+
385
+ ### Implementation
386
+
387
+ ```tsx
388
+ import { View, ScrollView, StyleSheet } from 'react-native'
389
+ import {
390
+ Badge,
391
+ Progress,
392
+ Input,
393
+ RadioGroup,
394
+ EmptyState,
395
+ Button,
396
+ ButtonGroup,
397
+ Text,
398
+ useTheme,
399
+ useToast,
400
+ } from '@retray-dev/ui-kit'
401
+
402
+ function OnboardingFlow() {
403
+ const { colors } = useTheme()
404
+ const { toast } = useToast()
405
+
406
+ return (
407
+ <View style={[styles.fullScreen, { backgroundColor: colors.background }]}>
408
+ {/* Header */}
409
+ <View style={[styles.screenHeader, { backgroundColor: colors.card, borderBottomColor: colors.border }]}>
410
+ <Button
411
+ label="Cerrar"
412
+ variant="text"
413
+ size="sm"
414
+ onPress={() => {/* close onboarding */}}
415
+ />
416
+ <Text variant="title-sm">Bienvenido</Text>
417
+ <View style={{ width: 70 }} />
418
+ </View>
419
+
420
+ {/* Content */}
421
+ <ScrollView contentContainerStyle={styles.screenContent} keyboardShouldPersistTaps="handled">
422
+ {/* Progress Indicator */}
423
+ <View style={{ alignItems: 'center', marginBottom: 16 }}>
424
+ <Badge label={`Paso ${onboardingStep + 1} de 3`} variant="secondary" />
425
+ <View style={{ height: 12 }} />
426
+ <Progress value={(onboardingStep + 1) * 33.3} style={{ width: '100%' }} />
427
+ </View>
428
+
429
+ {/* Step 1: Name */}
430
+ {onboardingStep === 0 && (
431
+ <View style={{ gap: 16 }}>
432
+ <Text variant="display-md" style={{ textAlign: 'center' }}>¡Hola! 👋</Text>
433
+ <Text variant="body-sm" color={colors.foregroundMuted} style={{ textAlign: 'center' }}>
434
+ Cuéntanos un poco sobre ti para personalizar tu experiencia.
435
+ </Text>
436
+ <Input
437
+ label="¿Cómo te llamas?"
438
+ value={onboardingName}
439
+ onChangeText={setOnboardingName}
440
+ placeholder="Tu nombre"
441
+ prefixIcon="user"
442
+ />
443
+ </View>
444
+ )}
445
+
446
+ {/* Step 2: Goal Selection */}
447
+ {onboardingStep === 1 && (
448
+ <View style={{ gap: 16 }}>
449
+ <Text variant="display-md" style={{ textAlign: 'center' }}>¿Cuál es tu meta?</Text>
450
+ <Text variant="body-sm" color={colors.foregroundMuted} style={{ textAlign: 'center' }}>
451
+ Te ayudaremos a alcanzarla.
452
+ </Text>
453
+ <RadioGroup
454
+ value={onboardingGoal}
455
+ onValueChange={setOnboardingGoal}
456
+ options={[
457
+ { label: 'Ahorrar dinero', value: 'save' },
458
+ { label: 'Pagar deudas', value: 'debt' },
459
+ { label: 'Invertir', value: 'invest' },
460
+ { label: 'Control de gastos', value: 'control' },
461
+ ]}
462
+ />
463
+ </View>
464
+ )}
465
+
466
+ {/* Step 3: Completion */}
467
+ {onboardingStep === 2 && (
468
+ <View style={{ gap: 16 }}>
469
+ <Text variant="display-md" style={{ textAlign: 'center' }}>
470
+ ¡Listo, {onboardingName || 'amigo'}!
471
+ </Text>
472
+ <Text variant="body-sm" color={colors.foregroundMuted} style={{ textAlign: 'center' }}>
473
+ Tu cuenta está configurada. Empieza a explorar.
474
+ </Text>
475
+ <EmptyState
476
+ iconName="check-circle"
477
+ title="Todo configurado"
478
+ description="Toca continuar para empezar."
479
+ />
480
+ </View>
481
+ )}
482
+
483
+ <View style={{ height: 32 }} />
484
+
485
+ {/* Navigation Buttons */}
486
+ {onboardingStep === 0 ? (
487
+ <Button
488
+ label="Continuar"
489
+ fullWidth
490
+ iconName="arrow-right"
491
+ onPress={() => setOnboardingStep((s) => s + 1)}
492
+ />
493
+ ) : (
494
+ <ButtonGroup gap={8}>
495
+ <Button
496
+ label="Atrás"
497
+ variant="secondary"
498
+ onPress={() => setOnboardingStep((s) => s - 1)}
499
+ />
500
+ <Button
501
+ label={onboardingStep === 2 ? 'Empezar' : 'Continuar'}
502
+ iconName={onboardingStep === 2 ? 'check' : 'arrow-right'}
503
+ onPress={() => {
504
+ if (onboardingStep < 2) {
505
+ setOnboardingStep((s) => s + 1)
506
+ } else {
507
+ setOnboardingStep(0)
508
+ toast({
509
+ title: `¡Bienvenido, ${onboardingName || 'amigo'}!`,
510
+ variant: 'success'
511
+ })
512
+ }
513
+ }}
514
+ />
515
+ </ButtonGroup>
516
+ )}
517
+ <View style={{ height: 32 }} />
518
+ </ScrollView>
519
+ </View>
520
+ )
521
+ }
522
+
523
+ const styles = StyleSheet.create({
524
+ fullScreen: {
525
+ flex: 1,
526
+ },
527
+ screenHeader: {
528
+ flexDirection: 'row',
529
+ alignItems: 'center',
530
+ justifyContent: 'space-between',
531
+ paddingHorizontal: 8,
532
+ paddingVertical: 8,
533
+ borderBottomWidth: StyleSheet.hairlineWidth,
534
+ },
535
+ screenContent: {
536
+ padding: 16,
537
+ paddingBottom: 48,
538
+ },
539
+ })
540
+ ```
541
+
542
+ ---
543
+
544
+ ## Common Patterns
545
+
546
+ ### Full-Screen Overlay Pattern
547
+
548
+ All examples use a full-screen overlay with consistent header structure:
549
+
550
+ ```tsx
551
+ <View style={styles.fullScreen}>
552
+ {/* Header with navigation */}
553
+ <View style={styles.screenHeader}>
554
+ <Button label="Back" variant="text" size="sm" onPress={onBack} />
555
+ <Text variant="title-sm">Screen Title</Text>
556
+ <View style={{ width: 70 }} /> {/* Spacer for center alignment */}
557
+ </View>
558
+
559
+ {/* Scrollable content */}
560
+ <ScrollView contentContainerStyle={styles.screenContent}>
561
+ {/* content */}
562
+ </ScrollView>
563
+ </View>
564
+ ```
565
+
566
+ ### Spacing Pattern
567
+
568
+ Consistent vertical rhythm with explicit `<View style={{ height: X }} />` separators:
569
+
570
+ ```tsx
571
+ <ComponentA />
572
+ <View style={{ height: 16 }} />
573
+ <ComponentB />
574
+ ```
575
+
576
+ ### Color Usage
577
+
578
+ Always pull colors from theme via `useTheme()`:
579
+
580
+ ```tsx
581
+ const { colors } = useTheme()
582
+
583
+ <View style={{ backgroundColor: colors.card, borderColor: colors.border }}>
584
+ <Text color={colors.foregroundMuted}>Caption text</Text>
585
+ </View>
586
+ ```
587
+
588
+ ### Form Field Spacing
589
+
590
+ Standard 12px gap between fields:
591
+
592
+ ```tsx
593
+ <Input label="Field 1" />
594
+ <View style={{ height: 12 }} />
595
+ <Input label="Field 2" />
596
+ ```
597
+
598
+ ### Toast Feedback
599
+
600
+ Use `useToast()` for success/error feedback after actions:
601
+
602
+ ```tsx
603
+ const { toast } = useToast()
604
+
605
+ toast({ title: 'Action completed', variant: 'success' })
606
+ toast({ title: 'Error occurred', variant: 'destructive' })
607
+ ```
608
+
609
+ ### Button Pairs & Groups
610
+
611
+ Use `ButtonGroup` for equally-spaced button layouts (50%/50% split):
612
+
613
+ ```tsx
614
+ // Horizontal pair (Cancel/Confirm pattern)
615
+ // Use size="sm" when icons are present to prevent text clipping on mobile
616
+ <ButtonGroup>
617
+ <Button label="Cancel" variant="secondary" size="sm" iconName="x" onPress={handleCancel} />
618
+ <Button label="Confirm" size="sm" iconName="check" onPress={handleConfirm} />
619
+ </ButtonGroup>
620
+
621
+ // Vertical stack
622
+ <ButtonGroup vertical gap={8}>
623
+ <Button label="Primary Action" size="sm" iconName="zap" onPress={handlePrimary} />
624
+ <Button label="Secondary Action" variant="secondary" size="sm" iconName="settings" onPress={handleSecondary} />
625
+ <Button label="Delete" variant="destructive" size="sm" iconName="trash-2" onPress={handleDelete} />
626
+ </ButtonGroup>
627
+
628
+ // Conditional rendering (single vs pair)
629
+ {isFirstStep ? (
630
+ <Button label="Continue" fullWidth iconName="arrow-right" onPress={handleNext} />
631
+ ) : (
632
+ <ButtonGroup>
633
+ <Button label="Back" variant="secondary" onPress={handleBack} />
634
+ <Button label="Continue" iconName="arrow-right" onPress={handleNext} />
635
+ </ButtonGroup>
636
+ )}
637
+ ```
638
+
639
+ ---
640
+
641
+ ## Running the Examples
642
+
643
+ These examples are live in the `example/` app included with the source. To run them:
644
+
645
+ ```bash
646
+ # Clone the repo
647
+ git clone https://github.com/YOUR_USERNAME/retray-ui-kit
648
+ cd retray-ui-kit
649
+
650
+ # Install dependencies
651
+ pnpm install
652
+
653
+ # Build the library
654
+ pnpm build
655
+
656
+ # Run the example app
657
+ cd example
658
+ pnpm start
659
+ # Or: pnpm ios / pnpm android
660
+ ```
661
+
662
+ Inside the example app, navigate to the "🖥 App Screen Compositions" accordion to access all three screens.
663
+
664
+ ---
665
+
666
+ **For AI agents:** When generating screens, follow these patterns for consistency with the library's design philosophy. Use the theme colors, typography variants, spacing tokens, and component props shown in these examples.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A personal React Native / Expo UI component library with a built-in design system, dark mode support, haptic feedback, and smooth animations.
4
4
 
5
- - 36 components across 7 categories
5
+ - 37 components across 7 categories
6
6
  - Light/dark theme with 12 public tokens (24 resolved) and full customization
7
7
  - Apple HIG–compliant touch targets and haptic feedback
8
8
  - Animated interactions: spring press, sliding tabs, accordion easing, animated progress
@@ -142,11 +142,11 @@ import { SPACING, ICON_SIZES, RADIUS, SHADOWS, BREAKPOINTS, TYPOGRAPHY } from '@
142
142
  | ----------- | ----------------------------------------------------------------------------------------------- |
143
143
  | Display | `Text`, `Badge`, `Avatar`, `Separator`, `Spinner`, `Skeleton`, `Progress`, `CurrencyDisplay` |
144
144
  | Surfaces | `Card`, `AlertBanner`, `EmptyState`, `MediaCard` |
145
- | Form | `Button`, `IconButton`, `Input`, `CurrencyInput`, `Textarea`, `Checkbox`, `Switch`, `Toggle`, `RadioGroup`, `Select`, `Slider` |
145
+ | Form | `Button`, `ButtonGroup`, `IconButton`, `Input`, `CurrencyInput`, `Textarea`, `Checkbox`, `Switch`, `Toggle`, `RadioGroup`, `Select`, `Slider` |
146
146
  | Composition | `Tabs`, `Accordion` |
147
147
  | Overlays | `Sheet`, `ConfirmDialog` |
148
148
  | Feedback | `Toast` / `ToastProvider` / `useToast` |
149
- | Data | `ListItem`, `Chip` / `ChipGroup`, `LabelValue`, `MonthPicker`, `CategoryStrip` |
149
+ | Data | `ListItem`, `Chip` / `ChipGroup`, `LabelValue`, `MonthPicker`, `CategoryStrip`, `DetailRow` |
150
150
  | Utilities | `Pressable` |
151
151
 
152
152
  ### Quick examples