Composing Components
Learn how to compose components with TW-Classed
Composing Components
Composing one Classed component into another.
Classed Components can be composed via the classed function.
First argument composition
The first argument of the classed function is the Classed component to be composed. All variants and classNames are inherited.
import { classed } from "@tw-classed/react";
const BaseButton = classed("button");
const CheckoutButton = classed(
BaseButton,
"bg-blue-500 text-white font-bold py-2 px-4 rounded",
{
variants: {
size: {
sm: "text-sm",
lg: "text-lg",
},
},
defaultVariants: {
disabled: "opacity-50 cursor-not-allowed",
},
}
);
() => (
<>
<BaseButton>Base Button</BaseButton>
<CheckoutButton size="sm">Checkout Button</CheckoutButton>
</>
);Any argument composition
The classed function accepts any number of arguments and will compose them in order. All classNames and variants are inherited.
import { classed } from "@tw-classed/react";
const SizeButton = classed("button", {
variants: {
size: {
sm: "text-sm",
lg: "text-lg",
},
},
defaultVariants: {
size: "sm",
},
});
const ColorButton = classed("button", {
variants: {
color: {
red: "text-red-500",
blue: "text-blue-500",
},
},
defaultVariants: {
color: "red",
},
});
const Anchor = classed("a", "flex items-center", SizeButton, ColorButton);
// Anchor will be rendered as an `a` element inheriting all classNames and variants from SizeButton and ColorButton
() => (
<>
<Anchor size="lg" color="blue">
Anchor
</Anchor>
</>
);Using the render prop
The render prop can be used to change the underlying element of a Classed component. This is powered by the useRender hook from @base-ui/react.
import { classed } from "@tw-classed/react";
const BaseButton = classed(
"button",
"bg-blue-500 text-white",
"hover:bg-blue-400"
);
() => (
<BaseButton render={<a href="https://google.com" />}>
Link Button
</BaseButton>
);Using render as a function
The render prop also accepts a function that receives the props and allows you to have full control over the rendered element:
import { classed } from "@tw-classed/react";
const Button = classed("button", {
base: "px-4 py-2 rounded",
variants: {
color: {
blue: "bg-blue-500 text-white",
red: "bg-red-500 text-white",
},
},
});
() => (
<Button
color="blue"
render={(props) => (
<a {...props} href="/contact">
Contact Us
</a>
)}
>
Click me
</Button>
);Composing non-classed components
Classed components can be composed with non-classed components as the first argument to the classed function.
import { Link } from "react-router-dom";
import { classed } from "@tw-classed/react";
// First argument to classed
const LinkButton = classed(Link, "bg-blue-500 text-white");
() => <LinkButton to="/checkout">Checkout</LinkButton>;Note: When wrapping a custom component (non-intrinsic element), the render prop is not available. The component uses its own props directly.