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 here
return {
// 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:

PropType / Value
colorSchemestring value of a theme token (ie. blue or green)
themeThe theme object
colorModeDark or Light depending on the current value in the ColorMode Provider
orientationhorizontal 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.

NameDescriptionFunction Call
getColorRetrieves 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)
toneDetermines if the given color is relatively "light" or "dark". Requires the theme and a colortone(color)(theme)
isDark / isLightUtilizes the tone method to return a boolean whether a color is "Dark" or "Light".isDark(color)(theme)
transparentizeReturns 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)
whitenReturns 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)
blackenThe opposite of whiten. Requires the color, the amount of black (0 - 100), and the theme object.blacken(color, amount)(theme)
darkenSimilar to blacken, but darkens the shade of the given color.darken(color, amount)(theme)
lightenSimilar to whiten, but lightens the shade of the given color.lighten(color, amount)(theme)
contrastReturns 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)
isAccessibleDetermines 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)
complementaryProvide the complementary color to the provided color. Requires a color and the theme object.complementary(color)(theme)
generateStripeCreates 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)" )
randomColorGenerates a random color. Can optionally take an object with either any string to convert to a hex, or an array of colors to randomly pickrandomColor(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 } = props
const 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 } = props
return {
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 getBg function which returns this method and applied to any instance of a background prop.

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 reference object property, since the second argument fallback is provided, then the var() 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 a toString to make the value valid in the object because the argument of $diff is supplied to calc which 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,
})

Proudly made inNigeria by Segun Adebayo

Deployed by â–² Vercel