Theme Tools
The Theme Tools from ChakraUI are a collection of utilities that are for public use to simplify your custom theme file or styling within components using methods to make your design more dynamic.
With any of these tools, you will need to install the theme-tools package
separately as they are not a part of @chakra-ui/react.
import { ... } from '@chakra-ui/theme-tools'
Usage#
All of the tools are used in various places within your theme file. Each example below comes from the default component themes from ChakraUI. In most cases, they leverage style props that are passed into a given component to be able to function correctly.
Take for example a new Button variant. We need to access the props by giving a
variant an anonymous function. And then destructure what you need.
Typically, the props you might need are the theme object itself and the
colorScheme which you pass in as an active color token names (not including
the range values) (see the default theme colors)
const theme = extendTheme({components: {Button: {variants: {variantCustom: (props) => {const { theme, colorScheme: c } = props// Some setup logic herereturn {// Apply styles here}},},},},})
Note: This is where it's best to split up your theme file to scale out your project
Style Function Props#
When creating a variant or base style with dynamic styles, it's value can be a function instead of an object to use props that are passed to the component. The following props can be used as part of the signature:
| Prop | Type / Value |
|---|---|
colorScheme | string value of a theme token (ie. blue or green) |
theme | The theme object |
colorMode | Dark or Light depending on the current value in the ColorMode Provider |
orientation | horizontal or vertical, defined as the direction the component is laid out. (Like setting flexDirection) |
And any other props passed to the component you want to access!
Colors#
Below are the methods that can be used to access and alter the colors from the theme.
| Name | Description | Function Call |
|---|---|---|
getColor | Retrieves a color hex value. Needs the theme and color name, and can take a fallback hex if the color name does not return a valid hex from the theme. | getColor(theme, color, fallback) |
tone | Determines if the given color is relatively "light" or "dark". Requires the theme and a color | tone(color)(theme) |
isDark / isLight | Utilizes the tone method to return a boolean whether a color is "Dark" or "Light". | isDark(color)(theme) |
transparentize | Returns the given color with an alpha value as an rgba string. Requires the color, opacity in decimals (0 - 1) and the theme object. | transparentize(color, opacity)(theme) |
whiten | Returns a hex value with a whiter shade of the given color. Requires the color, the amount of white (0 - 100) and the theme object. | whiten(color, amount)(theme) |
blacken | The opposite of whiten. Requires the color, the amount of black (0 - 100), and the theme object. | blacken(color, amount)(theme) |
darken | Similar to blacken, but darkens the shade of the given color. | darken(color, amount)(theme) |
lighten | Similar to whiten, but lightens the shade of the given color. | lighten(color, amount)(theme) |
contrast | Returns the contrast ratio of two provided colors. The first param is the foreground color, and the second the background color. Also requires the theme object. | contrast(fg, bg)(theme) |
isAccessible | Determines if the two given colors meet contrast ratio guidelines. Requires the theme object, the text color as the first param, the background color as the second param, and an optional object of WCAG params (See the API Docs). | isAccessible(textColor, bgColor, options?)(theme) |
complementary | Provide the complementary color to the provided color. Requires a color and the theme object. | complementary(color)(theme) |
generateStripe | Creates a set of styles for a gradient background image to use as a divider. Optionally can take a new unit size (height/width) and color. | generateStripe(size = "1rem", color = "rgba(255, 255, 255, 0.15)" ) |
randomColor | Generates a random color. Can optionally take an object with either any string to convert to a hex, or an array of colors to randomly pick | randomColor(opts?) |
Color Tool Examples#
Below showcases a mix of the methods in action from Chakra's default component theme.
We can find a prime use case of getColor() in the Alert themes, where a
function is created with mode() and transparentize() theme tool method for
the background color to determine which color to return based on the color mode.
Mode is discussed later in the Component Theme Tools.
function getBg(props: StyleFunctionProps): string {const { theme, colorScheme: c } = propsconst lightBg = getColor(theme, `${c}.100`, c)const darkBg = transparentize(`${c}.200`, 0.16)(theme)return mode(lightBg, darkBg)(props)}const variantSubtle: PartsStyleFunction<typeof parts> = (props) => {const { colorScheme: c } = propsreturn {container: { bg: getBg(props) },icon: { color: mode(`${c}.500`, `${c}.200`)(props) },spinner: {color: mode(`${c}.500`, `${c}.200`)(props),},}}
Component Tools#
There are mny times where you need the theme to be reliant on the color mode and/or the direction a component is rendered (horizontally or vertically).
mode()#
A function that accepts two values and requires the props object from the component theme (variant or base style) to check for color mode. Then returns either the first value if in "light" mode or the second if in "dark" mode.
You can see the example above with the
getBgfunction which returns this method and applied to any instance of abackgroundprop.
orient#
A function that returns an object of declared styles depending on orientation value ("horizontal" or "vertical").
It is used both in themes and in components or component hooks to obtain orientation state for the most dynamic styling possible.
The example below spreads the orient return into a
markerStyle object
that is used for the marker of the Slider component. So if the orientation
value provided is "vertical", then the styling declared in the "vertical" object
is returned.
const markerStyle: React.CSSProperties = {position: 'absolute',pointerEvents: 'none',...orient({orientation,vertical: {bottom: isReversed ? `${100 - markerPercent}%` : `${markerPercent}%`,},horizontal: {left: isReversed ? `${100 - markerPercent}%` : `${markerPercent}%`,},}),}
CSS tools#
cssCalc#
This is a collection of methods used to create the CSS calc() function based
on number value passed in. The collection is imported as calc followed by the
method name.
For example: calc.add(10, 20) will return calc(10 + 20)
In addition to methods that create calc(), there is also the negate method
which return the value multiplied by -1. If a string is passed in such as
"5 + 8", then the value returned is -5 + 8. If it's an actual operation and
not a string, such as calc.negate(5 + 8), then the value returned is -13.
cssVar#
Method to generate a prefixed CSS variable and reference var() function.
cssVar('custom-component', 'blue', 'chakra')/** Returns the object* {* variable: `--chakra-custom-component`,* reference: `var(--chakra-custom-component, blue)`* }*/
In the
referenceobject property, since the second argumentfallbackis provided, then thevar()function is called with the fallback value as its second argument, in this case "blue".
The example below comes from the Switch component default theme, which
utilizes both tools to help create the initial setup of the base styles.
Note that
negate()is extended with atoStringto make the value valid in the object because the argument of$diffis supplied tocalcwhich passes it down to the method.
const $width = cssVar('switch-track-width')const $height = cssVar('switch-track-height')const $diff = cssVar('switch-track-diff')const diffValue = calc.subtract($width, $height)const $translateX = cssVar('switch-thumb-x')// Later in the file...const baseStyle: PartsStyleFunction<typeof parts> = (props) => ({container: {[$diff.variable]: diffValue,[$translateX.variable]: $diff.reference,_rtl: {[$translateX.variable]: calc($diff).negate().toString(),},},track: baseStyleTrack(props),thumb: baseStyleThumb,})