Skip to main content

🎨 Styling with Unistyles 3.0

Shipnative uses React Native Unistyles 3.0 for a powerful and flexible styling solution. Unistyles provides a unified way to manage themes, responsive design, and component variants, ensuring a consistent and maintainable UI across your application. CRITICAL: Always use theme values from Unistyles. Avoid hardcoding colors, spacing, or typography values directly in your components.

Key Concepts

Theme Values

Unistyles centralizes your design tokens (colors, spacing, typography, etc.) in a single theme file (apps/app/app/theme/unistyles.ts). This allows for easy customization and ensures consistency. Accessing Theme Values:
import { useUnistyles } from 'react-native-unistyles'

const MyComponent = () => {
  const { theme } = useUnistyles()

  return (
    <View style={{ backgroundColor: theme.colors.background, padding: theme.spacing.md }}>
      <Text style={{ color: theme.colors.foreground, fontSize: theme.typography.sizes['2xl'] }}>
        Hello Shipnative!
      </Text>
    </View>
  )
}
Common Theme Values:
  • Colors (semantic):
    • theme.colors.primary (Primary action color)
    • theme.colors.background (Main screen background)
    • theme.colors.foreground (Main text color)
    • theme.colors.card (Card backgrounds)
    • theme.colors.error (Error states)
  • Spacing (8px grid):
    • theme.spacing.sm (8px)
    • theme.spacing.md (16px)
    • theme.spacing.lg (24px)
  • Typography:
    • theme.typography.sizes.base (Base font size, e.g., 16px)
    • theme.typography.fonts.bold (Bold font family)
  • Radius:
    • theme.radius.lg (Large border radius, e.g., 16px)
  • Shadows:
    • theme.shadows.md (Medium elevation shadow)
You can find the complete theme definition in apps/app/app/theme/unistyles.ts.

StyleSheet.create with Theme Function

Always define your styles using StyleSheet.create with a theme function. This ensures your styles automatically adapt to the current theme (e.g., dark mode).
import { StyleSheet, useUnistyles } from 'react-native-unistyles'

const MyScreen = () => {
  const { theme } = useUnistyles() // Access the current theme

  return (
    <View style={styles.container}>
      <Text style={styles.title}>My App Title</Text>
    </View>
  )
}

const styles = StyleSheet.create((theme) => ({
  container: {
    flex: 1,
    backgroundColor: theme.colors.background, // Uses theme background color
    padding: theme.spacing.lg,
  },
  title: {
    fontSize: theme.typography.sizes['2xl'],
    fontFamily: theme.typography.fonts.bold,
    color: theme.colors.foreground, // Uses theme foreground color
  },
}))

Component Variants

Unistyles allows you to define component variants, making it easy to create reusable components with different visual states (e.g., different button sizes or styles).
import { StyleSheet, useUnistyles } from 'react-native-unistyles'
import { Button as RNButton } from 'react-native'

type ButtonProps = {
  variant?: 'filled' | 'outlined' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  title: string;
  onPress: () => void;
}

const Button = ({ variant = 'filled', size = 'md', title, onPress }: ButtonProps) => {
  const { theme } = useUnistyles()
  const variantStyles = styles.button({ variant, size }) // Apply variants

  return (
    <RNButton
      title={title}
      onPress={onPress}
      style={[variantStyles, styles.baseButton]} // Combine base and variant styles
    />
  )
}

const styles = StyleSheet.create((theme) => ({
  baseButton: {
    borderRadius: theme.radius.md,
    justifyContent: 'center',
    alignItems: 'center',
  },
  button: {
    variants: {
      variant: {
        filled: { backgroundColor: theme.colors.primary, color: theme.colors.primaryForeground },
        outlined: { borderWidth: 1, borderColor: theme.colors.border, color: theme.colors.foreground },
        ghost: { backgroundColor: 'transparent', color: theme.colors.primary },
      },
      size: {
        sm: { height: 36, paddingHorizontal: theme.spacing.md },
        md: { height: 44, paddingHorizontal: theme.spacing.lg },
        lg: { height: 56, paddingHorizontal: theme.spacing.xl },
      },
    },
  },
}))

Dark Mode Support

