@oriva/design-system
v1.0.2
Published
Oriva design system - comprehensive component library, design tokens, and Tamagui configuration for building beautiful, accessible applications
Downloads
31
Maintainers
Readme
Design System
A comprehensive, production-ready component library and design tokens for building beautiful, accessible applications with React Native and Tamagui.
Get Started • Components • Design Tokens • Hooks • Examples • 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
npm install @oriva/design-system react-native react tamagui @tamagui/core2. Setup Tamagui
Create tamagui.config.ts in your project:
import { tamaguiConfig } from '@oriva/design-system/tamagui.config'
export default tamaguiConfig3. Wrap Your App
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
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:
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
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:
tokens.spacing[0] // 0px
tokens.spacing[1] // 4px
tokens.spacing[2] // 8px
tokens.spacing[4] // 16px
tokens.spacing[8] // 32px
tokens.spacing[16] // 64pxTypography
Control text appearance:
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.5Responsive Design
Use Tamagui's responsive syntax with our tokens:
<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
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:
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:
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:
import { useMedia } from '@oriva/design-system/hooks'
function MyComponent() {
const { isSmall, isMedium, isLarge } = useMedia()
return isSmall ? <MobileLayout /> : <DesktopLayout />
}useResponsive
Get current breakpoint:
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
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="[email protected]"
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
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:
// ✅ Good
<TextInput
placeholder="Search"
accessibilityLabel="Search products"
aria-label="Search products"
/>
// ❌ Avoid
<TextInput placeholder="Search" />Use semantic components:
// ✅ 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:
# 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:
// 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:
- Verify
tamagui.config.tsexists - Check that
TamaguiProviderwraps your app - Ensure you're using components from the design system (not custom styled components)
- Rebuild your Metro bundler:
npm start -- --reset-cache
"Colors look wrong on dark mode"
Problem: Theme not switching properly.
Solution:
// 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:
// ✅ 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
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
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
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
License
MIT © Oriva
Version History
See 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
