Configuration

Set up custom themes, tokens, shorthands, and media queries.

You'll want to create a tamagui.config.ts in the root of your application code that sets up your design system properties. Overview
Let's start with a full yet slimmed down tamagui.config.ts:
import { createTamagui, createTokens, createFont } from 'tamagui'
const interFont = createFont({
family: 'Inter, Helvetica, Arial, sans-serif',
size: {
1: 12,
2: 14,
3: 15,
// ...
},
lineHeight: {
1: 17,
2: 22,
3: 25,
// ...
},
weight: {
4: 300,
6: 600,
},
letterSpacing: {
4: 0,
8: -1,
},
})
const size = {
0: 0,
1: 5,
2: 10
// ....
}
export const tokens = createTokens({
font: { body: interFont },
size,
space: { ...size, '-1': -5, '-2': -10 },
radius: { 0: 0, 1: 3 },
zIndex: { 0: 0, 1: 100, 2: 200 },
color: {
white: '#fff',
black: '#000'
},
})
const config = createTamagui({
tokens,
themes: {
light: {
bg: '#f2f2f2',
color: tokens.color.black,
},
dark: {
bg: '#111',
color: tokens.color.white,
},
},
media: {
sm: { maxWidth: 860 },
gtSm: { minWidth: 860 + 1 },
short: { maxHeight: 820 },
hoverNone: { hover: 'none' },
pointerCoarse: { pointer: 'coarse' },
},
shorthands: {
px: 'paddingHorizontal',
f: 'flex',
w: 'width',
},
})
type Conf = typeof config
// this will give you types for your components
declare module 'tamagui' {
interface TamaguiCustomConfig extends Conf {}
}
export default config
The createTamagui function receives a configuration object:
  • tokens: Use createTokens to generate variables in your theme and app.
  • theme: Define your design theme, which map to CSS properties.
  • media: Define reusable responsive media queries.
  • shorthands: Define any props you want to expand to style values, keys being the shorthand and values being the expanded style prop.
Add Provider
Import and use the Tamagui Provider component at the top component in your app.
import Tamagui from './tamagui.config'
export default function App() {
return (
<Tamagui.Provider>
{/* The rest of your app here */}
</Tamagui.Provider>
)
}
Tokens
Tokens have a structure inspired by but divergent from the Theme UI spec . They are mapped to CSS variables at build time. Font tokens
The font tokens are a bit special and are created with createFont:
const interFont = createFont({
family: 'Inter, Helvetica, Arial, sans-serif',
size: {
1: 12,
2: 14,
3: 15,
// ...
},
lineHeight: {
1: 17,
2: 22,
3: 25,
// ...
},
weight: {
4: 300,
6: 600,
},
letterSpacing: {
4: 0,
8: -1,
},
})
Note, you don't need to use numbered keys, you can use sm or tiny or whatever you'd like. But you do want keep those keys consistent.
This gives you a lot of power over customizing every aspect of your design based on each font family. In other styling libraries that follow the Theme UI spec, you generally don't group your size/lineHeight/weight/etc tokens by the family, which means you are forced to choose a single vertical rythym no matter the font. Things to note:
  • The keys of size, lineHeight, weight, and letterSpacing are meant to match.
  • Define the full set of keys on size, the rest can be a subset.
  • Missing keys from partially defined objects will be filled in.
    • In the example above, weight is only defined at 4 and 6.
    • At creation Tamagui fills in the missing keys with previous value, or the next one if no previous exists. So weight 1 === 300, weight 5 === 300, and weight 7 === 600.
wwwwwwwwwwwwwwwwwww
Non-font tokens
The rest of the tokens categories besides font are flatter. Note that space and size generally share keys, and that space can generally use negative keys as well.
// passed into createTamagui
const tokens = createTokens({
color: {
white: '#fff',
black: '#000'
},
})
You access tokens then by using $ prefixes in your values. Note that Tamagui knows which tokens to use based on the style property you use.
const App = () => (
<Text fontSize="$lg" lineHeight="$lg" fontFamily="$mono" color="$white" >
Hello world
</Text>
)
One final note: using tokens with themes. Tokens are considered a "fallback" to themes, so any values you define in your theme will override the token. The next section will explain this further. Themes
Themes live one level below tokens. Tokens are your variables, where themes use those tokens to create consistent, generic properties that you then typically use in shareable components. Themes should generally only deal with colors. Tamagui components in general expect a set of theme keys to be defined like the following, but you can deviate if you create your own design system. See the source for the website  for a fuller example.
const light = {
bg: '#fff',
bg2: tokens.color.gray2,
bg3: tokens.color.gray4,
bg4: tokens.color.gray5,
bgTransparent: tokens.color.grayA1,
borderColor: tokens.color.gray4,
borderColor2: tokens.color.gray6,
color: tokens.color.gray12,
color2: tokens.color.gray11,
color3: tokens.color.gray10,
color4: tokens.color.gray9,
shadowColor: tokens.color.grayA4,
shadowColor2: tokens.color.grayA6,
...lightColors,
}
Notice you don't have to use tokens as your theme values, but if you do they avoid some overhead. With Tamagui, the idea is that bg, color, and borderColor represent the "primary" and clearest colors, and bg2, color2 etc get more subtle. To see how it works, here's a snippet from InteractiveFrame which is the frame component that's used in Button:
export const InteractiveFrame = styled(XStack, {
borderRadius: '$1',
paddingVertical: '$2',
paddingHorizontal: '$3',
backgroundColor: '$bg2',
justifyContent: 'center',
alignItems: 'center',
cursor: 'pointer',
flexWrap: 'nowrap',
flexDirection: 'row',
flexShrink: 1,
hoverStyle: {
backgroundColor: '$bg3',
},
pressStyle: {
backgroundColor: '$bg4',
},
// ...
})
Media
For more full docs on media queries, see the useMedia docs page. Shorthands
Shorthands are defined directly on your createTamagui call, rather than being attached to each component. The reason for this is that it de-couples shorthands from components - it forces component kits to standardize on the basic react-native style syntax, and lets the user of the component kit decide their own "utility shorthands" as they see fit. We think this is a natural model. Here's an example of a complete shorthands configuration:
const shorthands = {
ac: 'alignContent',
ai: 'alignItems',
als: 'alignSelf',
bblr: 'borderBottomLeftRadius',
bbrr: 'borderBottomRightRadius',
bc: 'backgroundColor',
br: 'borderRadius',
btlr: 'borderTopLeftRadius',
btrr: 'borderTopRightRadius',
f: 'flex',
fb: 'flexBasis',
fd: 'flexDirection',
fg: 'flexGrow',
fs: 'flexShrink',
fw: 'flexWrap',
h: 'height',
jc: 'justifyContent',
m: 'margin',
mb: 'marginBottom',
ml: 'marginLeft',
mr: 'marginRight',
mt: 'marginTop',
mx: 'marginHorizontal',
my: 'marginVertical',
p: 'padding',
pb: 'paddingBottom',
pe: 'pointerEvents',
pl: 'paddingLeft',
pr: 'paddingRight',
pt: 'paddingTop',
px: 'paddingHorizontal',
py: 'paddingVertical',
w: 'width',
zi: 'zIndex',
lh: 'lineHeight',
ta: 'textAlign',
fos: 'fontSize',
} as const
export default createTamagui({
shorthands
})