Chakra Factory
Chakra factory serves as an object of chakra enabled JSX elements, and also a function that can be used to enable custom component receive chakra's style props.
import { chakra } from "@chakra-ui/react"
Chakra JSX Elements
Create base html elements with theme-aware style props using chakra.<element>
notation. For example, if you want a plain html button with ability to pass
chakra styles, you can write <chakra.button />
.
<chakra.button
px='3'
py='2'
bg='green.200'
rounded='md'
_hover={{ bg: 'green.300' }}
>
Click me
</chakra.button>
This reduces the need to create custom component wrappers and name them. This syntax is available for common html elements. See the reference for the full list of elements supported.
<chakra.h1 fontSize='lg'> Heading </chakra.h1>
Chakra factory function
This is a function that converts non-chakra components or jsx element to chakra-enabled components so you can pass style props to them.
Consider a package called react-input-autoresize
, let's use the chakra factory
function to make possible to pass style props.
The function will infer the prop types from the wrapped component and also add chakra style props.
import { chakra } from '@chakra-ui/react';
import Textarea from 'react-input-autoresize';
const AutoResizeInput = chakra(Textarea);
function Example() {
return <AutoResizeInput bg='red.200' fontSize='12px' />;
}
Considering that Chakra uses emotion
under the hood, ensure the non-chakra
component accepts className
as props for this to work correctly
Attaching styles
In some instances, you might need to attach specific styles to the component wrapped in the chakra factory
const AutoResizeInput = chakra(AutoResizeInput, {
baseStyle: {
bg: 'papayawhip',
color: 'red.500',
},
});
You can also use the chakra factory on jsx elements as well.
const Card = chakra('div', {
baseStyle: {
shadow: 'lg',
rounded: 'lg',
bg: 'white',
},
});
Allowing custom props to be forwarded
By default, the chakra
factory only filters chakra related style props from
getting to the DOM. For more fine-grained control of how and what prop should be
forwarded, pass the shouldForwardProp
option.
Here's a simple example that allows all props (including chakra's style props)
to pass through except the sample
prop.
const Div = chakra('div', {
shouldForwardProp: (prop) => !['sample'].includes(prop),
});
Another example that combines the default shouldForwardProp
from Chakra UI
with custom logic.
import { chakra, shouldForwardProp } from '@chakra-ui/react';
const Div = chakra('div', {
shouldForwardProp: (prop) => {
// don't forward Chakra's props
const isChakraProp = !shouldForwardProp(prop);
if (isChakraProp) return false;
// else, only forward `sample` prop
return ['sample'].includes(prop);
},
});
To filter non-HTML attributes, you can leverage @emotion/is-prop-valid package.
import isValidHTMLProp from '@emotion/is-prop-valid';
import { chakra, shouldForwardProp } from '@chakra-ui/react';
const Div = chakra('div', {
shouldForwardProp: (prop) => {
// don't forward Chakra's props
const isChakraProp = !shouldForwardProp(prop);
if (isChakraProp) return false;
// forward valid HTML props
const isValidProp = isValidHTMLProp(prop);
if (isValidProp) return true;
// else, only forward `sample` prop
return ['sample'].includes(prop);
},
});