DEV Community

Serif COLAKEL
Serif COLAKEL

Posted on

Setting Up Expo with Styled Components and TypeScript

This guide walks you through setting up an Expo project using styled-components and TypeScript. The project supports a theme system, dark mode, and type-safe UI components, making it a robust foundation for modern React Native applications.

Code


πŸš€ Features

  • Styled Components: Leverage the power of styled-components with TypeScript.
  • Expo Router: Simplified navigation management.
  • Dark/Light Themes: Built-in theme switching based on system preferences.
  • Pre-configured Components: Ready-to-use, customizable UI elements.
  • Consistent Design: Standardized spacing and typography systems.
  • Type Safety: Fully typed themes and components.

πŸ› οΈ Quick Start

Step 1: Create a New Expo Project

Run the following command to initialize a new Expo project:

npx create-expo-app styled-setup --template

# Choose template: ➟ Blank (TypeScript)
Enter fullscreen mode Exit fullscreen mode

Step 2: Install Dependencies

Install the required dependencies for styled-components:

# Install styled-components
npm install styled-components

# Install type definitions for styled-components
npm install @types/styled-components-react-native --save-dev
Enter fullscreen mode Exit fullscreen mode

πŸ“‚ Project Structure

Organize your project with the following structure:

β”œβ”€β”€ app/                     # Expo Router app directory
β”‚   β”œβ”€β”€ (tabs)/              # Tab navigation
β”‚   β”‚   β”œβ”€β”€ index.tsx        # First tab screen
β”‚   β”‚   β”œβ”€β”€ two.tsx          # Second tab screen
β”‚   β”‚   └── _layout.tsx      # Tab layout configuration
β”‚   β”œβ”€β”€ _layout.tsx          # Root layout
β”‚   β”œβ”€β”€ modal.tsx            # Modal screen
β”‚   └── +not-found.tsx       # 404 screen
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ ui/                  # UI components
β”‚   β”‚   β”œβ”€β”€ button/
β”‚   β”‚   β”œβ”€β”€ container/
β”‚   β”‚   β”œβ”€β”€ text/
β”‚   β”‚   └── layout/
β”‚   └── ExternalLink.tsx
β”œβ”€β”€ themes/                  # Theme configuration
β”‚   β”œβ”€β”€ colors.ts            # Color definitions
β”‚   β”œβ”€β”€ sizes.ts             # Size scales
β”‚   β”œβ”€β”€ spacing.ts           # Spacing system
β”‚   β”œβ”€β”€ styles.ts            # Common styles
β”‚   β”œβ”€β”€ theme.d.ts           # Theme type definitions
β”‚   └── index.ts             # Theme export
└── hooks/                   # Custom hooks
    └── useColors.ts         # Theme colors hook
Enter fullscreen mode Exit fullscreen mode

✨ Core Components

Button Component

The Button component is a flexible, styled button supporting variants, sizes, and loading states.

import Button from "@/components/ui/button";

// Usage
<Button variant="primary" size="lg" shape="rounded" loading={false}>
  Click Me
</Button>;
Enter fullscreen mode Exit fullscreen mode

Props:

  • variant: 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info'
  • size: 'sm' | 'md' | 'lg' | 'xl'
  • shape: 'square' | 'rounded' | 'roundedLg' | 'circular'
  • loading: boolean
  • disabled: boolean

Flex Layout

The Flex and FlexItem components offer a flexible layout system inspired by CSS flexbox.

import { Flex, FlexItem } from "@/components/ui/layout";

// Usage
<Flex direction="row" justify="space-between" align="center" gap="md">
  <FlexItem grow={1}>
    <Text>Content</Text>
  </FlexItem>
</Flex>;
Enter fullscreen mode Exit fullscreen mode

Props:

  • direction: 'row' | 'column'
  • justify: 'start' | 'center' | 'end' | 'between' | 'around'
  • align: 'start' | 'center' | 'end'
  • gap: 'sm' | 'md' | 'lg' | 'xl'
  • wrap: 'wrap' | 'nowrap'

🎨 Theme System

Colors

Define a consistent color palette in themes/colors.ts:

const colors = {
  primary: "#3b82f6",
  secondary: "#22c55e",
  success: "#16a34a",
  error: "#dc2626",
  warning: "#f59e0b",
  info: "#0ea5e9",
  // Additional colors...
};
Enter fullscreen mode Exit fullscreen mode

Spacing

Standardize spacing in themes/spacing.ts:

const spacing = {
  padding: {
    xs: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 32,
  },
  // Margin and gap definitions...
};
Enter fullscreen mode Exit fullscreen mode

Typography

Define font sizes in themes/styles.ts:

const fontSizes = {
  xs: 8,
  sm: 12,
  base: 14,
  md: 16,
  lg: 20,
  xl: 24,
  // Additional sizes...
};
Enter fullscreen mode Exit fullscreen mode

πŸŒ™ Dark Mode Support

The app adapts to system dark mode preferences dynamically:

function RootLayoutNav() {
  const colorScheme = useColorScheme();

  return (
    <ThemeProvider
      theme={{
        ...themes,
        isDark: colorScheme === "dark",
      }}
    >
      <Stack>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
      </Stack>
    </ThemeProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

πŸ›‘οΈ Type Safety

Theme Types

Ensure theme type safety with themes/theme.d.ts:

import "styled-components/native";
import theme from ".";

export type AppTheme = typeof theme;

declare module "styled-components/native" {
  export interface DefaultTheme extends AppTheme {}
}
Enter fullscreen mode Exit fullscreen mode

Component Props

Define props for the Button component:

type ButtonProps = {
  variant?: keyof typeof buttonVariants;
  size?: keyof typeof buttonSizes;
  shape?: keyof typeof buttonShapes;
  gap?: keyof typeof buttonGap;
} & TouchableOpacityProps;
Enter fullscreen mode Exit fullscreen mode

πŸ”‘ Best Practices

  1. Theming:
  • Use theme values instead of hardcoding.
  • Access values via props: ${({ theme }) => theme.colors.primary}.
  1. Component Organization:
  • Separate styled components into style.tsx files.
  • Group related components in folders with an index.tsx entry point.
  1. TypeScript:
  • Type all props and components explicitly.
  • Extend existing React Native types where applicable.
  1. Performance:
    • Define styled components outside render functions.
    • Memoize complex components.
    • Minimize prop changes.

🏁 Conclusion

This guide provides a comprehensive setup for using styled-components with Expo and TypeScript. With a robust theme system, dark mode support, and type-safe components, this foundation ensures a scalable and maintainable codebase. Customize and extend this setup to meet your project’s unique requirements.

Have questions or feedback? Drop a comment or reach out! πŸš€

Top comments (0)