Build faster with Premium Chakra UI Components 💎
Learn moreJanuary 3, 2025
Suppose that you need to change the padding of a button based on some pressed state.
const App = () => {
const [isPressed, setPressed] = useState(false)
// How do style the button separately based on the pressed state?
return <Button>Click Me</Button>
}You might be tempted to do something like this:
import { defineRecipe } from "@chakra-ui/react"
export const buttonRecipe = defineRecipe({
base: {
display: "flex",
},
variants: {
size: {
sm: ({ isPressed }) => ({
padding: isPressed ? "8" : "4",
fontSize: "12px",
}),
},
},
})This doesn't work because Chakra doesn't support functions in recipes. We require recipes to be serializable.
There are two ways to handle this:
data-* attributesFirst, apply the dynamic values to the component using the data-* attribute.
const App = () => {
const [isPressed, setPressed] = useState(false)
return <Button data-pressed={isPressed || undefined}>Click Me</Button>
}Next, style the recipe using the data-* attribute.
export const buttonRecipe = defineRecipe({
base: {
display: "flex",
},
variants: {
size: {
sm: {
padding: "4",
fontSize: "12px",
"&[data-pressed]": {
padding: "8",
},
},
},
},
})compoundVariantsCompound variants allow you to create style overrides based on variant combinations.
isActive variantcompoundVariants array that contains the style overridesimport { defineRecipe } from "@chakra-ui/react"
export const buttonRecipe = defineRecipe({
base: {
display: "flex",
},
variants: {
size: {
sm: {
padding: "4",
fontSize: "12px",
},
},
isPressed: {
true: {},
false: {},
},
},
compoundVariants: [
{
size: "sm",
isPressed: true,
css: {
padding: "8px",
fontSize: "12px",
},
},
],
})Then, you can pass the isPressed variant to the component as props.
<Button visual="solid" isPressed={isPressed}>
Click Me
</Button>If you use TypeScript, don't forget to run the typegen command to generate the
types for the recipe. See the CLI docs
for how to run typegen in postinstall, CI, and monorepos.
npx @chakra-ui/cli typegen