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.
π 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)
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
π 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
β¨ 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>;
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>;
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...
};
Spacing
Standardize spacing in themes/spacing.ts
:
const spacing = {
padding: {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
},
// Margin and gap definitions...
};
Typography
Define font sizes in themes/styles.ts
:
const fontSizes = {
xs: 8,
sm: 12,
base: 14,
md: 16,
lg: 20,
xl: 24,
// Additional sizes...
};
π 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>
);
}
π‘οΈ 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 {}
}
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;
π Best Practices
- Theming:
- Use theme values instead of hardcoding.
- Access values via props:
${({ theme }) => theme.colors.primary}
.
- Component Organization:
- Separate styled components into
style.tsx
files. - Group related components in folders with an
index.tsx
entry point.
- TypeScript:
- Type all props and components explicitly.
- Extend existing React Native types where applicable.
-
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)