Back to Tamagui

Config V4

library/config-v4.mdx

1.144.48.8 KB
Original Source

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:

js
{
  // 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',
}
json
{
  "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):

tsx
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.