@retray-dev/ui-kit 2.3.0 → 2.5.1

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 CHANGED
@@ -1,4 +1,4 @@
1
- # @retray-dev/ui-kit — Component Reference (v2.1.0)
1
+ # @retray-dev/ui-kit — Component Reference (v2.5.1)
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
 
@@ -121,12 +121,12 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
121
121
  | color | `string` | — | Override the color. Defaults to `foreground`, except `caption` which uses `mutedForeground` |
122
122
 
123
123
  **Sizes:**
124
- - `h1`: 32px / 700 weight
125
- - `h2`: 24px / 700 weight
126
- - `h3`: 20px / 600 weight
127
- - `body`: 16px / 400 weight
128
- - `label`: 14px / 500 weight
129
- - `caption`: 12px / 400 weight / `mutedForeground` color by default
124
+ - `h1`: 40px / 700 weight / lineHeight 52
125
+ - `h2`: 28px / 700 weight / lineHeight 36
126
+ - `h3`: 22px / 600 weight / lineHeight 30
127
+ - `body`: 17px / 400 weight / lineHeight 26
128
+ - `label`: 15px / 500 weight / lineHeight 22
129
+ - `caption`: 13px / 400 weight / lineHeight 20 / `mutedForeground` color by default
130
130
 
131
131
  **Example:**
132
132
  ```tsx
@@ -152,7 +152,7 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
152
152
  | loading | `boolean` | `false` | Replaces label with a spinner and forces disabled state |
153
153
  | fullWidth | `boolean` | `false` | Stretches to container width (`alignSelf: 'stretch'`) |
154
154
  | disabled | `boolean` | — | Reduces opacity to 0.5 |
155
- | icon | `React.ReactNode` | — | Icon rendered alongside the label |
155
+ | icon | `React.ReactNode \| ((props: { label, size, variant }) => React.ReactNode)` | — | Icon rendered alongside the label. Can be a node or a render function |
156
156
  | iconPosition | `'left' \| 'right'` | `'left'` | Side the icon appears on |
157
157
 
158
158
  **Variants:**
@@ -162,7 +162,7 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
162
162
  - `ghost`: fully transparent — in-context or low-emphasis actions
163
163
  - `destructive`: filled with `destructive` token — irreversible or dangerous actions
164
164
 
165
- **Animations:** Scale springs to 0.97 on `onPressIn`, back to 1.0 on `onPressOut`.
165
+ **Animations:** Scale springs to 0.95 on `onPressIn`, back to 1.0 on `onPressOut`.
166
166
 
167
167
  **Example:**
168
168
  ```tsx
@@ -188,7 +188,10 @@ import type { ThemeColors } from '@retray-dev/ui-kit'
188
188
  | hint | `string` | — | Helper text below (hidden when `error` is set) |
189
189
  | prefix | `string \| ReactNode` | — | Content rendered before the input field (e.g., `"$"` or an icon) |
190
190
  | suffix | `string \| ReactNode` | — | Content rendered after the input field (e.g., `"kg"` or a button) |
191
+ | prefixStyle | `TextStyle` | — | Style applied to the prefix text when prefix is a string |
192
+ | suffixStyle | `TextStyle` | — | Style applied to the suffix text when suffix is a string |
191
193
  | type | `'text' \| 'password'` | `'text'` | When `'password'`, shows a visibility toggle button in the suffix slot |
194
+ | containerStyle | `ViewStyle` | — | Style for the outer container `View` |
192
195
 
193
196
  **Border colors:** `destructive` when `error` is set, `ring` when focused, `border` otherwise.
194
197
 
@@ -260,7 +263,8 @@ const [amount, setAmount] = useState(0)
260
263
  | label | `string` | — | Label above |
261
264
  | error | `string` | — | Error text below; red border |
262
265
  | hint | `string` | — | Helper text below |
263
- | rows | `number` | `4` | Sets `minHeight` (each row ≈ 28px) |
266
+ | rows | `number` | `4` | Sets `minHeight` (each row ≈ 30px) and `numberOfLines` |
267
+ | containerStyle | `ViewStyle` | — | Style for the outer container `View` |
264
268
 
265
269
  **Example:**
266
270
  ```tsx
@@ -505,8 +509,8 @@ All sub-components (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`,
505
509
  **Notes:**
506
510
  - `CardHeader` and `CardContent` have `padding: 24`. Override via the `style` prop: `<CardContent style={{ padding: 16 }}>`
507
511
  - `CardFooter` has `paddingTop: 0` so it connects naturally to `CardContent`
