Config v5
Modern config and themes with @tamagui/config/v5
The recommended Tamagui configuration gives you a complete design system, flexible theme generation, Tailwind aligned shorthands, multiple animation drivers, and easy customization.
V5 builds on v4 with more colors, theme helpers, and expanded media queries. Migration from v4 is straightforward - see what’s changed.
First install the config package:
yarn
npm
bun
pnpm
yarn add @tamagui/config
What’s Different from v4
Changes
- Animations not bundled - Import separately from
v5-css,v5-rn,v5-reanimated, orv5-motion. See Choosing an Animation Driver. - Media query naming -
2xl/2xs→xxl/xxs/xxxs. Max queries use kebab-case:max2Xl→max-xxl. styleCompat: 'react-native'-flexnow usesflexBasis: 0by default (v4 used'legacy'withflexBasis: auto).defaultPositionnot set - Defaults to browserstaticinstead of v4’s'relative'. You can still set it in your config.
New Features
- More color themes: gray, blue, red, yellow, green, orange, pink, purple, teal, neutral (v4 had blue, red, yellow, green, black, white)
- More theme colors:
shadow1-shadow8,highlight1-highlight8,background01/background001throughbackground08,color01/color001,white0/white02-white08,black0/black02-black08, and more - More animation values: timing presets from
0msto500ms, plus named springs likequick,bouncy,lazy, and variants likequickLessBouncy createV5Themehelper for easy theme customization and swapping colorsgetThemecallback increateV5Themefor computing custom values across every theme automatically based on each theme’s palette and scheme- Easier theme swapping: pass only the
childrenThemesyou want tocreateV5Themeto replace or extend the default color set - Height-based media queries:
height-sm,height-md,height-lgand max variants touchandhoverablemedia queries for device capability detection- Color utilities:
adjustPalette,adjustPalettesfor transforming palettes - Radix Colors v3 with improved accessibility (v4 used legacy Radix)
Migrating from v4
To restore v4 behavior while using v5:
tamagui.config.ts
import { defaultConfig } from '@tamagui/config/v5'import { animations } from '@tamagui/config/v5-css'import { createTamagui } from 'tamagui'export const config = createTamagui({...defaultConfig,animations,settings: {...defaultConfig.settings,styleCompat: 'legacy',defaultPosition: 'relative',},})
Update media query names in your code: $2xl → $xxl, $2xs → $xxs,
$max2Xl → $max-xxl.
Choosing an Animation Driver
V5 provides separate entry points for different animation drivers, so you only bundle what you need:
tamagui.config.ts
import { defaultConfig } from '@tamagui/config/v5'import { animations } from '@tamagui/config/v5-css'import { createTamagui } from 'tamagui'export const config = createTamagui({...defaultConfig,animations,})
Available animation drivers:
@tamagui/config/v5-css- CSS animations (smallest bundle, great for web)@tamagui/config/v5-motion- Motion animations (spring physics, smooth)@tamagui/config/v5-rn- React Native Animated API@tamagui/config/v5-reanimated- Reanimated (best native performance)
The base @tamagui/config/v5 export includes no animations. Import animations
separately from one of the driver entry points above.
Cross-Platform Animation Setup
For apps targeting both web and native, you can use different animation drivers per platform:
tamagui.config.ts
import { defaultConfig } from '@tamagui/config/v5'import { animations as animationsCSS } from '@tamagui/config/v5-css'import { animations as animationsReanimated } from '@tamagui/config/v5-reanimated'import { createTamagui, isWeb } from 'tamagui'export const config = createTamagui({...defaultConfig,animations: isWeb ? animationsCSS : animationsReanimated,})
This gives you CSS animations on web (smaller bundle, better performance) and Reanimated on native (smooth 60fps animations).
Available Animations
All v5 animation drivers include these preset animations:
Timing animations (fixed duration):
Props
0ms
Instant (0ms)
50ms
50 milliseconds
75ms
75 milliseconds
100ms
100 milliseconds
200ms
200 milliseconds
250ms
250 milliseconds
300ms
300 milliseconds
400ms
400 milliseconds
500ms
500 milliseconds
Spring animations (physics-based):
Props
superBouncy
Very bouncy, playful spring
bouncy
Bouncy spring with natural feel
superLazy
Very slow, heavy spring
lazy
Slow, relaxed spring
medium
Balanced spring for general use
slowest
Slowest spring animation
slow
Slow spring animation
quick
Fast, responsive spring
quickLessBouncy
Quick with minimal overshoot
quicker
Faster spring
quickerLessBouncy
Faster with minimal overshoot
quickest
Fastest spring
quickestLessBouncy
Fastest with minimal overshoot
Customizing Themes with createV5Theme
The createV5Theme function lets you customize the default v5 themes. The
easiest way to add or change colors is using @tamagui/colors which provides
Radix color palettes:
tamagui.config.ts
import { createV5Theme, defaultChildrenThemes, defaultConfig } from '@tamagui/config/v5'import { cyan, cyanDark, amber, amberDark } from '@tamagui/colors'import { createTamagui } from 'tamagui'const themes = createV5Theme({childrenThemes: {// include defaults (blue, red, green, yellow, etc.)...defaultChildrenThemes,// add new colorscyan: { light: cyan, dark: cyanDark },amber: { light: amber, dark: amberDark },},})export const config = createTamagui({...defaultConfig,themes,})
Or use only the colors you need:
tamagui.config.ts
import { createV5Theme } from '@tamagui/config/v5'import { blue, blueDark, gray, grayDark } from '@tamagui/colors'// minimal theme with just blue and grayconst themes = createV5Theme({childrenThemes: {blue: { light: blue, dark: blueDark },gray: { light: gray, dark: grayDark },},})
createV5Theme Options
Props
childrenThemes
Record<string, { light: ColorObject, dark: ColorObject }>
Color themes to include. Use defaultChildrenThemes to include defaults, or pass only the colors you need. Works directly with @tamagui/colors.
darkPalette
string[]
Override the dark base palette (12 colors from darkest to lightest)
lightPalette
string[]
Override the light base palette (12 colors from lightest to darkest)
grandChildrenThemes
Record<string, { template: string }>
Override grandChildren themes (alt1, alt2, surface1, etc.)
componentThemes
false | ComponentThemes
Default:
falseComponent themes (defaults to false in v5). We recommend using defaultProps instead.
getTheme
(info: { palette: string[], scheme: "light" | "dark" }) => Record<string, string>
Callback that runs for every generated theme, letting you compute custom values based on each theme's palette and color scheme. The default uses this to generate opacity variants like color01, background001, etc.
Customizing Every Theme with getTheme
The getTheme option lets you add computed colors to every generated theme. It
receives each theme’s palette and scheme, so your custom values automatically
adapt to every color and light/dark variant:
tamagui.config.ts
import { createV5Theme, opacify } from '@tamagui/config/v5'const themes = createV5Theme({getTheme: ({ palette, scheme }) => {const bg = palette[7]const fg = palette[palette.length - 2]return {// add your own computed theme valuesmyOverlay: opacify(bg, 0.5),mySubtleText: opacify(fg, 0.6),}},})
This is how v5 generates its built-in opacity tokens (background01,
color001, etc.) — your custom getTheme merges on top of the defaults.
Subtle Theme Variant
For a more muted look, use the subtle variant which has desaturated colors:
tamagui.config.ts
import { defaultConfig, themes } from '@tamagui/config/v5-subtle'import { createTamagui } from 'tamagui'export const config = createTamagui({...defaultConfig,themes,})
Custom Color Adjustments
Use adjustPalette to transform colors with a callback function. The callback
receives each color’s HSL values and its 1-based index (1-12):
tamagui.config.ts
import {adjustPalette,adjustPalettes,defaultChildrenThemes,createV5Theme,} from '@tamagui/config/v5'// adjust a single palette - desaturate and lightenconst mutedBlue = adjustPalette(blue, (hsl, i) => ({...hsl,s: hsl.s * 0.7,l: Math.min(100, hsl.l * 1.1),}))// adjust multiple palettes at once with adjustPalettesconst mutedThemes = adjustPalettes(defaultChildrenThemes, {// 'default' applies to all colors not explicitly listeddefault: {light: (hsl, i) => ({ ...hsl, s: hsl.s * 0.8 }),dark: (hsl, i) => ({ ...hsl, s: hsl.s * 0.6, l: hsl.l * 0.9 }),},// override specific colorsyellow: {light: (hsl) => ({ ...hsl, s: hsl.s * 0.5 }),dark: (hsl, i) => ({ ...hsl, s: hsl.s * (i <= 4 ? 0.3 : 0.8) }),},// skip adjustment for specific colorsgray: undefined,})const themes = createV5Theme({ childrenThemes: mutedThemes })
The callback receives:
hsl- object withh(hue 0-360),s(saturation 0-100),l(lightness 0-100)i- 1-based index in the palette (1-12)
Use the index to apply different adjustments to background colors (1-4), mid-tones (5-8), and foreground colors (9-12).
Theme Values
V5 themes include a rich set of color values accessible via $theme-* tokens.
Base Colors (color1-12)
Every theme includes 12 base colors that shift based on the theme:
<View bg="$color1" /> // Lightest in light mode, darkest in dark mode<View bg="$color6" /> // Mid-range<View bg="$color12" /> // Darkest in light mode, lightest in dark mode
Semantic Colors
Standard semantic values that adapt to each theme:
background,backgroundHover,backgroundPress,backgroundFocuscolor,colorHover,colorPress,colorFocusborderColor,borderColorHover,borderColorPress,borderColorFocusplaceholderColor,outlineColor
Opacity Variants
Foreground and background colors with opacity variants. The naming uses the
opacity value without the decimal point (e.g., 01 = 10%, 0025 = 2.5%).
color01(10%),color0075(7.5%),color005(5%),color0025(2.5%),color002(2%),color001(1%)background01(10%),background0075(7.5%),background005(5%),background0025(2.5%),background002(2%),background001(1%)background02(20%),background04(40%),background06(60%),background08(80%)
White & Black (Fixed)
Always available regardless of theme, with opacity variants:
white,white0(transparent),white02,white04,white06,white08black,black0(transparent),black02,black04,black06,black08white1-white12,black1-black12(12-step scales)
Shadow & Highlight Colors
Pre-tuned shadow opacities (black) for light and dark modes:
shadow1throughshadow8(light shadows are subtler, dark are stronger)shadowColor- Default shadow color for the theme
Pre-tuned highlight opacities (white) for light and dark modes:
highlight1throughhighlight8(matching shadow scale, useful for glows/overlays)
Radix Color Scales
All color themes expose their full 12-step scale:
<View bg="$blue5" /><Text color="$red11" /><View borderColor="$green7" />
Available scales: gray1-12, blue1-12, red1-12, green1-12, yellow1-12,
orange1-12, pink1-12, purple1-12, teal1-12
Neutral Colors
The neutral scale maintains sufficient contrast on both light and dark
backgrounds - useful for text or UI that needs to work regardless of theme:
neutral1-neutral12
Accent Colors
Every theme includes an inverted accent scale for contrast elements:
accent1-accent12- Inverted palette (light colors in dark mode, vice versa)accentBackground,accentColor- Quick access to accent bg/fg
<Button theme="accent">Primary Action</Button><View bg="$accentBackground" color="$accentColor" />
Color Themes
V5 includes these color themes by default:
- Grayscale: gray, neutral
- Colors: blue, green, red, yellow, orange, pink, purple, teal
- Fixed: black, white (generated from base palettes, don’t change between light/dark)
Each color theme has 12 steps following the Radix Colors pattern.
Use any color theme with the theme prop:
<Button theme="blue">Blue button</Button><Card theme="purple">Purple card</Card>
Access individual color values in any theme:
<View bg="$orange5" borderColor="$teal7" /><Text color="$pink11" />
Templates
V5 includes default templates that control how theme values map to palette
indices. Available templates: base, surface1, surface2, surface3,
alt1, alt2, inverse.
For more details on how templates work, see the Creating Custom Themes Guide.
Component Themes
V5 keeps component themes because they solve a hard problem — how do you change
the theme of an entire area (like from dark to dark_green) but have the
components inside it still keep their relative shades?
One of the great things in Tamagui is being able to set component themes, and sub-themes, and have an entire area of your UI re-theme and look perfect.
We’d exported just having the ability to set a default theme, like “surface1 =>
4”, but then if you try and re-theme a component to green, that would
conflict. For example, if you made your default <Button theme="surface3" />,
then if someone uses it <Button theme="green" /> now it’s green, but not the
Button green that is typically stronger than your base green.
So for now we’ve left them on! We do want to move away from component themes in
general as they can be tricky to understand. But the benefits are also strong,
and until we find a great solution we’re leaving them. You can always set
componentThemes: false in your createV5Themes function to turn it off.
Settings
V5 config includes these default settings:
Props
defaultFont
"body"
fastSchemeChange
true - Uses DynamicColorIOS on iOS for fast light/dark theme changes.
shouldAddPrefersColorThemes
true - Generates CSS for prefers-color-scheme.
allowedStyleValues
"somewhat-strict-web" - Allows web-only values like vh, vw.
addThemeClassName
"html" - Adds theme className to html tag for CSS variable access.
onlyAllowShorthands
true - Removes types for longhand versions of shorthands.
styleCompat
"react-native" - Aligns flex defaults to React Native (flexBasis: 0).
Media Queries
V5 includes an expanded set of media queries with height-based, max-width, and min-width variants.
The $sm through $xxl breakpoints match Tailwind CSS exactly (640, 768, 1024,
1280, 1536), making it easy to work across both ecosystems. The smaller
breakpoints ($xxxs, $xxs, $xs) provide finer control below 640px, which is
especially useful for container queries where you need granularity at smaller
sizes.
Min-Width (Mobile-First)
Props
xxxs
minWidth: 260
xxs
minWidth: 340
xs
minWidth: 460
sm
minWidth: 640
md
minWidth: 768
lg
minWidth: 1024
xl
minWidth: 1280
xxl
minWidth: 1536
Max-Width (Desktop-First)
Props
max-xxxs
maxWidth: 260
max-xxs
maxWidth: 340
max-xs
maxWidth: 460
max-sm
maxWidth: 640
max-md
maxWidth: 768
max-lg
maxWidth: 1024
max-xl
maxWidth: 1280
max-xxl
maxWidth: 1536
Height Min (Mobile-First)
Props
height-sm
minHeight: 640
height-md
minHeight: 768
height-lg
minHeight: 1024
Height Max (Desktop-First)
Props
max-height-sm
maxHeight: 640
max-height-md
maxHeight: 768
max-height-lg
maxHeight: 1024
Height queries have higher CSS specificity than width queries. When both match, height wins.
Device Capability
Props
touchable
pointer: coarse (touch devices)
hoverable
hover: hover (devices with hover capability)
These names describe intent rather than CSS implementation details — you’re thinking “is this a touch device?” not “what’s the pointer media query name?” They also read naturally in code:
<Button $touchable={{ p: '$4', minH: 44 }} $hoverable={{ hoverStyle: { bg: '$color5' } }} />
On web, these aren’t exact opposites. A laptop with a touchscreen might have
pointer: fine (trackpad as primary input) but still support touch. Having both
lets you target exactly what you mean.
On native, touch is always true and hoverable is always false since you
can’t hover on a touchscreen.
Shorthands
V5 includes Tailwind-aligned shorthands. With onlyAllowShorthands: true (the
default), only the short forms are available in types.
Text
Props
text
textAlign
Layout & Spacing
Props
p
padding
pt
paddingTop
pb
paddingBottom
pl
paddingLeft
pr
paddingRight
px
paddingHorizontal
py
paddingVertical
m
margin
mt
marginTop
mb
marginBottom
ml
marginLeft
mr
marginRight
mx
marginHorizontal
my
marginVertical
Position & Size
Props
t
top
b
bottom
l
left
r
right
minW
minWidth
maxW
maxWidth
minH
minHeight
maxH
maxHeight
z
zIndex
Flex & Alignment
Props
grow
flexGrow
shrink
flexShrink
items
alignItems
self
alignSelf
content
alignContent
justify
justifyContent
Other
Props
bg
backgroundColor
rounded
borderRadius
select
userSelect
Tree Shaking Themes
Production Optimization - Theme JS can grow to 20KB or more. Since Tamagui can hydrate themes from CSS variables, you can remove the themes JS from your client bundle for better Lighthouse scores.
This works because Tamagui generates CSS variables for all theme values. On the client, it reads these from the DOM instead of needing the JS object.
Setup
tamagui.config.ts
import { defaultConfig, themes } from '@tamagui/config/v5'import { createTamagui } from 'tamagui'export const config = createTamagui({...defaultConfig,// only load themes on server - client hydrates from CSS// for non-One Vite apps, use import.meta.env.SSR insteadthemes: process.env.VITE_ENVIRONMENT === 'client' ? ({} as typeof themes) : themes,})
This optimization requires server-side rendering. The CSS must be rendered on the server
for the client to hydrate from it. Make sure you’re using config.getCSS() or the
bundler plugin’s outputCSS option.
Summary: v4 to v5 Migration Checklist
- Add animations import - v5 doesn’t bundle animations:
import { animations } from '@tamagui/config/v5-css'
- Update media query names -
2xl→xxl,2xs→xxs,max2Xl→max-xxl - Review flex behavior - v5 uses
flexBasis: 0by default (React Native style) - Review position - v5 doesn’t set
defaultPosition(defaults tostatic) - Review theme colors - v5 uses Radix Colors v3 with slightly different values