npm package: @oriva/design-system
Description: Oriva design system - comprehensive component library, design tokens, and Tamagui configuration for building beautiful, accessible applications
Author: Oriva
Latest version: 1.0.2

# Design System

A comprehensive, production-ready component library and design tokens for building beautiful, accessible applications with React Native and Tamagui.

**[Get Started](#quick-start)** • **[Components](#components)** • **[Design Tokens](#design-tokens)** • **[Hooks](#hooks)** • **[Examples](#examples)** • **[Troubleshooting](#troubleshooting)**

---

## What is This?

This is a complete design system package that provides:

- **50+ UI Components** — Atoms (basic) and molecules (composite) for every common UI need
- **Design Tokens** — Colors, spacing, typography, shadows, and more for consistent styling
- **Tamagui Integration** — Pre-configured Tamagui setup for optimal performance
- **Accessibility First** — WCAG AA compliant with keyboard navigation and screen reader support
- **Responsive Design** — Built-in breakpoints for mobile, tablet, and desktop
- **Theme Support** — Light, dark, and customizable theme variants

Perfect for building:
- **Mobile apps** with React Native
- **Web apps** with React
- **Cross-platform apps** that work on iOS, Android, and web
- **Accessible applications** that work for everyone

---

## Quick Start

### 1. Installation

```bash
npm install @oriva/design-system react-native react tamagui @tamagui/core
```

### 2. Setup Tamagui

Create `tamagui.config.ts` in your project:

```typescript
import { tamaguiConfig } from '@oriva/design-system/tamagui.config'

export default tamaguiConfig
```

### 3. Wrap Your App

```typescript
import { TamaguiProvider } from 'tamagui'
import { tamaguiConfig } from '@oriva/design-system/tamagui.config'
import MyApp from './App'

export default function Root() {
  return (
    <TamaguiProvider config={tamaguiConfig}>
      <MyApp />
    </TamaguiProvider>
  )
}
```

### 4. Use Components

```typescript
import { Button, Text, Card } from '@oriva/design-system/atoms'

export default function MyComponent() {
  return (
    <Card padding="medium">
      <Text>Hello, world!</Text>
      <Button onPress={() => alert('Clicked!')}>
        Press me
      </Button>
    </Card>
  )
}
```

**That's it!** Your app now has access to all design system components, tokens, and theming.

---

## Components

### Atoms — Basic Building Blocks

Atoms are simple, self-contained components for single UI purposes.

#### Common Atoms

| Component | Purpose | Example |
|-----------|---------|---------|
| **Button** | Clickable action | `<Button>Click me</Button>` |
| **Text** | Typography | `<Text size="lg" weight="bold">Title</Text>` |
| **TextInput** | Text input | `<TextInput placeholder="Enter text" />` |
| **Icon** | Icon from library | `<Icon name="heart" size="large" />` |
| **Badge** | Status labels | `<Badge variant="success">Active</Badge>` |
| **Card** | Container/card | `<Card><Text>Content</Text></Card>` |
| **Avatar** | User images | `<Avatar initials="JD" />` |
| **Checkbox** | Boolean input | `<Checkbox value={true} onChange={...} />` |
| **Divider** | Visual separator | `<Divider />` |

#### Temporal Components (Date/Time)

Perfect for scheduling and time-based features:

```typescript
import { DatePicker, TimePicker, DurationPicker } from '@oriva/design-system/atoms'

<DatePicker
  value={selectedDate}
  onChange={(date) => setSelectedDate(date)}
  minimumDate={new Date()}
  placeholder="Select date"
/>

<TimePicker
  value={selectedTime}
  onChange={(time) => setSelectedTime(time)}
  use24Hour={false}
  placeholder="Select time"
/>

<DurationPicker
  value={minutes}
  onChange={(dur) setDuration(dur)}
  unit="minutes"
  placeholder="Enter duration"
/>
```

### Molecules — Composed Components

Molecules combine multiple atoms into functional units.

#### Common Molecules

| Component | Purpose | Example |
|-----------|---------|---------|
| **FormField** | Label + input + validation | `<FormField label="Email" error="Invalid" />` |
| **ButtonGroup** | Multiple buttons | `<ButtonGroup><Button/><Button/></ButtonGroup>` |
| **SearchBar** | Search + clear button | `<SearchBar onChangeText={...} />` |
| **Header** | Page header | `<Header title="My Page" showBack />` |
| **Alert** | Alert/notification | `<Alert variant="warning">Be careful</Alert>` |
| **Tabs** | Tab navigation | `<Tabs tabs={[{label: "A"}, {label: "B"}]} />` |
| **Accordion** | Expandable sections | `<Accordion items={[{title: "Section"}]} />` |
| **Calendar** | Month view calendar | `<Calendar onDateSelect={...} />` |

---

## Design Tokens

Design tokens are standardized values for consistent styling across your app.

### Colors

```typescript
import { tokens } from '@oriva/design-system'

// Use semantic colors
tokens.colors.primary       // Brand primary color
tokens.colors.success       // Success green
tokens.colors.danger        // Error red
tokens.colors.warning       // Warning orange

// Use grayscale
tokens.colors.neutral[50]   // Very light
tokens.colors.neutral[900]  // Very dark

// Use in components
<View style={{ backgroundColor: tokens.colors.primary }}>
  <Text style={{ color: tokens.colors.neutral[900] }}>Hello</Text>
</View>
```

### Spacing

Standard spacing scale for margins and padding:

```typescript
tokens.spacing[0]     // 0px
tokens.spacing[1]     // 4px
tokens.spacing[2]     // 8px
tokens.spacing[4]     // 16px
tokens.spacing[8]     // 32px
tokens.spacing[16]    // 64px
```

### Typography

Control text appearance:

```typescript
tokens.typography.size.sm      // 14px
tokens.typography.size.base    // 16px
tokens.typography.size.lg      // 18px
tokens.typography.size.xl      // 20px
tokens.typography.size['2xl']  // 24px

tokens.typography.weight.normal      // 400
tokens.typography.weight.bold        // 700
tokens.typography.weight.semibold    // 600

tokens.typography.lineHeight.tight   // 1.25
tokens.typography.lineHeight.normal  // 1.5
```

### Responsive Design

Use Tamagui's responsive syntax with our tokens:

```typescript
<Text
  size={{ $sm: 'sm', $md: 'base', $lg: 'xl' }}
  padding={{ $sm: 4, $md: 8, $lg: 16 }}
>
  Responsive text
</Text>
```

Breakpoints:
- `$sm` — 640px and up
- `$md` — 768px and up
- `$lg` — 1024px and up
- `$xl` — 1280px and up
- `$2xl` — 1536px and up

---

## Theming

Switch between light, dark, and custom themes.

### Using Themes

```typescript
import { TamaguiProvider } from 'tamagui'
import { tamaguiConfig } from '@oriva/design-system/tamagui.config'
import { useTheme } from '@oriva/design-system/hooks'

function MyComponent() {
  const { theme, toggleTheme } = useTheme()

  return (
    <Button onPress={toggleTheme}>
      Switch to {theme === 'light' ? 'dark' : 'light'} mode
    </Button>
  )
}
```

### Available Themes

- **light** — Light background, dark text (default)
- **dark** — Dark background, light text
- **hugo** — Brand-specific theme with Romance Red accent

### Custom Themes

Create your own theme by extending the config:

```typescript
import { tamaguiConfig, createTamaGuiConfig } from '@oriva/design-system'

const myConfig = createTamaGuiConfig({
  ...tamaguiConfig,
  themes: {
    ...tamaguiConfig.themes,
    custom: {
      background: '#f0f0f0',
      foreground: '#333333',
      primary: '#my-brand-color',
      // ... other colors
    },
  },
})
```

---

## Hooks

Utility hooks for common patterns.

### useTheme

Access and manage theme:

```typescript
import { useTheme } from '@oriva/design-system/hooks'

function MyComponent() {
  const { theme, tokens } = useTheme()

  return (
    <View style={{ backgroundColor: tokens.colors.background }}>
      Current theme: {theme}
    </View>
  )
}
```

### useMedia

Detect responsive breakpoints:

```typescript
import { useMedia } from '@oriva/design-system/hooks'

function MyComponent() {
  const { isSmall, isMedium, isLarge } = useMedia()

  return isSmall ? <MobileLayout /> : <DesktopLayout />
}
```

### useResponsive

Get current breakpoint:

```typescript
import { useResponsive } from '@oriva/design-system/hooks'

function MyComponent() {
  const { breakpoint, isMobile, isDesktop } = useResponsive()

  return <Text>Current breakpoint: {breakpoint}</Text>
}
```

---

## Examples

### Example 1: Login Form

```typescript
import {
  Button,
  Text,
  TextInput,
  Card,
} from '@oriva/design-system/atoms'
import { FormField } from '@oriva/design-system/molecules'
import { useState } from 'react'
import { View } from 'tamagui'

export default function LoginScreen() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [error, setError] = useState('')

  const handleLogin = async () => {
    if (!email || !password) {
      setError('Please fill in all fields')
      return
    }

    try {
      // Call your API
      const response = await fetch('/api/login', {
        method: 'POST',
        body: JSON.stringify({ email, password }),
      })
      // Handle response...
    } catch (err) {
      setError('Login failed. Try again.')
    }
  }

  return (
    <View flex={1} justifyContent="center" paddingHorizontal={16}>
      <Card padding="large" marginBottom={24}>
        <Text size="2xl" weight="bold" marginBottom={24}>
          Welcome Back
        </Text>

        <FormField
          label="Email"
          error={error ? 'Email required' : undefined}
        >
          <TextInput
            value={email}
            onChangeText={setEmail}
            placeholder="you@example.com"
            keyboardType="email-address"
          />
        </FormField>

        <FormField label="Password" marginTop={16}>
          <TextInput
            value={password}
            onChangeText={setPassword}
            placeholder="Enter password"
            secureTextEntry
          />
        </FormField>

        {error && (
          <Text color="$danger" marginTop={12}>
            {error}
          </Text>
        )}

        <Button
          onPress={handleLogin}
          fullWidth
          marginTop={24}
        >
          Sign In
        </Button>
      </Card>
    </View>
  )
}
```

### Example 2: Responsive Card Grid

```typescript
import { Card, Text } from '@oriva/design-system/atoms'
import { useResponsive } from '@oriva/design-system/hooks'
import { View } from 'tamagui'

export default function CardGrid({ items }) {
  const { breakpoint } = useResponsive()

  const columns = breakpoint === 'xs' ? 1 : breakpoint === 'md' ? 2 : 3

  return (
    <View
      display="flex"
      flexDirection="row"
      flexWrap="wrap"
      gap={16}
      padding={16}
    >
      {items.map((item) => (
        <Card
          key={item.id}
          flex={1}
          minWidth={breakpoint === 'xs' ? '100%' : '48%'}
          padding="medium"
        >
          <Text weight="bold">{item.title}</Text>
          <Text color="$textSecondary" marginTop={8}>
            {item.description}
          </Text>
        </Card>
      ))}
    </View>
  )
}
```

---

## Accessibility

All components are built with accessibility in mind.

### Features

- ✅ Full keyboard navigation (Tab, Enter, Arrow keys, Escape)
- ✅ Screen reader support with proper ARIA labels
- ✅ High contrast and color-blind friendly color palette
- ✅ Focus indicators visible in all interactive elements
- ✅ Semantic HTML (when used in web)

### Best Practices

Always provide meaningful labels:

```typescript
// ✅ Good
<TextInput
  placeholder="Search"
  accessibilityLabel="Search products"
  aria-label="Search products"
/>

// ❌ Avoid
<TextInput placeholder="Search" />
```

Use semantic components:

```typescript
// ✅ Good - uses Button component with semantic role
<Button accessibilityRole="button">
  Click me
</Button>

// ❌ Avoid - using generic View
<View onPress={() => {}} style={{ cursor: 'pointer' }}>
  Click me
</View>
```

---

## Troubleshooting

### "Module not found: @oriva/design-system"

**Problem**: Package not installed or incorrect import path.

**Solution**:
```bash
# Install the package
npm install @oriva/design-system

# Check your import
import { Button } from '@oriva/design-system/atoms' // ✅ Correct
import { Button } from '@oriva/design-system'        // Also works
```

### "TamaguiProvider is not defined"

**Problem**: Tamagui provider not set up properly.

**Solution**:
```typescript
// Make sure your root file has:
import { TamaguiProvider } from 'tamagui'
import { tamaguiConfig } from '@oriva/design-system/tamagui.config'

export default function Root() {
  return (
    <TamaguiProvider config={tamaguiConfig}>
      <MyApp />
    </TamaguiProvider>
  )
}
```

### "Styles not applying"

**Problem**: Tamagui configuration not properly set up.

**Solution**:
1. Verify `tamagui.config.ts` exists
2. Check that `TamaguiProvider` wraps your app
3. Ensure you're using components from the design system (not custom styled components)
4. Rebuild your Metro bundler: `npm start -- --reset-cache`

### "Colors look wrong on dark mode"

**Problem**: Theme not switching properly.

**Solution**:
```typescript
// Explicitly set theme if auto-detection isn't working
<TamaguiProvider config={tamaguiConfig} defaultTheme="dark">
  <MyApp />
</TamaguiProvider>
```

### "Bundle size too large"

**Problem**: Including unused components.

**Solution**: Use tree-shaking by importing only what you need:

```typescript
// ✅ Good - only imports Button
import { Button } from '@oriva/design-system/atoms'

// ❌ Avoid - imports everything
import * as DesignSystem from '@oriva/design-system'
```

---

## API Reference

### Button Props

```typescript
interface ButtonProps {
  onPress?: () => void                           // Click handler
  disabled?: boolean                             // Disable button
  loading?: boolean                              // Show loading state
  variant?: 'primary' | 'secondary' | 'ghost'    // Style variant
  size?: 'small' | 'medium' | 'large'            // Button size
  fullWidth?: boolean                            // Stretch to container
  icon?: ReactNode                               // Icon component
  children?: ReactNode                           // Button text
}
```

### TextInput Props

```typescript
interface TextInputProps {
  value?: string                                       // Input value
  onChangeText?: (text: string) => void               // Change handler
  placeholder?: string                                // Placeholder text
  secureTextEntry?: boolean                           // Password input
  multiline?: boolean                                 // Multi-line input
  keyboardType?: 'default' | 'email-address' | ...   // Keyboard type
  disabled?: boolean                                  // Disable input
  error?: string                                      // Error message
}
```

### Card Props

```typescript
interface CardProps {
  children?: ReactNode                           // Card content
  variant?: 'default' | 'elevated' | 'outlined'  // Card style
  pressable?: boolean                            // Make pressable
  onPress?: () => void                           // Press handler
  padding?: 'small' | 'medium' | 'large'         // Padding size
}
```

See full API documentation in the TypeScript types.

---

## Contributing

Found a bug? Want to suggest an improvement? Contributions are welcome!

**Before contributing**:
- Check existing issues
- Run tests: `npm test`
- Build the package: `npm run build`
- Check TypeScript: `npm run type-check`

---

## Support

- 📖 [Full Documentation](https://github.com/your-org/design-system)
- 🐛 [Report Issues](https://github.com/your-org/design-system/issues)
- 💬 [Discussions](https://github.com/your-org/design-system/discussions)

---

## License

MIT © Oriva

---

## Version History

See [CHANGELOG.md](./CHANGELOG.md) for release notes and breaking changes.

**Current Version**: 1.0.0

**Latest Changes**:
- Initial release with atoms, molecules, design tokens
- DatePicker, TimePicker, DurationPicker components
- Calendar component with date highlighting
- Tamagui integration
- Full accessibility support
- Light, dark, and customizable themes