I have a Button component, which accepts a variant prop. I want the className for the button to change based on the prop passed to it.
The goal is to avoid using if/else statements buttons, instead using a single button that dynamically changes based on the need.
// provide the variant to component:
<Button variant="default" />
// would return:
<button className={variantClasses.default} />
interface Props {
variant: string;
innerText: string;
}
function Button({ variant, innerText }: Props) {
// classes for all variants
const variantClasses = {
error: "...classes",
default: "...classes",
};
// if no variant provided, return an error variant.
if (!variant) {
return <button className={variantClasses.error}>Error</button>;
}
// else return the correct variant with matching styles.
else {
return (
<button className={`${variantClasses}.${variant}`}>
{innerText || "Button"}
</button>
);
}
}
export default Button;
className.variantClasses instead of an object.Tailwind does not support interpolation through classes the same way other css solutions do, so a workaround was needed. We can do this instead:
Here's what to do
name and className attributes.name matches variant provided.className prop on button component.interface Props {
variant: string;
innerText: string;
}
function Button({ variant, innerText }: Props) {
const variantClasses = [
{
name: "error",
className:
"...classes",
},
{
name: "filled",
className:
"...classes",
},
];
let activeClass = variantClasses.find((v) => v.name === variant);
// if matching variant is not found, throw error variant
if (!activeClass) {
return <button className={variantClasses[0].className}>Error</button>;
}
// if variant found, return matching class
else {
return (
<button className={activeClass?.className}>
{innerText || "Button"}
</button>
);
}
}
export default Button;