All components in Shipnative are designed to support dark mode automatically through the use of semantic theme colors. When the user’s device theme changes, Unistyles will automatically apply the corresponding dark mode colors defined in apps/app/app/theme/unistyles.ts.
// Example from unistyles.ts (simplified)
export const lightTheme = {
  colors: {
    background: '#FFFFFF',
    foreground: '#000000',
    primary: '#007AFF',
  },
  // ... other tokens
}

export const darkTheme = {
  colors: {
    background: '#000000',
    foreground: '#FFFFFF',
    primary: '#0A84FF',
  },
  // ... other tokens
}
By using theme.colors.background and theme.colors.foreground, your components will automatically switch between white/black backgrounds and black/white text respectively, based on the active theme.

Common Mistakes to Avoid

  • ❌ Hardcoding values: color: "#000000" or marginTop: 24
    • βœ… Solution: Always use theme values: color: theme.colors.foreground, marginTop: theme.spacing.lg
  • ❌ Using inline styles for complex styling: style={{ flex: 1, padding: 16 }}
    • βœ… Solution: Use StyleSheet.create for better performance and maintainability: style={styles.container}
  • ❌ Not using the theme function in StyleSheet.create: StyleSheet.create({ container: { ... } })
    • βœ… Solution: Pass the theme function to StyleSheet.create to enable dynamic theme access: StyleSheet.create((theme) => ({ container: { ... } }))

🎨 Component Showcase

Shipnative includes a Component Showcase - a visual gallery of all pre-built components with live examples. This is perfect for:
  • πŸ‘€ Seeing what components are available
  • πŸ“‹ Copy-pasting component code
  • 🎨 Viewing components in light/dark mode
  • πŸ“± Testing responsive behavior

How to Access

Open the Dev Menu in your running app:
  • iOS Simulator: Press Cmd + D
  • Android Emulator: Press Cmd + M (Mac) or Ctrl + M (Windows/Linux)
  • Physical Device: Shake the device
Then select β€œComponent Showcase” from the menu.

What’s Included

The showcase displays all Shipnative components with examples: UI Components:
  • Button (filled, outlined, ghost, danger variants)
  • TextField (with labels, errors, helpers)
  • Card (default, elevated, outlined presets)
  • Text (heading, subheading, body, caption presets)
  • Avatar (with images and initials)
  • Badge (status indicators)
  • Divider
  • IconButton
  • Spinner
Each component shows:
  • βœ… All variants and sizes
  • βœ… Light and dark mode versions
  • βœ… Code snippets ready to copy
  • βœ… Props and usage examples
Tip: Use the Component Showcase as a reference when building your UI. You can see exactly how each component looks and behaves before using it in your screens!

Building Your Own Components

When creating custom components, follow the same patterns used in the showcase:
  1. Use Unistyles theme values
  2. Support variants with StyleSheet.create
  3. Include TypeScript props interface
  4. Support dark mode automatically
  5. Add to the showcase for team reference
Example based on showcase patterns:
import { Pressable } from 'react-native'
import { StyleSheet, useUnistyles } from 'react-native-unistyles'
import { Text } from '@/components/Text'

interface MyComponentProps {
  title: string
  variant?: 'primary' | 'secondary'
  onPress?: () => void
}

export function MyComponent({
  title,
  variant = 'primary',
  onPress
}: MyComponentProps) {
  const { theme } = useUnistyles()

  return (
    <Pressable
      style={[
        styles.container,
        variant === 'primary' && styles.primary,
        variant === 'secondary' && styles.secondary,
      ]}
      onPress={onPress}
    >
      <Text preset="subheading">{title}</Text>
    </Pressable>
  )
}

const styles = StyleSheet.create((theme) => ({
  container: {
    padding: theme.spacing.md,
    borderRadius: theme.radius.lg,
    alignItems: 'center',
  },
  primary: {
    backgroundColor: theme.colors.primary,
  },
  secondary: {
    backgroundColor: theme.colors.secondary,
  },
}))

Resources

  • Unistyles Documentation: https://unistyl.es/
  • Shipnative Theme Definition: apps/app/app/theme/unistyles.ts
  • Shipnative Core Components: apps/app/app/components/ (for examples of Unistyles usage)
  • Component Showcase: Access via Dev Menu in your running app