@retray-dev/ui-kit 2.3.0 → 2.5.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 CHANGED
@@ -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
@@ -890,6 +890,7 @@ function MyComponent() {
890
890
  **Notes:**
891
891
  - Max 3 toasts shown simultaneously (oldest is removed when a 4th arrives)
892
892
  - Toasts appear at the top of the screen, below the status bar (dynamic safe area inset)
893
+ - **On web:** constrained to 400px wide and centered (`alignSelf: 'center'`) — not full-width
893
894
  - Entrance: `withTiming(120ms, Easing.out(Easing.exp))` slide-down + opacity fade — fast, sharp feel
894
895
  - Exit: `withTiming(200ms)` slide-up + opacity fade
895
896
  - Swipe left or right to dismiss early (threshold: 80px or 800 pt/s velocity)
@@ -899,32 +900,81 @@ function MyComponent() {
899
900
  ### ListItem
900
901
 
901
902
  **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.
903
+ **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
904
 
904
905
  | Prop | Type | Default | Notes |
905
906
  |------|------|---------|-------|
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 |
907
+ | title | `string` | required | Primary text (17px / 500 weight) |
908
+ | subtitle | `string` | — | Secondary line below the title (14px / 400 weight) |
909
+ | caption | `string` | — | Tertiary / caption line below the subtitle (12px / 400 weight, 70% opacity) |
910
+ | leftRender | `ReactNode` | — | Arbitrary content in a fixed 44×44pt left slot (avatar, icon, image, etc.) |
911
+ | rightRender | `string \| ReactNode` | — | Content on the right edge. Strings are styled as muted text (15px); pass ReactNode for Badges, prices, switches, etc. |
912
+ | variant | `'plain' \| 'card'` | `'plain'` | `plain`: no background, sits inside a parent surface. `card`: standalone surface with background, border, and shadow |
913
+ | showChevron | `boolean` | `false` | Shows a `›` chevron on the far right. Ignored when `rightRender` is set |
914
+ | showSeparator | `boolean` | `false` | Renders a hairline separator at the bottom. Useful when stacking multiple plain items in a list |
915
+ | onPress | `() => void` | — | Makes the row pressable (scale spring + haptics). No animation or haptics when omitted |
911
916
  | disabled | `boolean` | — | Reduces opacity to 0.45 |
912
- | style | `ViewStyle` | — | |
917
+ | style | `ViewStyle` | — | Style applied to the outer container |
918
+ | titleStyle | `TextStyle` | — | Style override for the title text |
919
+ | subtitleStyle | `TextStyle` | — | Style override for the subtitle text |
920
+ | captionStyle | `TextStyle` | — | Style override for the caption text |
921
+ | icon | `ReactNode` | — | **Deprecated** — use `leftRender` |
922
+ | trailing | `string \| ReactNode` | — | **Deprecated** — use `rightRender` |
923
+
924
+ **Animation:** Scale springs to 0.97 on press-in, back to 1.0 on press-out (only when `onPress` is provided).
913
925
 
914
926
  **Example:**
915
927
  ```tsx
928
+ // Simple row with chevron
929
+ <ListItem
930
+ title="Profile"
931
+ subtitle="Manage your account"
932
+ showChevron
933
+ onPress={() => navigate('profile')}
934
+ />
935
+
936
+ // Rich row: avatar + title/subtitle/caption + price + badge
916
937
  <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')}
938
+ leftRender={<Avatar src={item.avatar} fallback={item.initials} size="md" />}
939
+ title={item.name}
940
+ subtitle={item.date}
941
+ caption={item.category}
942
+ rightRender={
943
+ <View style={{ alignItems: 'flex-end', gap: 4 }}>
944
+ <Text variant="label">${item.amount}</Text>
945
+ <Badge label={item.status} variant="secondary" size="sm" />
946
+ </View>
947
+ }
948
+ onPress={() => navigate('detail', { id: item.id })}
922
949
  />
923
950
 
924
- // Non-interactive row
925
- <ListItem title="Account number" trailing="**** 4321" />
951
+ // Card variant (standalone surface)
952
+ <ListItem
953
+ variant="card"
954
+ leftRender={<Ionicons name="wallet-outline" size={20} />}
955
+ title="Balance"
956
+ subtitle="Available funds"
957
+ rightRender="$12.500"
958
+ />
959
+
960
+ // List with separators
961
+ {transactions.map((t, i) => (
962
+ <ListItem
963
+ key={t.id}
964
+ title={t.name}
965
+ subtitle={t.date}
966
+ rightRender={t.amount}
967
+ showSeparator={i < transactions.length - 1}
968
+ onPress={() => navigate('detail', { id: t.id })}
969
+ />
970
+ ))}
926
971
  ```
927
972
 
973
+ **Notes:**
974
+ - `leftRender` renders inside a fixed 44×44pt container (centered) — no need to wrap in a sized View
975
+ - `rightRender` container has `maxWidth: 160` and aligns content to the right edge
976
+ - The separator inset aligns to the text block: `marginLeft: 16 + 44 + 12` when `leftRender` is set, `marginLeft: 16` otherwise
977
+
928
978
  ---
929
979
 
930
980
  ### Chip / ChipGroup
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;