Add cva's VariantProps
to existing react components
Thank you for making cva
(Class Variance Authority).
npm i class-variance-authority react-cva-tools
yarn add class-variance-authority react-cva-tools
Tailwind CSS IntelliSense (ref: joe-bell/cva)
For Tailwind CSS IntelliSense Vscode extension, you can add the following to you setting.json
"tailwindCSS.experimental.classRegex": [
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["withCva\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
["withVariants\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
]
withVariants(component: React.ElementType, ...cvaArgs: Parameters<typeof cva>)
create a Button
component with 'button'
// components/Button.tsx
export const Button = withVariants('button', ['btn', 'font-bold'], {
variants: {
intent: {
primary: 'bg-blue-700 hover:bg-blue-800 text-gray-100',
},
padding: {
small: '',
medium: 'py-1 px-2',
},
round: {
small: 'rounded-sm',
medium: 'rounded',
full: 'rounded-full',
},
shadow: {
medium: 'shadow',
},
},
defaultVariants: {
padding: 'medium',
round: 'medium',
shadow: 'medium',
},
});
<Button
id="a-btn"
className="test-btn"
variants={{
intent: 'primary',
}}
onClick={(e) => {
alert('Click!!');
}}
>
click
</Button>
Result
<button
id="a-btn"
class="btn font-bold bg-blue-700 hover:bg-blue-800 text-gray-100 py-1 px-2 rounded shadow test-btn"
>
click
</button>
export const Box: FC<ComponentPropsWithoutRef<'div'>> = ({ ...props }) => (
<div {...props} />
);
export const FlexBox = withVariants(Box, null, {
variants: {
flex: {
row: 'flex flex-row',
},
},
});
create a CircleButton
by passing default variants parameters to Button
import { Button } from '@components/Button';
export const CircleButton = withDefaultVariants(Button, {
round: 'full',
className: 'w-12 h-12',
});
<CircleButton className="test" />
Result
<button
class="btn font-bold py-1 px-2 rounded-full shadow test w-12 h-12"
></button>
create a Button
component with cva. The result is the same as using withVariants
const buttonCva = cva(['btn', 'font-bold'], {
variants: {
intent: {
primary: 'bg-blue-700 hover:bg-blue-800 text-gray-100',
},
padding: {
small: '',
medium: 'py-1 px-2',
},
round: {
small: 'rounded-sm',
medium: 'rounded',
full: 'rounded-full',
},
shadow: {
medium: 'shadow',
},
},
defaultVariants: {
padding: 'medium',
round: 'medium',
shadow: 'medium',
},
});
export const Button = withCva('button', buttonCva);
<Button
id="a-btn"
className="test-btn"
variants={{
intent: 'primary',
}}
onClick={(e) => {
alert('Click!!');
}}
>
click
</Button>
Result
<button
id="a-btn"
class="btn font-bold bg-blue-700 hover:bg-blue-800 text-gray-100 py-1 px-2 rounded shadow test-btn"
>
click
</button>