@retray-dev/ui-kit 2.5.2 → 2.7.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 +245 -5
- package/README.md +18 -0
- package/dist/index.d.mts +173 -8
- package/dist/index.d.ts +173 -8
- package/dist/index.js +319 -179
- package/dist/index.mjs +259 -132
- package/package.json +1 -1
- package/src/components/AlertBanner/AlertBanner.tsx +14 -2
- package/src/components/Badge/Badge.tsx +16 -2
- package/src/components/Button/Button.tsx +20 -3
- package/src/components/EmptyState/EmptyState.tsx +15 -3
- package/src/components/Input/Input.tsx +29 -8
- package/src/components/ListItem/ListItem.tsx +26 -3
- package/src/components/Toast/Toast.tsx +11 -1
- package/src/components/Toggle/Toggle.tsx +27 -2
- package/src/index.ts +21 -0
- package/src/tokens.ts +69 -0
- package/src/utils/haptics.ts +18 -12
- package/src/utils/icons.ts +73 -0
package/COMPONENTS.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @retray-dev/ui-kit — Component Reference (v2.
|
|
1
|
+
# @retray-dev/ui-kit — Component Reference (v2.7.0)
|
|
2
2
|
|
|
3
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
4
|
|
|
@@ -105,6 +105,99 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
|
|
|
105
105
|
|
|
106
106
|
---
|
|
107
107
|
|
|
108
|
+
## Design Tokens
|
|
109
|
+
|
|
110
|
+
Static structural constants exported from the package root — no context or provider needed. Use these instead of hardcoding values.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { SPACING, ICON_SIZES, RADIUS, SHADOWS, BREAKPOINTS } from '@retray-dev/ui-kit'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### SPACING
|
|
117
|
+
|
|
118
|
+
8pt-grid spacing scale.
|
|
119
|
+
|
|
120
|
+
| Key | Value |
|
|
121
|
+
|-----|-------|
|
|
122
|
+
| `xs` | 4 |
|
|
123
|
+
| `sm` | 8 |
|
|
124
|
+
| `md` | 12 |
|
|
125
|
+
| `lg` | 16 |
|
|
126
|
+
| `xl` | 24 |
|
|
127
|
+
| `2xl` | 32 |
|
|
128
|
+
| `3xl` | 48 |
|
|
129
|
+
|
|
130
|
+
**Types:** `Spacing`, `SpacingKey`
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
<View style={{ gap: SPACING.md, padding: SPACING.lg }} />
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### ICON_SIZES
|
|
137
|
+
|
|
138
|
+
Semantic icon size scale aligned to HIG roles.
|
|
139
|
+
|
|
140
|
+
| Key | Value |
|
|
141
|
+
|-----|-------|
|
|
142
|
+
| `sm` | 14 |
|
|
143
|
+
| `md` | 18 |
|
|
144
|
+
| `lg` | 22 |
|
|
145
|
+
| `xl` | 28 |
|
|
146
|
+
| `2xl` | 32 |
|
|
147
|
+
|
|
148
|
+
**Types:** `IconSize`, `IconSizeKey`
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
<Icon name="home" size={ICON_SIZES.md} color={colors.foreground} />
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### RADIUS
|
|
155
|
+
|
|
156
|
+
Border radius scale used throughout the library.
|
|
157
|
+
|
|
158
|
+
| Key | Value | Used in |
|
|
159
|
+
|-----|-------|---------|
|
|
160
|
+
| `sm` | 4 | — |
|
|
161
|
+
| `md` | 8 | Inputs, Buttons, Checkboxes, Toggles, Tabs |
|
|
162
|
+
| `lg` | 12 | Cards, AlertBanner, Toast, EmptyState, Select list |
|
|
163
|
+
| `xl` | 16 | Sheet top corners |
|
|
164
|
+
| `full` | 9999 | Pills, circular elements |
|
|
165
|
+
|
|
166
|
+
**Types:** `Radius`, `RadiusKey`
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
<View style={{ borderRadius: RADIUS.lg }} />
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### SHADOWS
|
|
173
|
+
|
|
174
|
+
Cross-platform shadow presets (RN `shadow*` properties + `elevation`).
|
|
175
|
+
|
|
176
|
+
| Key | Height | Opacity | Radius | Elevation |
|
|
177
|
+
|-----|--------|---------|--------|-----------|
|
|
178
|
+
| `sm` | 1 | 0.08 | 4 | 2 |
|
|
179
|
+
| `md` | 3 | 0.12 | 8 | 5 |
|
|
180
|
+
| `lg` | 6 | 0.20 | 16 | 10 |
|
|
181
|
+
| `xl` | 12 | 0.28 | 24 | 18 |
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
<View style={[styles.card, SHADOWS.md]} />
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### BREAKPOINTS
|
|
188
|
+
|
|
189
|
+
Layout breakpoints.
|
|
190
|
+
|
|
191
|
+
| Key | Value |
|
|
192
|
+
|-----|-------|
|
|
193
|
+
| `wide` | 700 |
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
const isWide = width >= BREAKPOINTS.wide
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
108
201
|
## Components
|
|
109
202
|
|
|
110
203
|
---
|
|
@@ -153,6 +246,8 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
|
|
|
153
246
|
| fullWidth | `boolean` | `false` | Stretches to container width (`alignSelf: 'stretch'`) |
|
|
154
247
|
| disabled | `boolean` | — | Reduces opacity to 0.5 |
|
|
155
248
|
| icon | `React.ReactNode \| ((props: { label, size, variant }) => React.ReactNode)` | — | Icon rendered alongside the label. Can be a node or a render function |
|
|
249
|
+
| iconName | `string` | — | Icon name from `@expo/vector-icons` (e.g. `"arrow-right"`). See [icons.expo.fyi](https://icons.expo.fyi). Takes precedence over `icon` |
|
|
250
|
+
| iconColor | `string` | — | Override icon color. Defaults to variant label color |
|
|
156
251
|
| iconPosition | `'left' \| 'right'` | `'left'` | Side the icon appears on |
|
|
157
252
|
|
|
158
253
|
**Variants:**
|
|
@@ -170,7 +265,8 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
|
|
|
170
265
|
<Button label="Cancel" variant="ghost" onPress={onCancel} />
|
|
171
266
|
<Button label="Delete" variant="outline" size="sm" />
|
|
172
267
|
<Button label="Submitting..." loading fullWidth />
|
|
173
|
-
<Button label="
|
|
268
|
+
<Button label="Continue" iconName="arrow-right" iconPosition="right" />
|
|
269
|
+
<Button label="Delete" variant="destructive" iconName="trash-2" />
|
|
174
270
|
```
|
|
175
271
|
|
|
176
272
|
---
|
|
@@ -190,6 +286,10 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
|
|
|
190
286
|
| suffix | `string \| ReactNode` | — | Content rendered after the input field (e.g., `"kg"` or a button) |
|
|
191
287
|
| prefixStyle | `TextStyle` | — | Style applied to the prefix text when prefix is a string |
|
|
192
288
|
| suffixStyle | `TextStyle` | — | Style applied to the suffix text when suffix is a string |
|
|
289
|
+
| prefixIcon | `string` | — | Icon name from `@expo/vector-icons` rendered before the input. Takes precedence over `prefix` |
|
|
290
|
+
| suffixIcon | `string` | — | Icon name from `@expo/vector-icons` rendered after the input. Takes precedence over `suffix` (unless `type="password"`) |
|
|
291
|
+
| prefixIconColor | `string` | — | Override prefix icon color. Defaults to `mutedForeground` |
|
|
292
|
+
| suffixIconColor | `string` | — | Override suffix icon color. Defaults to `mutedForeground` |
|
|
193
293
|
| type | `'text' \| 'password'` | `'text'` | When `'password'`, shows a visibility toggle button in the suffix slot |
|
|
194
294
|
| containerStyle | `ViewStyle` | — | Style for the outer container `View` |
|
|
195
295
|
|
|
@@ -202,6 +302,8 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
|
|
|
202
302
|
<Input label="Username" hint="Must be at least 4 characters" />
|
|
203
303
|
<Input label="Amount" prefix="$" placeholder="0.00" keyboardType="numeric" />
|
|
204
304
|
<Input label="Weight" suffix="kg" placeholder="0" />
|
|
305
|
+
<Input placeholder="Search..." prefixIcon="search" />
|
|
306
|
+
<Input placeholder="Amount" prefixIcon="dollar-sign" suffixIcon="check" />
|
|
205
307
|
```
|
|
206
308
|
|
|
207
309
|
---
|
|
@@ -285,6 +387,8 @@ const [amount, setAmount] = useState(0)
|
|
|
285
387
|
| variant | `'default' \| 'secondary' \| 'destructive' \| 'outline'` | `'default'` | — |
|
|
286
388
|
| size | `'sm' \| 'md' \| 'lg'` | `'md'` | Controls padding and font size |
|
|
287
389
|
| icon | `ReactNode` | — | Icon rendered before the label/children |
|
|
390
|
+
| iconName | `string` | — | Icon name from `@expo/vector-icons`. Takes precedence over `icon` |
|
|
391
|
+
| iconColor | `string` | — | Override icon color. Defaults to variant foreground color |
|
|
288
392
|
| style | `ViewStyle` | — | — |
|
|
289
393
|
|
|
290
394
|
**Example:**
|
|
@@ -293,7 +397,8 @@ const [amount, setAmount] = useState(0)
|
|
|
293
397
|
<Badge label="Error" variant="destructive" />
|
|
294
398
|
<Badge label="Draft" variant="secondary" size="sm" />
|
|
295
399
|
<Badge label="Beta" variant="outline" />
|
|
296
|
-
<Badge
|
|
400
|
+
<Badge label="Active" variant="default" iconName="check" size="sm" />
|
|
401
|
+
<Badge label="Error" variant="destructive" iconName="alert-circle" />
|
|
297
402
|
```
|
|
298
403
|
|
|
299
404
|
---
|
|
@@ -528,6 +633,8 @@ All sub-components (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`,
|
|
|
528
633
|
| description | `string` | — | Detail text |
|
|
529
634
|
| variant | `'default' \| 'destructive' \| 'success'` | `'default'` | Controls border/text color |
|
|
530
635
|
| icon | `ReactNode` | — | Icon placed to the left of the text content. Defaults to a variant-appropriate symbol (`ℹ`, `⚠`, `✓`) |
|
|
636
|
+
| iconName | `string` | — | Icon name from `@expo/vector-icons`. Takes precedence over `icon` (but still falls back to the variant default when neither is set) |
|
|
637
|
+
| iconColor | `string` | — | Override icon color. Defaults to the variant title color |
|
|
531
638
|
| style | `ViewStyle` | — | — |
|
|
532
639
|
|
|
533
640
|
**Example:**
|
|
@@ -535,6 +642,7 @@ All sub-components (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`,
|
|
|
535
642
|
<AlertBanner title="Info" description="Your session will expire in 5 minutes." />
|
|
536
643
|
<AlertBanner variant="destructive" title="Error" description="Failed to save. Try again." />
|
|
537
644
|
<AlertBanner variant="success" title="Done" description="Your changes have been saved." />
|
|
645
|
+
<AlertBanner iconName="bell" title="Reminder" description="Complete your profile." />
|
|
538
646
|
```
|
|
539
647
|
|
|
540
648
|
---
|
|
@@ -549,6 +657,8 @@ All sub-components (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`,
|
|
|
549
657
|
| title | `string` | required | — |
|
|
550
658
|
| description | `string` | — | — |
|
|
551
659
|
| icon | `ReactNode` | — | Shown in a 48×48 muted square above the text |
|
|
660
|
+
| iconName | `string` | — | Icon name from `@expo/vector-icons`. Takes precedence over `icon`. Sized automatically (48 default, 32 compact) |
|
|
661
|
+
| iconColor | `string` | — | Override icon color. Defaults to `mutedForeground` |
|
|
552
662
|
| action | `ReactNode` | — | Usually a `Button`, placed below the text |
|
|
553
663
|
| size | `'default' \| 'compact'` | `'default'` | `compact` hides description/action, uses a 36×36 icon, smaller title (15px), and tighter spacing |
|
|
554
664
|
| style | `ViewStyle` | — | — |
|
|
@@ -560,6 +670,8 @@ All sub-components (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`,
|
|
|
560
670
|
description="You're all caught up!"
|
|
561
671
|
action={<Button label="Refresh" variant="outline" size="sm" />}
|
|
562
672
|
/>
|
|
673
|
+
<EmptyState iconName="inbox" title="No messages" description="You're all caught up." />
|
|
674
|
+
<EmptyState iconName="search" title="No results" size="compact" />
|
|
563
675
|
```
|
|
564
676
|
|
|
565
677
|
---
|
|
@@ -621,14 +733,19 @@ const [accepted, setAccepted] = useState(false)
|
|
|
621
733
|
| label | `string` | — | Text label |
|
|
622
734
|
| icon | `ReactNode \| ((pressed: boolean) => ReactNode)` | — | Icon shown when not pressed — can be combined with `label` |
|
|
623
735
|
| activeIcon | `ReactNode \| ((pressed: boolean) => ReactNode)` | — | Icon shown when pressed. If omitted, a default `✓` check mark is shown |
|
|
736
|
+
| iconName | `string` | — | Icon name from `@expo/vector-icons` shown when not pressed. Takes precedence over `icon` |
|
|
737
|
+
| activeIconName | `string` | — | Icon name shown when pressed. Takes precedence over `activeIcon` |
|
|
738
|
+
| iconColor | `string` | — | Override inactive icon color. Defaults to `mutedForeground` |
|
|
739
|
+
| activeIconColor | `string` | — | Override active icon color. Defaults to `primary` |
|
|
624
740
|
|
|
625
741
|
**Animation:** `borderColor` and `backgroundColor` animate via `Animated.timing` (150ms, `Easing.out`) on press state change. `borderWidth` stays fixed at 2pt to prevent layout jumps.
|
|
626
742
|
|
|
627
743
|
**Example:**
|
|
628
744
|
```tsx
|
|
629
745
|
<Toggle pressed={bold} onPressedChange={setBold} label="Bold" variant="outline" />
|
|
746
|
+
<Toggle pressed={muted} onPressedChange={setMuted} iconName="volume-x" activeIconName="volume" />
|
|
630
747
|
|
|
631
|
-
// With custom active icon
|
|
748
|
+
// With custom active icon (ReactNode)
|
|
632
749
|
<Toggle
|
|
633
750
|
pressed={favorited}
|
|
634
751
|
onPressedChange={setFavorited}
|
|
@@ -873,6 +990,9 @@ function MyComponent() {
|
|
|
873
990
|
onPress={async () => {
|
|
874
991
|
await save()
|
|
875
992
|
toast({ title: 'Saved', description: 'Your changes were saved.', variant: 'success' })
|
|
993
|
+
// With custom icon name
|
|
994
|
+
toast({ title: 'Saved', variant: 'success', iconName: 'check-circle' })
|
|
995
|
+
toast({ title: 'Oops', variant: 'destructive', iconName: 'x-circle' })
|
|
876
996
|
}}
|
|
877
997
|
/>
|
|
878
998
|
)
|
|
@@ -888,6 +1008,8 @@ function MyComponent() {
|
|
|
888
1008
|
| variant | `'default' \| 'destructive' \| 'success'` | `'default'` | `default`: dark background. `destructive`: red. `success`: green |
|
|
889
1009
|
| duration | `number` (ms) | `3000` | Auto-dismiss after this delay |
|
|
890
1010
|
| icon | `ReactNode` | — | Custom icon node. Defaults to a variant-appropriate symbol (`✓`, `✖`, `ℹ`) at 22px |
|
|
1011
|
+
| iconName | `string` | — | Icon name from `@expo/vector-icons`. Takes precedence over `icon` |
|
|
1012
|
+
| iconColor | `string` | — | Override icon color. Defaults to variant text color |
|
|
891
1013
|
|
|
892
1014
|
**`dismiss(id)`:** Dismiss a toast programmatically. The `id` is returned by the `toast()` call — store it if you need programmatic dismissal.
|
|
893
1015
|
|
|
@@ -913,6 +1035,10 @@ function MyComponent() {
|
|
|
913
1035
|
| caption | `string` | — | Tertiary / caption line below the subtitle (12px / 400 weight, 70% opacity) |
|
|
914
1036
|
| leftRender | `ReactNode` | — | Arbitrary content in a fixed 44×44pt left slot (avatar, icon, image, etc.) |
|
|
915
1037
|
| rightRender | `string \| ReactNode` | — | Content on the right edge. Strings are styled as muted text (15px); pass ReactNode for Badges, prices, switches, etc. |
|
|
1038
|
+
| leftIcon | `string` | — | Icon name from `@expo/vector-icons` in the left slot. Takes precedence over `leftRender`. Size 24, color `foreground` |
|
|
1039
|
+
| rightIcon | `string` | — | Icon name from `@expo/vector-icons` in the right slot. Takes precedence over `rightRender`. Size 24, color `mutedForeground` |
|
|
1040
|
+
| leftIconColor | `string` | — | Override left icon color |
|
|
1041
|
+
| rightIconColor | `string` | — | Override right icon color |
|
|
916
1042
|
| variant | `'plain' \| 'card'` | `'plain'` | `plain`: no background, sits inside a parent surface. `card`: standalone surface with background, border, and shadow |
|
|
917
1043
|
| showChevron | `boolean` | `false` | Shows a `›` chevron on the far right. Ignored when `rightRender` is set |
|
|
918
1044
|
| showSeparator | `boolean` | `false` | Renders a hairline separator at the bottom. Useful when stacking multiple plain items in a list |
|
|
@@ -952,10 +1078,14 @@ function MyComponent() {
|
|
|
952
1078
|
onPress={() => navigate('detail', { id: item.id })}
|
|
953
1079
|
/>
|
|
954
1080
|
|
|
1081
|
+
// Icon name props (no manual imports needed)
|
|
1082
|
+
<ListItem title="Profile" leftIcon="user" rightIcon="chevron-right" onPress={() => {}} />
|
|
1083
|
+
<ListItem title="Notifications" leftIcon="bell" subtitle="3 unread" showChevron />
|
|
1084
|
+
|
|
955
1085
|
// Card variant (standalone surface)
|
|
956
1086
|
<ListItem
|
|
957
1087
|
variant="card"
|
|
958
|
-
|
|
1088
|
+
leftIcon="credit-card"
|
|
959
1089
|
title="Balance"
|
|
960
1090
|
subtitle="Available funds"
|
|
961
1091
|
rightRender="$12.500"
|
|
@@ -1117,3 +1247,113 @@ const [period, setPeriod] = useState({ month: new Date().getMonth() + 1, year: n
|
|
|
1117
1247
|
<MonthPicker value={period} onChange={setPeriod} />
|
|
1118
1248
|
// Displays: "April 2026"
|
|
1119
1249
|
```
|
|
1250
|
+
|
|
1251
|
+
---
|
|
1252
|
+
|
|
1253
|
+
## Icon System
|
|
1254
|
+
|
|
1255
|
+
The library ships a built-in icon resolver so you can pass a plain icon name string to any component — no manual imports, no size guessing, no color math.
|
|
1256
|
+
|
|
1257
|
+
### Supported families
|
|
1258
|
+
|
|
1259
|
+
Icons are resolved by checking each family's glyph map in priority order (first match wins):
|
|
1260
|
+
|
|
1261
|
+
| Priority | Family | Best for |
|
|
1262
|
+
|---|---|---|
|
|
1263
|
+
| 1 (highest) | `Feather` | Clean line icons, UI essentials |
|
|
1264
|
+
| 2 | `AntDesign` | Semantic UI icons |
|
|
1265
|
+
| 3 | `Entypo` | Social, media, navigation icons |
|
|
1266
|
+
| 4 | `FontAwesome5` | Wide coverage of named icons |
|
|
1267
|
+
| 5 | `MaterialIcons` | Material-style icons |
|
|
1268
|
+
| 6 (lowest) | `Ionicons` | Fallback |
|
|
1269
|
+
|
|
1270
|
+
Browse all available icons: **https://icons.expo.fyi**
|
|
1271
|
+
|
|
1272
|
+
### Standalone `Icon` component
|
|
1273
|
+
|
|
1274
|
+
```tsx
|
|
1275
|
+
import { Icon } from '@retray-dev/ui-kit'
|
|
1276
|
+
|
|
1277
|
+
<Icon name="home" size={24} color="#000" />
|
|
1278
|
+
<Icon name="star" size={20} color={colors.primary} />
|
|
1279
|
+
|
|
1280
|
+
// Force a specific family when the same name exists in multiple families:
|
|
1281
|
+
<Icon name="heart" size={24} color="red" family="FontAwesome5" />
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
**Props:**
|
|
1285
|
+
|
|
1286
|
+
| Prop | Type | Required | Description |
|
|
1287
|
+
|---|---|---|---|
|
|
1288
|
+
| `name` | `string` | Yes | Icon name (e.g. `"home"`, `"star"`, `"arrow-right"`) |
|
|
1289
|
+
| `size` | `number` | Yes | Icon size in points |
|
|
1290
|
+
| `color` | `string` | Yes | Icon color |
|
|
1291
|
+
| `family` | `IconFamily` | No | Override resolved family |
|
|
1292
|
+
|
|
1293
|
+
Returns `null` (no crash) if the icon name is not found in any family.
|
|
1294
|
+
|
|
1295
|
+
### `renderIcon` helper
|
|
1296
|
+
|
|
1297
|
+
```tsx
|
|
1298
|
+
import { renderIcon } from '@retray-dev/ui-kit'
|
|
1299
|
+
|
|
1300
|
+
const node = renderIcon('check', 18, colors.primary)
|
|
1301
|
+
```
|
|
1302
|
+
|
|
1303
|
+
### `iconName` props on components
|
|
1304
|
+
|
|
1305
|
+
Each component that accepts icon slots now has a corresponding `iconName` prop. Pass the icon name as a string and the library resolves size and color automatically.
|
|
1306
|
+
|
|
1307
|
+
| Component | Prop(s) | Slot | Default size | Default color |
|
|
1308
|
+
|---|---|---|---|---|
|
|
1309
|
+
| `Button` | `iconName`, `iconColor` | Left or right of label | sm=16 / md=18 / lg=20 | Variant label color |
|
|
1310
|
+
| `Input` | `prefixIcon`, `prefixIconColor` | Before input text | 20 | `mutedForeground` |
|
|
1311
|
+
| `Input` | `suffixIcon`, `suffixIconColor` | After input text | 20 | `mutedForeground` |
|
|
1312
|
+
| `ListItem` | `leftIcon`, `leftIconColor` | Left 44×44 slot | 24 | `foreground` |
|
|
1313
|
+
| `ListItem` | `rightIcon`, `rightIconColor` | Right slot | 24 | `mutedForeground` |
|
|
1314
|
+
| `Badge` | `iconName`, `iconColor` | Before label | sm=10 / md=12 / lg=14 | Variant foreground |
|
|
1315
|
+
| `Toggle` | `iconName`, `iconColor` | When not pressed | sm=16 / md=18 / lg=20 | `mutedForeground` |
|
|
1316
|
+
| `Toggle` | `activeIconName`, `activeIconColor` | When pressed | sm=16 / md=18 / lg=20 | `primary` |
|
|
1317
|
+
| `AlertBanner` | `iconName`, `iconColor` | Left of content | 18 | Variant title color |
|
|
1318
|
+
| `EmptyState` | `iconName`, `iconColor` | Center icon slot | default=48 / compact=32 | `mutedForeground` |
|
|
1319
|
+
| `Toast` | `iconName`, `iconColor` | Left of message | 22 | Variant text color |
|
|
1320
|
+
|
|
1321
|
+
**Precedence:** `iconName` takes precedence over the corresponding ReactNode prop (`icon`, `prefix`, `suffix`, etc.) when both are supplied.
|
|
1322
|
+
|
|
1323
|
+
**Backward compatibility:** All existing `icon`, `prefix`, `suffix`, `leftRender`, `rightRender` ReactNode props continue to work exactly as before.
|
|
1324
|
+
|
|
1325
|
+
**Example — Button with icon:**
|
|
1326
|
+
```tsx
|
|
1327
|
+
<Button label="Continue" iconName="arrow-right" iconPosition="right" />
|
|
1328
|
+
<Button label="Delete" variant="destructive" iconName="trash-2" />
|
|
1329
|
+
```
|
|
1330
|
+
|
|
1331
|
+
**Example — Input with icons:**
|
|
1332
|
+
```tsx
|
|
1333
|
+
<Input placeholder="Search..." prefixIcon="search" />
|
|
1334
|
+
<Input placeholder="Amount" prefixIcon="dollar-sign" suffixIcon="check" />
|
|
1335
|
+
```
|
|
1336
|
+
|
|
1337
|
+
**Example — ListItem with icons:**
|
|
1338
|
+
```tsx
|
|
1339
|
+
<ListItem title="Profile" leftIcon="user" rightIcon="chevron-right" />
|
|
1340
|
+
<ListItem title="Notifications" leftIcon="bell" subtitle="3 unread" showChevron />
|
|
1341
|
+
```
|
|
1342
|
+
|
|
1343
|
+
**Example — Badge with icon:**
|
|
1344
|
+
```tsx
|
|
1345
|
+
<Badge label="Active" variant="default" iconName="check" size="sm" />
|
|
1346
|
+
<Badge label="Error" variant="destructive" iconName="alert-circle" />
|
|
1347
|
+
```
|
|
1348
|
+
|
|
1349
|
+
**Example — Toast with icon:**
|
|
1350
|
+
```tsx
|
|
1351
|
+
const { toast } = useToast()
|
|
1352
|
+
toast({ title: "Saved", variant: "success", iconName: "check-circle" })
|
|
1353
|
+
toast({ title: "Oops", variant: "destructive", iconName: "x-circle" })
|
|
1354
|
+
```
|
|
1355
|
+
|
|
1356
|
+
**Example — EmptyState with icon:**
|
|
1357
|
+
```tsx
|
|
1358
|
+
<EmptyState iconName="inbox" title="No messages" description="You're all caught up." />
|
|
1359
|
+
```
|
package/README.md
CHANGED
|
@@ -95,6 +95,24 @@ const { colors, colorScheme } = useTheme()
|
|
|
95
95
|
|
|
96
96
|
**Available tokens:** `background`, `foreground`, `card`, `cardForeground`, `primary`, `primaryForeground`, `secondary`, `secondaryForeground`, `muted`, `mutedForeground`, `accent`, `accentForeground`, `destructive`, `destructiveForeground`, `border`, `input`, `ring`, `success`, `successForeground`
|
|
97
97
|
|
|
98
|
+
## Design Tokens
|
|
99
|
+
|
|
100
|
+
Static structural constants — no provider required:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { SPACING, ICON_SIZES, RADIUS, SHADOWS, BREAKPOINTS } from '@retray-dev/ui-kit'
|
|
104
|
+
|
|
105
|
+
<View style={{ gap: SPACING.md, padding: SPACING.lg, borderRadius: RADIUS.lg, ...SHADOWS.sm }} />
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
| Token | Keys |
|
|
109
|
+
|-------|------|
|
|
110
|
+
| `SPACING` | `xs` (4), `sm` (8), `md` (12), `lg` (16), `xl` (24), `2xl` (32), `3xl` (48) |
|
|
111
|
+
| `ICON_SIZES` | `sm` (14), `md` (18), `lg` (22), `xl` (28), `2xl` (32) |
|
|
112
|
+
| `RADIUS` | `sm` (4), `md` (8), `lg` (12), `xl` (16), `full` (9999) |
|
|
113
|
+
| `SHADOWS` | `sm`, `md`, `lg`, `xl` — cross-platform shadow presets |
|
|
114
|
+
| `BREAKPOINTS` | `wide` (700) |
|
|
115
|
+
|
|
98
116
|
## Components
|
|
99
117
|
|
|
100
118
|
| Category | Components |
|
package/dist/index.d.mts
CHANGED
|
@@ -75,10 +75,18 @@ interface ButtonProps extends TouchableOpacityProps {
|
|
|
75
75
|
size: ButtonSize;
|
|
76
76
|
variant: ButtonVariant;
|
|
77
77
|
}) => React.ReactNode);
|
|
78
|
+
/**
|
|
79
|
+
* Icon name from `@expo/vector-icons` (e.g. `"home"`, `"star"`, `"arrow-right"`).
|
|
80
|
+
* See https://icons.expo.fyi to browse available icons.
|
|
81
|
+
* Takes precedence over `icon` when both are supplied.
|
|
82
|
+
*/
|
|
83
|
+
iconName?: string;
|
|
84
|
+
/** Override the resolved icon color. Defaults to the label foreground color for the active variant. */
|
|
85
|
+
iconColor?: string;
|
|
78
86
|
/** Side the icon appears on. Defaults to `'left'`. */
|
|
79
87
|
iconPosition?: 'left' | 'right';
|
|
80
88
|
}
|
|
81
|
-
declare function Button({ label, variant, size, loading, fullWidth, icon, iconPosition, disabled, style, onPress, ...props }: ButtonProps): React.JSX.Element;
|
|
89
|
+
declare function Button({ label, variant, size, loading, fullWidth, icon, iconName, iconColor, iconPosition, disabled, style, onPress, ...props }: ButtonProps): React.JSX.Element;
|
|
82
90
|
|
|
83
91
|
type TextVariant = 'h1' | 'h2' | 'h3' | 'body' | 'caption' | 'label';
|
|
84
92
|
interface TextProps extends TextProps$1 {
|
|
@@ -101,12 +109,26 @@ interface InputProps extends TextInputProps {
|
|
|
101
109
|
prefixStyle?: TextStyle;
|
|
102
110
|
/** Style applied to suffix text if suffix is a string. */
|
|
103
111
|
suffixStyle?: TextStyle;
|
|
112
|
+
/**
|
|
113
|
+
* Icon name from `@expo/vector-icons` rendered before the input text.
|
|
114
|
+
* See https://icons.expo.fyi. Takes precedence over `prefix`.
|
|
115
|
+
*/
|
|
116
|
+
prefixIcon?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Icon name from `@expo/vector-icons` rendered after the input text.
|
|
119
|
+
* See https://icons.expo.fyi. Takes precedence over `suffix` (unless `type="password"`).
|
|
120
|
+
*/
|
|
121
|
+
suffixIcon?: string;
|
|
122
|
+
/** Override the resolved prefix icon color. Defaults to `mutedForeground`. */
|
|
123
|
+
prefixIconColor?: string;
|
|
124
|
+
/** Override the resolved suffix icon color. Defaults to `mutedForeground`. */
|
|
125
|
+
suffixIconColor?: string;
|
|
104
126
|
/** Input type. When set to \`'password'\`, shows a toggle button to reveal/hide text. */
|
|
105
127
|
type?: 'text' | 'password';
|
|
106
128
|
/** Style for the outer container \`View\`. Use \`style\` (from \`TextInputProps\`) to style the \`TextInput\` itself. */
|
|
107
129
|
containerStyle?: ViewStyle;
|
|
108
130
|
}
|
|
109
|
-
declare function Input({ label, error, hint, prefix, suffix, prefixStyle, suffixStyle, type, containerStyle, style, onFocus, onBlur, secureTextEntry, ...props }: InputProps): React.JSX.Element;
|
|
131
|
+
declare function Input({ label, error, hint, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type, containerStyle, style, onFocus, onBlur, secureTextEntry, ...props }: InputProps): React.JSX.Element;
|
|
110
132
|
|
|
111
133
|
type BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline';
|
|
112
134
|
type BadgeSize = 'sm' | 'md' | 'lg';
|
|
@@ -118,9 +140,16 @@ interface BadgeProps {
|
|
|
118
140
|
size?: BadgeSize;
|
|
119
141
|
/** Icon rendered before the label/children. */
|
|
120
142
|
icon?: React.ReactNode;
|
|
143
|
+
/**
|
|
144
|
+
* Icon name from `@expo/vector-icons` rendered before the label.
|
|
145
|
+
* See https://icons.expo.fyi. Takes precedence over `icon`.
|
|
146
|
+
*/
|
|
147
|
+
iconName?: string;
|
|
148
|
+
/** Override the resolved icon color. Defaults to the variant foreground color. */
|
|
149
|
+
iconColor?: string;
|
|
121
150
|
style?: ViewStyle;
|
|
122
151
|
}
|
|
123
|
-
declare function Badge({ label, children, variant, size, icon, style }: BadgeProps): React.JSX.Element;
|
|
152
|
+
declare function Badge({ label, children, variant, size, icon, iconName, iconColor, style }: BadgeProps): React.JSX.Element;
|
|
124
153
|
|
|
125
154
|
type CardVariant = 'elevated' | 'outlined' | 'filled';
|
|
126
155
|
interface CardProps {
|
|
@@ -196,9 +225,16 @@ interface AlertBannerProps {
|
|
|
196
225
|
description?: string;
|
|
197
226
|
variant?: AlertBannerVariant;
|
|
198
227
|
icon?: React.ReactNode;
|
|
228
|
+
/**
|
|
229
|
+
* Icon name from `@expo/vector-icons`. See https://icons.expo.fyi.
|
|
230
|
+
* Takes precedence over `icon`. When neither is set, a default variant icon is shown.
|
|
231
|
+
*/
|
|
232
|
+
iconName?: string;
|
|
233
|
+
/** Override the resolved icon color. Defaults to the variant title color. */
|
|
234
|
+
iconColor?: string;
|
|
199
235
|
style?: ViewStyle;
|
|
200
236
|
}
|
|
201
|
-
declare function AlertBanner({ title, description, variant, icon, style }: AlertBannerProps): React.JSX.Element;
|
|
237
|
+
declare function AlertBanner({ title, description, variant, icon, iconName, iconColor, style }: AlertBannerProps): React.JSX.Element;
|
|
202
238
|
|
|
203
239
|
interface ProgressProps {
|
|
204
240
|
/** Current progress value. Clamped to `[0, max]`. Defaults to `0`. */
|
|
@@ -211,6 +247,13 @@ declare function Progress({ value, max, style }: ProgressProps): React.JSX.Eleme
|
|
|
211
247
|
|
|
212
248
|
interface EmptyStateProps {
|
|
213
249
|
icon?: React.ReactNode;
|
|
250
|
+
/**
|
|
251
|
+
* Icon name from `@expo/vector-icons`. See https://icons.expo.fyi.
|
|
252
|
+
* Takes precedence over `icon`. Sized automatically to fit the slot (48 default, 32 compact).
|
|
253
|
+
*/
|
|
254
|
+
iconName?: string;
|
|
255
|
+
/** Override the resolved icon color. Defaults to `mutedForeground`. */
|
|
256
|
+
iconColor?: string;
|
|
214
257
|
title: string;
|
|
215
258
|
description?: string;
|
|
216
259
|
action?: React.ReactNode;
|
|
@@ -218,7 +261,7 @@ interface EmptyStateProps {
|
|
|
218
261
|
size?: 'default' | 'compact';
|
|
219
262
|
style?: ViewStyle;
|
|
220
263
|
}
|
|
221
|
-
declare function EmptyState({ icon, title, description, action, size, style }: EmptyStateProps): React.JSX.Element;
|
|
264
|
+
declare function EmptyState({ icon, iconName, iconColor, title, description, action, size, style }: EmptyStateProps): React.JSX.Element;
|
|
222
265
|
|
|
223
266
|
interface TextareaProps extends TextInputProps {
|
|
224
267
|
label?: string;
|
|
@@ -262,8 +305,22 @@ interface ToggleProps extends TouchableOpacityProps {
|
|
|
262
305
|
icon?: React.ReactNode | ((pressed: boolean) => React.ReactNode);
|
|
263
306
|
/** Icon to show when pressed/active. If omitted, a default check mark is used. */
|
|
264
307
|
activeIcon?: React.ReactNode | ((pressed: boolean) => React.ReactNode);
|
|
308
|
+
/**
|
|
309
|
+
* Icon name from `@expo/vector-icons` shown when not pressed.
|
|
310
|
+
* See https://icons.expo.fyi. Takes precedence over `icon`.
|
|
311
|
+
*/
|
|
312
|
+
iconName?: string;
|
|
313
|
+
/**
|
|
314
|
+
* Icon name from `@expo/vector-icons` shown when pressed/active.
|
|
315
|
+
* See https://icons.expo.fyi. Takes precedence over `activeIcon`.
|
|
316
|
+
*/
|
|
317
|
+
activeIconName?: string;
|
|
318
|
+
/** Override the resolved inactive icon color. Defaults to `mutedForeground`. */
|
|
319
|
+
iconColor?: string;
|
|
320
|
+
/** Override the resolved active icon color. Defaults to `primary`. */
|
|
321
|
+
activeIconColor?: string;
|
|
265
322
|
}
|
|
266
|
-
declare function Toggle({ pressed, onPressedChange, variant, size, label, icon, activeIcon, disabled, style, ...props }: ToggleProps): React.JSX.Element;
|
|
323
|
+
declare function Toggle({ pressed, onPressedChange, variant, size, label, icon, activeIcon, iconName, activeIconName, iconColor, activeIconColor, disabled, style, ...props }: ToggleProps): React.JSX.Element;
|
|
267
324
|
|
|
268
325
|
interface RadioOption {
|
|
269
326
|
label: string;
|
|
@@ -378,6 +435,13 @@ interface ToastItem {
|
|
|
378
435
|
description?: string;
|
|
379
436
|
variant?: ToastVariant;
|
|
380
437
|
icon?: React.ReactNode;
|
|
438
|
+
/**
|
|
439
|
+
* Icon name from `@expo/vector-icons`. See https://icons.expo.fyi.
|
|
440
|
+
* Takes precedence over `icon`. When neither is set, a default variant icon is shown.
|
|
441
|
+
*/
|
|
442
|
+
iconName?: string;
|
|
443
|
+
/** Override the resolved icon color. Defaults to the variant text color. */
|
|
444
|
+
iconColor?: string;
|
|
381
445
|
/** Auto-dismiss delay in milliseconds. Defaults to `3000`. */
|
|
382
446
|
duration?: number;
|
|
383
447
|
}
|
|
@@ -446,6 +510,20 @@ interface ListItemProps {
|
|
|
446
510
|
trailing?: React.ReactNode | string;
|
|
447
511
|
/** @deprecated Use `leftRender` instead. */
|
|
448
512
|
icon?: React.ReactNode;
|
|
513
|
+
/**
|
|
514
|
+
* Icon name from `@expo/vector-icons` rendered in the left slot.
|
|
515
|
+
* See https://icons.expo.fyi. Takes precedence over `leftRender`.
|
|
516
|
+
*/
|
|
517
|
+
leftIcon?: string;
|
|
518
|
+
/**
|
|
519
|
+
* Icon name from `@expo/vector-icons` rendered in the right slot.
|
|
520
|
+
* See https://icons.expo.fyi. Takes precedence over `rightRender`.
|
|
521
|
+
*/
|
|
522
|
+
rightIcon?: string;
|
|
523
|
+
/** Override the resolved left icon color. Defaults to `foreground`. */
|
|
524
|
+
leftIconColor?: string;
|
|
525
|
+
/** Override the resolved right icon color. Defaults to `mutedForeground`. */
|
|
526
|
+
rightIconColor?: string;
|
|
449
527
|
title: string;
|
|
450
528
|
/** Secondary line below the title. */
|
|
451
529
|
subtitle?: string;
|
|
@@ -471,7 +549,7 @@ interface ListItemProps {
|
|
|
471
549
|
/** Style applied to the caption Text. */
|
|
472
550
|
captionStyle?: TextStyle;
|
|
473
551
|
}
|
|
474
|
-
declare function ListItem({ leftRender, rightRender, trailing, icon, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, captionStyle, }: ListItemProps): React.JSX.Element;
|
|
552
|
+
declare function ListItem({ leftRender, rightRender, trailing, icon, leftIcon, rightIcon, leftIconColor, rightIconColor, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, captionStyle, }: ListItemProps): React.JSX.Element;
|
|
475
553
|
|
|
476
554
|
interface ChipProps {
|
|
477
555
|
label: string;
|
|
@@ -525,4 +603,91 @@ interface MonthPickerProps {
|
|
|
525
603
|
}
|
|
526
604
|
declare function MonthPicker({ value, onChange, style }: MonthPickerProps): React.JSX.Element;
|
|
527
605
|
|
|
528
|
-
|
|
606
|
+
type IconFamily = 'Feather' | 'AntDesign' | 'Entypo' | 'FontAwesome5' | 'MaterialIcons' | 'Ionicons';
|
|
607
|
+
interface IconProps {
|
|
608
|
+
/** Icon name from any supported @expo/vector-icons family. See https://icons.expo.fyi */
|
|
609
|
+
name: string;
|
|
610
|
+
size: number;
|
|
611
|
+
color: string;
|
|
612
|
+
/** Override the resolved family when the same name exists in multiple families. */
|
|
613
|
+
family?: IconFamily;
|
|
614
|
+
}
|
|
615
|
+
declare function Icon({ name, size, color, family }: IconProps): React.ReactElement | null;
|
|
616
|
+
declare function renderIcon(name: string, size: number, color: string): React.ReactElement | null;
|
|
617
|
+
|
|
618
|
+
declare const SPACING: {
|
|
619
|
+
readonly xs: 4;
|
|
620
|
+
readonly sm: 8;
|
|
621
|
+
readonly md: 12;
|
|
622
|
+
readonly lg: 16;
|
|
623
|
+
readonly xl: 24;
|
|
624
|
+
readonly '2xl': 32;
|
|
625
|
+
readonly '3xl': 48;
|
|
626
|
+
};
|
|
627
|
+
declare const ICON_SIZES: {
|
|
628
|
+
readonly sm: 14;
|
|
629
|
+
readonly md: 18;
|
|
630
|
+
readonly lg: 22;
|
|
631
|
+
readonly xl: 28;
|
|
632
|
+
readonly '2xl': 32;
|
|
633
|
+
};
|
|
634
|
+
declare const RADIUS: {
|
|
635
|
+
readonly sm: 4;
|
|
636
|
+
readonly md: 8;
|
|
637
|
+
readonly lg: 12;
|
|
638
|
+
readonly xl: 16;
|
|
639
|
+
readonly full: 9999;
|
|
640
|
+
};
|
|
641
|
+
declare const SHADOWS: {
|
|
642
|
+
readonly sm: {
|
|
643
|
+
readonly shadowColor: "#000";
|
|
644
|
+
readonly shadowOffset: {
|
|
645
|
+
readonly width: 0;
|
|
646
|
+
readonly height: 1;
|
|
647
|
+
};
|
|
648
|
+
readonly shadowOpacity: 0.08;
|
|
649
|
+
readonly shadowRadius: 4;
|
|
650
|
+
readonly elevation: 2;
|
|
651
|
+
};
|
|
652
|
+
readonly md: {
|
|
653
|
+
readonly shadowColor: "#000";
|
|
654
|
+
readonly shadowOffset: {
|
|
655
|
+
readonly width: 0;
|
|
656
|
+
readonly height: 3;
|
|
657
|
+
};
|
|
658
|
+
readonly shadowOpacity: 0.12;
|
|
659
|
+
readonly shadowRadius: 8;
|
|
660
|
+
readonly elevation: 5;
|
|
661
|
+
};
|
|
662
|
+
readonly lg: {
|
|
663
|
+
readonly shadowColor: "#000";
|
|
664
|
+
readonly shadowOffset: {
|
|
665
|
+
readonly width: 0;
|
|
666
|
+
readonly height: 6;
|
|
667
|
+
};
|
|
668
|
+
readonly shadowOpacity: 0.2;
|
|
669
|
+
readonly shadowRadius: 16;
|
|
670
|
+
readonly elevation: 10;
|
|
671
|
+
};
|
|
672
|
+
readonly xl: {
|
|
673
|
+
readonly shadowColor: "#000";
|
|
674
|
+
readonly shadowOffset: {
|
|
675
|
+
readonly width: 0;
|
|
676
|
+
readonly height: 12;
|
|
677
|
+
};
|
|
678
|
+
readonly shadowOpacity: 0.28;
|
|
679
|
+
readonly shadowRadius: 24;
|
|
680
|
+
readonly elevation: 18;
|
|
681
|
+
};
|
|
682
|
+
};
|
|
683
|
+
declare const BREAKPOINTS: {
|
|
684
|
+
readonly wide: 700;
|
|
685
|
+
};
|
|
686
|
+
type Spacing = typeof SPACING;
|
|
687
|
+
type SpacingKey = keyof Spacing;
|
|
688
|
+
type IconSize = typeof ICON_SIZES;
|
|
689
|
+
type IconSizeKey = keyof IconSize;
|
|
690
|
+
type Radius = typeof RADIUS;
|
|
691
|
+
type RadiusKey = keyof Radius;
|
|
692
|
+
|
|
693
|
+
export { Accordion, type AccordionItem, type AccordionProps, AlertBanner, type AlertBannerProps, type AlertBannerVariant, Avatar, type AvatarProps, type AvatarSize, BREAKPOINTS, Badge, type BadgeProps, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, CardContent, type CardContentProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, Checkbox, type CheckboxProps, Chip, ChipGroup, type ChipGroupProps, type ChipOption, type ChipProps, type ColorScheme, ConfirmDialog, type ConfirmDialogProps, CurrencyDisplay, type CurrencyDisplayProps, CurrencyInput, CurrencyInput as CurrencyInputLarge, type CurrencyInputProps, EmptyState, type EmptyStateProps, ICON_SIZES, Icon, type IconFamily, type IconProps, type IconSize, type IconSizeKey, Input, type InputProps, LabelValue, type LabelValueProps, ListItem, type ListItemProps, MonthPicker, type MonthPickerProps, type MonthPickerValue, Progress, type ProgressProps, RADIUS, RadioGroup, type RadioGroupProps, type RadioOption, type Radius, type RadiusKey, SHADOWS, SPACING, Select, type SelectOption, type SelectProps, Separator, type SeparatorProps, Sheet, type SheetProps, Skeleton, type SkeletonProps, Slider, type SliderProps, type Spacing, type SpacingKey, Spinner, type SpinnerProps, type SpinnerSize, Switch, type SwitchProps, type TabItem, Tabs, TabsContent, type TabsContentProps, type TabsProps, Text, type TextProps, type TextVariant, Textarea, type TextareaProps, type Theme, type ThemeColors, ThemeProvider, type ThemeProviderProps, type ToastItem, ToastProvider, type ToastProviderProps, type ToastVariant, Toggle, type ToggleProps, type ToggleSize, type ToggleVariant, defaultDark, defaultLight, renderIcon, useTheme, useToast };
|