Chakra UI v1.8.0 introduced a new feature called Semantic Tokens.
Semantic tokens allow us to use tokens with a specific name in Chakra props that map to a regular design token, for example, we can create a color semantic token that's called "success" that will map to the "green.500" color.
const theme = extendTheme({
semanticTokens: {
colors: {
success: "green.500"
}
}
});
and now the "success" token can be used in Chakra components as an "alias" to "green.500"
<Button bg="success">Accept</Button>
which will give us the same result as
<Button bg="green.500">Accept</Button>
Semantic Values
Another cool feature is mapping to a different value based on the current theme, for example, we can map the semantic token "error" to "red.600" in the light theme, and to "red.300" in the dark theme.
const theme = extendTheme({
semanticTokens: {
colors: {
error: {
default: "red.600",
_dark: "red.300"
}
}
}
});
This is really useful and allows us to reduce the usage of useColorModeValue, as now instead of
<Button bg={useColorModeValue('red.600', 'red.300')}>Retry</Button>
We can simply use the "error" semantic token:
<Button bg="error">Retry</Button>
Possible Semantic Token fields
As well as creating semantic tokens for colors, we can also create semantic tokens for every scale in Chakra UI: font sizes, borders, radii, sizes and more. see the complete list here and here.
In the following example we'll create semantic tokens for shadows & radii:
const theme = extendTheme({
semanticTokens: {
shadows: {
card: {
default: "md",
_dark: "none"
}
},
radii: {
card: "lg"
}
}
});
and now we can use our new tokens like so
<Box boxShadow="card" borderRadius="card">Card Content</Box>
Here's a codesandbox demo by Lazar Nikolov (Chakra UI core team member) demontrating these Semantic Tokens:
Taking things to the next level
Using everything we learned above we can now create a Semantic Tokens based design system with similar variants (50-900) to what chakra has for it's default colors.
We'll start with creating an array for the available color tints (50-900)
const availableColorTints = [
'50',
'100',
'200',
'300',
'400',
'500',
'600',
'700',
'800',
'900',
];
Now let's create a map of semantic token -> chakra theme color
const tokenToColorMap = {
primary: 'blue',
accent: 'teal',
success: 'green',
warning: 'orange',
error: 'red',
neutral: 'gray',
};
Now we'll build our theme's colors object using the tints array and the token map & we'll includes a simple color inversion logic for the dark & light themes to help us avoid calling useColorModeValue.
(primary.300 becomes blue.300 for the dark theme and blue.600 for the light theme which gives better results than leaving it to be the same color for both in my experience):
const colors = Object.entries(tokenToColorMap).reduce((acc, [token, color]) => {
availableColorTints.forEach((tint, index) => {
acc[`${token}.${tint}`] = {
default: `${color}.${availableColorTints[availableColorTints.length - 1 - index]}`,
_dark: `${color}.${tint}`,
};
});
return acc;
}, {});
This will generate the following colors object in runtime:
{
primary.50: {
default: "blue.900",
_dark: "blue.50"
},
primary.100: {
default: "blue.800",
_dark: "blue.100"
},
primary.200: {
default: "blue.700",
_dark: "blue.200"
},
primary.300: {
default: "blue.600",
_dark: "blue.300"
},
primary.400: {
default: "blue.500",
_dark: "blue.400"
},
primary.500: {
default: "blue.400",
_dark: "blue.500"
},
primary.600: {
default: "blue.300",
_dark: "blue.600"
},
primary.700: {
default: "blue.200",
_dark: "blue.700"
},
primary.800: {
default: "blue.100",
_dark: "blue.800"
},
primary.900: {
default: "blue.50",
_dark: "blue.900"
},
accent.50: {
default: "teal.900",
_dark: "teal.50"
},
// etc.
}
Now we can use our cool new Semantic Tokens in our components
<Button bg="primary.300" color="neutral.300">Ok</Button>
<Button bg="accent.400" color="neutral.400">Cancel</Button>
<Box bg="error.300" borderColor="error.400">Something went wrong</Box>
A full example of a theme file & usage is available in my personal website's github page.
Summary
We discussed what are semantic tokens, what are their benefits and how we can use them to our advantage when building a design system that's based on Chakra UI's built-in tokens.
Thanks for reading! 🚀
To read more about Semantic Tokens, see Chakra UI's docs.
Top comments (0)