# 📦 @retray-dev/ui-kit

A personal React Native / Expo UI component library with a built-in design system, dark mode support, haptic feedback, and smooth animations.

- 37 components across 7 categories
- Light/dark theme with 12 public tokens (24 resolved) and full customization
- Apple HIG–compliant touch targets and haptic feedback
- Animated interactions: spring press, sliding tabs, accordion easing, animated progress
- Built with TypeScript — full type declarations included

## Installation

```bash
# npm
npm install @retray-dev/ui-kit

# pnpm
pnpm add @retray-dev/ui-kit
```

### Peer dependencies

Install these in your app if not already present:

```bash
pnpm add expo-font 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
```

For Expo projects, run `npx expo install` instead to get SDK-compatible versions.

Add the Worklets Babel plugin to `babel.config.js` (required by `@gorhom/bottom-sheet`):

```js
module.exports = function (api) {
  api.cache(true)
  return {
    presets: ['babel-preset-expo'],
    plugins: ['react-native-worklets/plugin'],
  }
}
```

## Typography

All components use **Poppins** font family. You must load the fonts at app root before rendering any component:

```tsx
import { useFonts } from 'expo-font'
import { PoppinsFonts } from '@retray-dev/ui-kit/fonts'

export default function App() {
  const [fontsLoaded] = useFonts(PoppinsFonts)
  if (!fontsLoaded) return null

  return (
    // ... providers and app
  )
}
```

The library ships 13 font files (9 regular weights + 4 italic variants) as raw `.ttf` files. Metro resolves them at bundle time.

## Setup

Wrap your app root with all required providers. Order matters.

```tsx
import { SafeAreaProvider, initialWindowMetrics } from 'react-native-safe-area-context'
import { GestureHandlerRootView } from 'react-native-gesture-handler'
import { ThemeProvider, BottomSheetModalProvider, ToastProvider } from '@retray-dev/ui-kit'

export default function App() {
  return (
    <SafeAreaProvider initialMetrics={initialWindowMetrics}>
      <GestureHandlerRootView style={{ flex: 1 }}>
        <ThemeProvider colorScheme="system">
          <BottomSheetModalProvider>
            <ToastProvider>{/* your app */}</ToastProvider>
          </BottomSheetModalProvider>
        </ThemeProvider>
      </GestureHandlerRootView>
    </SafeAreaProvider>
  )
}
```

| Provider                   | Required by                                |
| -------------------------- | ------------------------------------------ |
| `SafeAreaProvider`         | `ToastProvider` (uses `useSafeAreaInsets`) |
| `GestureHandlerRootView`   | `Sheet`, `ConfirmDialog` (`@gorhom/bottom-sheet`) |
| `ThemeProvider`            | All components                             |
| `BottomSheetModalProvider` | `Sheet`, `ConfirmDialog`                   |
| `ToastProvider`            | `useToast` hook                            |

## Theme

Customize any color token per scheme:

```tsx
const myTheme = {
  light: { primary: '#6366f1', primaryForeground: '#ffffff' },
  dark:  { primary: '#818cf8', primaryForeground: '#ffffff' },
}

<ThemeProvider theme={myTheme} colorScheme="system">
```

Access theme colors anywhere inside the tree:

```tsx
import { useTheme } from '@retray-dev/ui-kit'

const { colors, colorScheme } = useTheme()
```

**Public tokens (12 — override these):** `background`, `foreground`, `card`, `primary`, `primaryForeground`, `border`, `destructive`, `destructiveForeground`, `success`, `successForeground`, `warning`, `warningForeground`

**Derived tokens (read-only via `useTheme()`):** `foregroundSubtle`, `foregroundMuted`, `surface`, `surfaceStrong`, `destructiveTint`, `destructiveBorder`, `successTint`, `successBorder`, `warningTint`, `warningBorder`, `ring`, `input`

## Design Tokens

Static structural constants — no provider required:

```ts
import { SPACING, ICON_SIZES, RADIUS, SHADOWS, BREAKPOINTS, TYPOGRAPHY } from '@retray-dev/ui-kit'

<View style={{ gap: SPACING.md, padding: SPACING.base, borderRadius: RADIUS.md, ...SHADOWS.sm }} />
```

| Token | Keys |
|-------|------|
| `SPACING` | `xxs` (2), `xs` (4), `sm` (8), `md` (12), `base` (16), `lg` (24), `xl` (32), `xxl` (48), `section` (64) |
| `ICON_SIZES` | `sm` (14), `md` (18), `lg` (22), `xl` (28), `2xl` (32) |
| `RADIUS` | `none` (0), `xs` (4), `sm` (8), `md` (14), `lg` (20), `xl` (32), `full` (9999) |
| `SHADOWS` | `sm`, `md`, `lg`, `xl` — cross-platform shadow presets |
| `BREAKPOINTS` | `wide` (700) |
| `TYPOGRAPHY` | 16 variants: `display-hero`, `display-xl`, `display-lg`, `display-md`, `display-sm`, `title-md`, `title-sm`, `body-md`, `body-sm`, `caption`, `caption-sm`, `badge-text`, `micro-label`, `uppercase-tag`, `button-lg`, `button-sm` |

## Components

| Category    | Components                                                                                      |
| ----------- | ----------------------------------------------------------------------------------------------- |
| Display     | `Text`, `Badge`, `Avatar`, `Separator`, `Spinner`, `Skeleton`, `Progress`, `CurrencyDisplay`   |
| Surfaces    | `Card`, `AlertBanner`, `EmptyState`, `MediaCard`                                                |
| Form        | `Button`, `ButtonGroup`, `IconButton`, `Input`, `CurrencyInput`, `Textarea`, `Checkbox`, `Switch`, `Toggle`, `RadioGroup`, `Select`, `Slider` |
| Composition | `Tabs`, `Accordion`                                                                             |
| Overlays    | `Sheet`, `ConfirmDialog`                                                                        |
| Feedback    | `Toast` / `ToastProvider` / `useToast`                                                          |
| Data        | `ListItem`, `Chip` / `ChipGroup`, `LabelValue`, `MonthPicker`, `CategoryStrip`, `DetailRow`    |
| Utilities   | `Pressable`                                                                                     |

### Quick examples

```tsx
import {
  Button, Input, Badge, Card, CardHeader, CardTitle, CardContent,
  Toast, useToast, Sheet, Select, Tabs, TabsContent,
} from '@retray-dev/ui-kit'

// Button
<Button label="Save" variant="primary" size="md" onPress={() => {}} />

// Toast
const { toast } = useToast()
toast({ title: 'Saved', variant: 'success' })

// Sheet (bottom sheet — auto-sizes to content)
<Sheet open={open} onClose={() => setOpen(false)} title="Options">
  <Text>Sheet content</Text>
</Sheet>

// Select
<Select
  value={value}
  onValueChange={setValue}
  options={[{ label: 'Option A', value: 'a' }, { label: 'Option B', value: 'b' }]}
  placeholder="Pick one"
/>
```

Full props reference and more examples are available in [COMPONENTS.md](./COMPONENTS.md), which is also shipped inside the npm package for use with AI tools:

```markdown
## UI Components

@./node_modules/@retray-dev/ui-kit/COMPONENTS.md
```

## License

MIT © Julian Camilo Cruz Sanchez
