Customization
Utilities
The utility API is a way to create your own CSS properties, map existing properties to a set of values or tokens. It's like building your own typesafe version of Chakra UI, Tailwind (in JS), or Styled System.
Panda comes with a set of utilities out of the box. You can customize them, or add your own.
Here are the properties you need to define or customize a utility:
className
: The className the property maps toshorthand
: The shorthand or alias version of the propertyvalues
: The possible values the property can have. Could be a token category, or an enum of values, string, number, or boolean.transform
: A function that converts the value to a valid css object
Creating a custom utility
Let's say we want to create new property br
that applies a border radius to an element.
export default defineConfig({
utilities: {
extend: {
br: {
className: 'rounded', // css({ br: "sm" }) => rounded-sm
values: 'radii', // connect values to the radii tokens
transform(value) {
return { borderRadius: value }
}
}
}
}
})
Then you can run the following command to generate the pattern JS code:
Now, we can use the br
property in our components.
function App() {
return <div className={css({ br: 'sm' })} />
}
or use in JSX style props
function App() {
return <styled.div br="sm" />
}
Using enum values
Let's say we want to create a new property borderX
that applies a limited set of inline border to an element and
automatically applies the border color.
export default defineConfig({
utilities: {
extend: {
borderX: {
values: ['1px', '2px', '4px'],
shorthand: 'bx', // `bx` or `borderX` can be used
transform(value, { token }) {
return {
borderInlineWidth: value,
borderColor: token('colors.red.200') // read the css variable for red.200
}
}
}
}
}
})
Now, we can use the borderX
or bx
property in our components.
function App() {
return <div className={css({ borderX: 'sm' })} />
}
Using mapped values
export default defineConfig({
utilities: {
extend: {
borderX: {
values: { small: '2px', medium: '5px' },
shorthand: 'bx',
transform(value, { token }) {
return {
borderTopWidth: value,
borderTopColor: token('colors.gray.400')
}
}
}
}
}
})
Using boolean values
export default defineConfig({
utilities: {
extend: {
truncate: {
className: 'truncate',
values: { type: 'boolean' },
transform(value) {
if (!value) return {}
return {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
}
}
}
}
})