508
- - `CardTitle`: 18px / 600 weight, `cardForeground` color
509
- - `CardDescription`: 14px, `mutedForeground` color
512
+ - `CardTitle`: 20px / 600 weight / lineHeight 28, `cardForeground` color
513
+ - `CardDescription`: 15px / lineHeight 22, `mutedForeground` color
510
514
  - Press animation scales to 0.98 via `Animated.spring` when `onPress` is provided
511
515
 
512
516
  ---
@@ -890,6 +894,7 @@ function MyComponent() {
890
894
  **Notes:**
891
895
  - Max 3 toasts shown simultaneously (oldest is removed when a 4th arrives)
892
896
  - Toasts appear at the top of the screen, below the status bar (dynamic safe area inset)
897
+ - **On web:** constrained to 400px wide and centered (`alignSelf: 'center'`) — not full-width
893
898
  - Entrance: `withTiming(120ms, Easing.out(Easing.exp))` slide-down + opacity fade — fast, sharp feel
894
899
  - Exit: `withTiming(200ms)` slide-up + opacity fade
895
900
  - Swipe left or right to dismiss early (threshold: 80px or 800 pt/s velocity)
@@ -899,32 +904,81 @@ function MyComponent() {
899
904
  ### ListItem
900
905
 
901
906
  **Import:** `import { ListItem } from '@retray-dev/ui-kit'`
902
- **When to use:** Rows in a list or menu. Composes icon, title, subtitle, and trailing content in a standard horizontal layout.
907
+ **When to use:** Rows in a list, feed, or menu. Composes a left slot (avatar, icon, image), title/subtitle/caption text block, and a right slot (price, badge, chevron, switch, etc.) in a standard horizontal layout. Supports both plain and card visual variants.
903
908
 
904
909
  | Prop | Type | Default | Notes |
905
910
  |------|------|---------|-------|
906
- | title | `string` | required | Primary label |
907
- | subtitle | `string` | — | Secondary label below the title |
908
- | icon | `ReactNode` | — | Node rendered to the left of the text content |
909
- | trailing | `string \| ReactNode` | — | Content on the right edge. Strings are styled as muted caption |
910
- | onPress | `() => void` | — | Makes the row pressable. Scale animation + haptics are only active when provided |
911
+ | title | `string` | required | Primary text (17px / 500 weight) |
912
+ | subtitle | `string` | — | Secondary line below the title (14px / 400 weight) |
913
+ | caption | `string` | — | Tertiary / caption line below the subtitle (12px / 400 weight, 70% opacity) |
914
+ | leftRender | `ReactNode` | — | Arbitrary content in a fixed 44×44pt left slot (avatar, icon, image, etc.) |
915
+ | rightRender | `string \| ReactNode` | — | Content on the right edge. Strings are styled as muted text (15px); pass ReactNode for Badges, prices, switches, etc. |
916
+ | variant | `'plain' \| 'card'` | `'plain'` | `plain`: no background, sits inside a parent surface. `card`: standalone surface with background, border, and shadow |
917
+ | showChevron | `boolean` | `false` | Shows a `›` chevron on the far right. Ignored when `rightRender` is set |
918
+ | showSeparator | `boolean` | `false` | Renders a hairline separator at the bottom. Useful when stacking multiple plain items in a list |
919
+ | onPress | `() => void` | — | Makes the row pressable (scale spring + haptics). No animation or haptics when omitted |
911
920
  | disabled | `boolean` | — | Reduces opacity to 0.45 |
912
- | style | `ViewStyle` | — | |
921
+ | style | `ViewStyle` | — | Style applied to the outer container |
922
+ | titleStyle | `TextStyle` | — | Style override for the title text |
923
+ | subtitleStyle | `TextStyle` | — | Style override for the subtitle text |
924
+ | captionStyle | `TextStyle` | — | Style override for the caption text |
925
+ | icon | `ReactNode` | — | **Deprecated** — use `leftRender` |
926
+ | trailing | `string \| ReactNode` | — | **Deprecated** — use `rightRender` |
927
+
928
+ **Animation:** Scale springs to 0.97 on press-in, back to 1.0 on press-out (only when `onPress` is provided).
913
929
 
914
930
  **Example:**
915
931
  ```tsx
932
+ // Simple row with chevron
933
+ <ListItem
934
+ title="Profile"
935
+ subtitle="Manage your account"
936
+ showChevron
937
+ onPress={() => navigate('profile')}
938
+ />
939
+
940
+ // Rich row: avatar + title/subtitle/caption + price + badge
916
941
  <ListItem
917
- icon={<Ionicons name="receipt-outline" size={18} />}
918
- title="Mercado"
919
- subtitle="12 mar 2025"
920
- trailing="$45.000"
921
- onPress={() => navigate('detail')}
942
+ leftRender={<Avatar src={item.avatar} fallback={item.initials} size="md" />}
943
+ title={item.name}
944
+ subtitle={item.date}
945
+ caption={item.category}
946
+ rightRender={
947
+ <View style={{ alignItems: 'flex-end', gap: 4 }}>
948
+ <Text variant="label">${item.amount}</Text>
949
+ <Badge label={item.status} variant="secondary" size="sm" />
950
+ </View>
951
+ }
952
+ onPress={() => navigate('detail', { id: item.id })}
922
953
  />
923
954
 
924
- // Non-interactive row
925
- <ListItem title="Account number" trailing="**** 4321" />
955
+ // Card variant (standalone surface)
956
+ <ListItem
957
+ variant="card"
958
+ leftRender={<Ionicons name="wallet-outline" size={20} />}
959
+ title="Balance"
960
+ subtitle="Available funds"
961
+ rightRender="$12.500"
962
+ />
963
+
964
+ // List with separators
965
+ {transactions.map((t, i) => (
966
+ <ListItem
967
+ key={t.id}
968
+ title={t.name}
969
+ subtitle={t.date}
970
+ rightRender={t.amount}
971
+ showSeparator={i < transactions.length - 1}
972
+ onPress={() => navigate('detail', { id: t.id })}
973
+ />
974
+ ))}
926
975
  ```
927
976
 
977
+ **Notes:**
978
+ - `leftRender` renders inside a fixed 44×44pt container (centered) — no need to wrap in a sized View
979
+ - `rightRender` container has `maxWidth: 160` and aligns content to the right edge
980
+ - The separator inset aligns to the text block: `marginLeft: 16 + 44 + 12` when `leftRender` is set, `marginLeft: 16` otherwise
981
+
928
982
  ---
929
983
 
930
984
  ### Chip / ChipGroup
package/README.md CHANGED
@@ -23,7 +23,7 @@ pnpm add @retray-dev/ui-kit
23
23
  Install these in your app if not already present:
24
24
 
25
25
  ```bash
26
- pnpm add expo-haptics react-native-safe-area-context @gorhom/bottom-sheet react-native-reanimated react-native-gesture-handler react-native-worklets
26
+ pnpm add expo-haptics expo-linear-gradient react-native-safe-area-context @gorhom/bottom-sheet react-native-reanimated react-native-gesture-handler react-native-worklets @react-native-picker/picker @react-native-community/slider @expo/vector-icons
27
27
  ```
28
28
 
29
29
  For Expo projects, run `npx expo install` instead to get SDK-compatible versions.
@@ -100,7 +100,7 @@ const { colors, colorScheme } = useTheme()
100
100
  | Category | Components |
101
101
  | ----------- | ----------------------------------------------------------------------------------------------- |
102
102
  | Display | `Text`, `Badge`, `Avatar`, `Separator`, `Spinner`, `Skeleton`, `Progress`, `CurrencyDisplay` |
103
- | Surfaces | `Card`, `Alert`, `EmptyState` |
103
+ | Surfaces | `Card`, `AlertBanner`, `EmptyState` |
104
104
  | Form | `Button`, `Input`, `CurrencyInput`, `CurrencyInputLarge`, `Textarea`, `Checkbox`, `Switch`, `Toggle`, `RadioGroup`, `Select`, `Slider` |
105
105
  | Composition | `Tabs`, `Accordion` |
106
106
  | Overlays | `Sheet`, `ConfirmDialog` |
@@ -116,9 +116,7 @@ import {
116
116
  } from '@retray-dev/ui-kit'
117
117
 
118
118
  // Button
119
- <Button variant="default" size="md" onPress={() => {}}>
120
- Save
121
- </Button>
119
+ <Button label="Save" variant="primary" size="md" onPress={() => {}} />
122
120
 
123
121
  // Toast
124
122
  const { toast } = useToast()
package/dist/index.d.mts CHANGED
@@ -430,16 +430,48 @@ interface CurrencyDisplayProps {
430
430
  }
431
431
  declare function CurrencyDisplay({ value, prefix, showDecimals, textColor, style }: CurrencyDisplayProps): React.JSX.Element;
432
432
 
433
+ type ListItemVariant = 'plain' | 'card';
433
434
  interface ListItemProps {
435
+ /**
436
+ * Arbitrary content rendered on the left (avatar, icon, image, etc.).
437
+ * Rendered inside a 44×44 aligned container.
438
+ */
439
+ leftRender?: React.ReactNode;
440
+ /**
441
+ * Arbitrary content rendered on the right (badge, price, chevron, switch, etc.).
442
+ * Replaces the old `trailing` prop (still accepted as an alias).
443
+ */
444
+ rightRender?: React.ReactNode | string;
445
+ /** @deprecated Use `rightRender` instead. */
446
+ trailing?: React.ReactNode | string;
447
+ /** @deprecated Use `leftRender` instead. */
434
448
  icon?: React.ReactNode;
435
449
  title: string;
450
+ /** Secondary line below the title. */
436
451
  subtitle?: string;
437
- trailing?: string | React.ReactNode;
452
+ /** Tertiary / caption line below the subtitle. */
453
+ caption?: string;
454
+ /**
455
+ * - `plain` (default): no background, no border — designed to sit inside a parent surface (Card, list wrapper, etc.)
456
+ * - `card`: standalone surface with background, border and shadow.
457
+ */
458
+ variant?: ListItemVariant;
459
+ /** Show a right-pointing chevron on the far right. Ignored when `rightRender` / `trailing` is set. */
460
+ showChevron?: boolean;
461
+ /** Visual separator line at the bottom of the item. Useful when rendering multiple plain items in a list. */
462
+ showSeparator?: boolean;
438
463
  onPress?: () => void;
439
464
  disabled?: boolean;
465
+ /** Style applied to the outer container. */
440
466
  style?: ViewStyle;
441
- }
442
- declare function ListItem({ icon, title, subtitle, trailing, onPress, disabled, style }: ListItemProps): React.JSX.Element;
467
+ /** Style applied to the title Text. */
468
+ titleStyle?: TextStyle;
469
+ /** Style applied to the subtitle Text. */
470
+ subtitleStyle?: TextStyle;
471
+ /** Style applied to the caption Text. */
472
+ captionStyle?: TextStyle;
473
+ }
474
+ declare function ListItem({ leftRender, rightRender, trailing, icon, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, captionStyle, }: ListItemProps): React.JSX.Element;
443
475
 
444
476
  interface ChipProps {
445
477
  label: string;
package/dist/index.d.ts CHANGED
@@ -430,16 +430,48 @@ interface CurrencyDisplayProps {
430
430
  }
431
431
  declare function CurrencyDisplay({ value, prefix, showDecimals, textColor, style }: CurrencyDisplayProps): React.JSX.Element;
432
432
 
433
+ type ListItemVariant = 'plain' | 'card';
433
434
  interface ListItemProps {
435
+ /**
436
+ * Arbitrary content rendered on the left (avatar, icon, image, etc.).
437
+ * Rendered inside a 44×44 aligned container.
438
+ */
439
+ leftRender?: React.ReactNode;
440
+ /**
441
+ * Arbitrary content rendered on the right (badge, price, chevron, switch, etc.).
442
+ * Replaces the old `trailing` prop (still accepted as an alias).
443
+ */
444
+ rightRender?: React.ReactNode | string;
445
+ /** @deprecated Use `rightRender` instead. */
446
+ trailing?: React.ReactNode | string;
447
+ /** @deprecated Use `leftRender` instead. */
434
448
  icon?: React.ReactNode;
435
449
  title: string;
450
+ /** Secondary line below the title. */
436
451
  subtitle?: string;
437
- trailing?: string | React.ReactNode;
452
+ /** Tertiary / caption line below the subtitle. */
453
+ caption?: string;
454
+ /**
455
+ * - `plain` (default): no background, no border — designed to sit inside a parent surface (Card, list wrapper, etc.)
456
+ * - `card`: standalone surface with background, border and shadow.
457
+ */
458
+ variant?: ListItemVariant;
459
+ /** Show a right-pointing chevron on the far right. Ignored when `rightRender` / `trailing` is set. */
460
+ showChevron?: boolean;
461
+ /** Visual separator line at the bottom of the item. Useful when rendering multiple plain items in a list. */
462
+ showSeparator?: boolean;
438
463
  onPress?: () => void;
439
464
  disabled?: boolean;
465
+ /** Style applied to the outer container. */
440
466
  style?: ViewStyle;
441
- }
442
- declare function ListItem({ icon, title, subtitle, trailing, onPress, disabled, style }: ListItemProps): React.JSX.Element;
467
+ /** Style applied to the title Text. */
468
+ titleStyle?: TextStyle;
469
+ /** Style applied to the subtitle Text. */
470
+ subtitleStyle?: TextStyle;
471
+ /** Style applied to the caption Text. */
472
+ captionStyle?: TextStyle;
473
+ }
474
+ declare function ListItem({ leftRender, rightRender, trailing, icon, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, captionStyle, }: ListItemProps): React.JSX.Element;
443
475
 
444
476
  interface ChipProps {
445
477
  label: string;