library/config-v4.mdx
Here's a fully built tamagui config v4 just without the themes because they are quite large.
Config v4 uses CSS animations by default on the web and react-native animations on mobile.
shorthands:
{
// text
text: 'textAlign',
// view
b: 'bottom',
bg: 'backgroundColor',
content: 'alignContent',
grow: 'flexGrow',
items: 'alignItems',
justify: 'justifyContent',
l: 'left',
m: 'margin',
maxH: 'maxHeight',
maxW: 'maxWidth',
mb: 'marginBottom',
minH: 'minHeight',
minW: 'minWidth',
ml: 'marginLeft',
mr: 'marginRight',
mt: 'marginTop',
mx: 'marginHorizontal',
my: 'marginVertical',
p: 'padding',
pb: 'paddingBottom',
pl: 'paddingLeft',
pr: 'paddingRight',
pt: 'paddingTop',
px: 'paddingHorizontal',
py: 'paddingVertical',
r: 'right',
rounded: 'borderRadius',
select: 'userSelect',
self: 'alignSelf',
shrink: 'flexShrink',
t: 'top',
z: 'zIndex',
}
{
"tamaguiConfig": {
"fonts": {
"body": {
"family": "-apple-system, system-ui, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif",
"lineHeight": {
"1": 21,
"2": 22,
"3": 23,
"4": 24,
"5": 26,
"6": 28,
"7": 30,
"8": 33,
"9": 40,
"10": 56,
"11": 65,
"12": 72,
"13": 82,
"14": 102,
"15": 124,
"16": 144,
"true": 24
},
"weight": { "true": "300" },
"letterSpacing": { "true": 0 },
"size": {
"1": 11,
"2": 12,
"3": 13,
"4": 14,
"5": 16,
"6": 18,
"7": 20,
"8": 23,
"9": 30,
"10": 46,
"11": 55,
"12": 62,
"13": 72,
"14": 92,
"15": 114,
"16": 134,
"true": 14
}
},
"heading": {
"family": "-apple-system, system-ui, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif",
"lineHeight": {
"1": 25.4,
"2": 26.8,
"3": 28.2,
"4": 29.6,
"5": 32.4,
"6": 35.2,
"7": 38,
"8": 42.2,
"9": 52,
"10": 74.4,
"11": 87,
"12": 96.8,
"13": 110.8,
"14": 138.8,
"15": 169.6,
"16": 197.6,
"true": 29.6
},
"weight": { "true": "300" },
"letterSpacing": { "true": 0 },
"size": {
"1": 15.4,
"2": 16.8,
"3": 18.2,
"4": 19.6,
"5": 22.4,
"6": 25.2,
"7": 28,
"8": 32.2,
"9": 42,
"10": 64.4,
"11": 77,
"12": 86.8,
"13": 100.8,
"14": 128.8,
"15": 159.6,
"16": 187.6,
"true": 19.6
}
}
},
"animations": {
"75ms": "ease-in 75ms",
"100ms": "ease-in 100ms",
"200ms": "ease-in 200ms",
"bouncy": "ease-in 200ms",
"superBouncy": "ease-in 500ms",
"lazy": "ease-in 1000ms",
"medium": "ease-in 300ms",
"slow": "ease-in 500ms",
"quick": "cubic-bezier(0.215, 0.610, 0.355, 1.000) 400ms",
"quicker": "cubic-bezier(0.215, 0.610, 0.355, 1.000) 300ms",
"quickest": "cubic-bezier(0.215, 0.610, 0.355, 1.000) 200ms",
"tooltip": "ease-in 400ms"
},
"media": {
"2xl": { "minWidth": 1536 },
"xl": { "minWidth": 1280 },
"lg": { "minWidth": 1024 },
"md": { "minWidth": 768 },
"sm": { "minWidth": 640 },
"xs": { "minWidth": 460 },
"2xs": { "minWidth": 340 }
},
"tokens": {
"radius": {
"$0": 0,
"$1": 3,
"$2": 5,
"$3": 7,
"$4": 9,
"$5": 10,
"$6": 16,
"$7": 19,
"$8": 22,
"$9": 26,
"$10": 34,
"$11": 42,
"$12": 50,
"$true": 9
},
"zIndex": {
"$0": 0,
"$1": 100,
"$2": 200,
"$3": 300,
"$4": 400,
"$5": 500
},
"space": {
"$0": 0,
"$1": 2,
"$2": 7,
"$3": 13,
"$4": 18,
"$5": 24,
"$6": 32,
"$7": 39,
"$8": 46,
"$9": 53,
"$10": 60,
"$11": 74,
"$12": 88,
"$13": 102,
"$14": 116,
"$15": 130,
"$16": 144,
"$true": 18
},
"size": {
"$0": 0,
"$1": 20,
"$2": 28,
"$3": 36,
"$4": 44,
"$5": 52,
"$6": 64,
"$7": 74,
"$8": 84,
"$9": 94,
"$10": 104,
"$11": 124,
"$12": 144,
"$13": 164,
"$14": 184,
"$15": 204,
"$16": 224,
"$true": 44
}
},
"settings": {
"defaultFont": "body",
"onlyAllowShorthands": true,
"mediaQueryDefaultActive": { "xs": true, "2xs": true },
"themeClassNameOnRoot": true,
"fastSchemeChange": true,
"shouldAddPrefersColorThemes": true
},
"unset": { "fontFamily": "$body" }
}
}
Notes:
The tokens are built out so they look like $size.4.5, but in practice they
aren't used like that. Tamagui has token categories like size, radius, etc
and they map to specific props.
So you just use that size token like so (see tamagui.mdx in library for more on defining and using tokens):
import { View } from 'tamagui'
export default () => <View width="$4.5" />
Config v4 themes are generated somewhat like so (as of Feb 10 2024):
const darkPalette = [
'#050505',
'#151515',
'#191919',
'#232323',
'#282828',
'#323232',
'#424242',
'#494949',
'#545454',
'#626262',
'#a5a5a5',
'#fff',
]
const lightPalette = [
'#fff',
'#f2f2f2',
'hsl(0, 0%, 93%)',
'hsl(0, 0%, 91%)',
'hsl(0, 0%, 88%)',
'hsl(0, 0%, 85%)',
'hsl(0, 0%, 82%)',
'hsl(0, 0%, 76%)',
'hsl(0, 0%, 56%)',
'hsl(0, 0%, 50%)',
'hsl(0, 0%, 42%)',
'hsl(0, 0%, 9%)',
]
const lightShadows = {
shadow1: 'rgba(0,0,0,0.04)',
shadow2: 'rgba(0,0,0,0.08)',
shadow3: 'rgba(0,0,0,0.16)',
shadow4: 'rgba(0,0,0,0.24)',
shadow5: 'rgba(0,0,0,0.32)',
shadow6: 'rgba(0,0,0,0.4)',
}
const darkShadows = {
shadow1: 'rgba(0,0,0,0.2)',
shadow2: 'rgba(0,0,0,0.3)',
shadow3: 'rgba(0,0,0,0.4)',
shadow4: 'rgba(0,0,0,0.5)',
shadow5: 'rgba(0,0,0,0.6)',
shadow6: 'rgba(0,0,0,0.7)',
}
const blackColors = {
black1: darkPalette[0],
black2: darkPalette[1],
black3: darkPalette[2],
black4: darkPalette[3],
black5: darkPalette[4],
black6: darkPalette[5],
black7: darkPalette[6],
black8: darkPalette[7],
black9: darkPalette[8],
black10: darkPalette[9],
black11: darkPalette[10],
black12: darkPalette[11],
}
const whiteColors = {
white1: lightPalette[0],
white2: lightPalette[1],
white3: lightPalette[2],
white4: lightPalette[3],
white5: lightPalette[4],
white6: lightPalette[5],
white7: lightPalette[6],
white8: lightPalette[7],
white9: lightPalette[8],
white10: lightPalette[9],
white11: lightPalette[10],
white12: lightPalette[11],
}
const generatedThemes = createThemes({
componentThemes: defaultComponentThemes,
base: {
palette: {
dark: darkPalette,
light: lightPalette,
},
// for values we don't want being inherited onto sub-themes
extra: {
light: {
...Colors.blue,
...Colors.green,
...Colors.red,
...Colors.yellow,
...lightShadows,
...blackColors,
...whiteColors,
shadowColor: lightShadows.shadow1,
},
dark: {
...Colors.blueDark,
...Colors.greenDark,
...Colors.redDark,
...Colors.yellowDark,
...darkShadows,
...blackColors,
...whiteColors,
shadowColor: darkShadows.shadow1,
},
},
},
// inverse accent theme
accent: {
palette: {
dark: lightPalette,
light: darkPalette,
},
},
childrenThemes: {
black: {
palette: {
dark: Object.values(blackColors),
light: Object.values(blackColors),
},
},
white: {
palette: {
dark: Object.values(whiteColors),
light: Object.values(whiteColors),
},
},
blue: {
palette: {
dark: Object.values(Colors.blueDark),
light: Object.values(Colors.blue),
},
},
red: {
palette: {
dark: Object.values(Colors.redDark),
light: Object.values(Colors.red),
},
},
yellow: {
palette: {
dark: Object.values(Colors.yellowDark),
light: Object.values(Colors.yellow),
},
},
green: {
palette: {
dark: Object.values(Colors.greenDark),
light: Object.values(Colors.green),
},
},
},
})
So you have themes like light, dark (coming from base), then light_accent,
dark_accent, from accent, and the colors like light_red, etc.