Styling
Theming with Restyle
Styling in React Native
We do NOT use StyleSheet.create or inline styles. We use Restyle by Shopify.
It provides a type-safe theme system that scales.
The Theme
Located at src/ui/style/theme.ts.
It defines your colors, spacing, and variants.
// Accessing the theme in code
import { useTheme } from '@shopify/restyle';
const theme = useTheme<Theme>();
const primaryColor = theme.colors.primary;How to Style Components
Instead of creating a style object, pass styles as props.
1. Margins & Padding (Spacing)
Use shorthand props from the theme spacing scale (xs, s, m, l, xl).
<Box padding="m" marginTop="xl">
<Text>Content</Text>
</Box>| Prop | CSS Equivalent |
|---|---|
m | margin |
p | padding |
mx | marginHorizontal |
py | paddingVertical |
2. Colors
Reference colors directly by name.
<Box backgroundColor="primary" borderColor="border" borderWidth={1}>
<Text color="textPrimary">Hello</Text>
</Box>3. Layout (Flexbox)
<Box
flex={1}
flexDirection="row"
justifyContent="space-between"
alignItems="center"
>
<Text>Left</Text>
<Text>Right</Text>
</Box>Variants
Variants allow you to define preset styles for components.
// Text Variants (defined in theme.textVariants)
<Text variant="h1">Heading 1</Text>
<Text variant="body">Body Text</Text>
<Text variant="caption">Caption</Text>
// Card Variants
<Card variant="elevated">...</Card>
<Card variant="outlined">...</Card>Defining Your Own Variants
Variants live in the theme, not in components. To add a new text style, extend textVariants in src/ui/style/theme.ts — every <Text variant="..."> in the app instantly gains the new option, fully typed:
// src/ui/style/theme.ts
textVariants: {
h1: { fontFamily: 'Inter-Bold', fontSize: 32, color: 'textPrimary' },
body: { fontFamily: 'Inter-Regular', fontSize: 16, color: 'textPrimary' },
caption: { fontFamily: 'Inter-Regular', fontSize: 12, color: 'textMuted' },
// add your own:
buttonLabel: { fontFamily: 'Inter-SemiBold', fontSize: 16, color: 'background' },
},The same pattern applies to cardVariants, buttonVariants, and any other component variant key. Because the variant name is checked against the theme at compile time, a typo like variant="bodyy" is caught before you ever run the app.
Responsive Styles
Restyle props accept breakpoint objects, so one component adapts to phones and tablets without a second layout. The breakpoints are defined once in the theme:
<Box
flexDirection={{ phone: 'column', tablet: 'row' }}
padding={{ phone: 'm', tablet: 'l' }}
>
{/* stacks on phones, sits side-by-side on tablets */}
</Box>Dark Mode
Restyle handles Dark Mode automatically.
If you use backgroundColor="background", it will automatically switch between light (#FFFFFF) and dark (#000000) based on the active theme.
The boilerplate ships a light and a dark theme with the same shape. The active theme is chosen from the device color scheme via useColorScheme() and passed to Restyle's ThemeProvider, so toggling the system setting re-themes the whole app with no per-component work. This only works if every component reads semantic color names (background, textPrimary, border) rather than literal hex values — which is exactly why the rule below matters.
[!TIP] Never hardcode hex codes like
#FF0000. Always add them tosrc/ui/style/tokens/colors.tsand reference them via the theme.
Why Not StyleSheet?
StyleSheet.create works, but it has no concept of your theme: nothing stops a teammate from typing #3B82F6 in twelve different files, and a rebrand becomes a find-and-replace. Restyle centralizes every token, makes dark mode free, and turns design-system drift into a compile error. The small upfront learning curve pays for itself the first time you change a brand color in one place and watch the whole app update.