Introduction to twc
mainclsx or tailwind-merge inside a forwardRef component, twc allows you to create reusable components directly from HTML elements using tagged template literals.repository·main·Indexed 23 days ago
https://github.com/gregberge/twcA lightweight (0.49kb) utility for creating reusable React components styled with Tailwind CSS. It reduces boilerplate by replacing traditional forwardRef patterns with a factory that supports tagged template literals, dynamic prop-based styling, and an asChild prop for composition. Features include integration with tailwind-merge and cva, transient prop filtering to prevent invalid HTML attributes, and the .attrs() method for attaching static or dynamic attributes.
clsx or tailwind-merge inside a forwardRef component, twc allows you to create reusable components directly from HTML elements using tagged template literals.TWC (Tailwind CSS + React Components) provides several out-of-the-box capabilities for building components:
asChild Prop: Reuse classes using the asChild pattern.tailwind-merge and cva (Class Variance Authority).The asChild prop allows you to apply the Tailwind CSS classes defined on a twc component to its immediate child element instead of rendering the default HTML tag. This is useful for styling third-party components (like next/link) using the styles already defined in your twc components.
Internally, twc uses the Radix UI Slot component to implement this behavior. When asChild is present, the twc component will not render its own tag; instead, it will pass its props (including the generated classes) to the child element.
import NextLink from "next/link";
import { Anchor } from "./components/anchor";
export default () => (
<Anchor asChild>
<NextLink href="/">Go home</NextLink>
</Anchor>,
);react-twc does not support props interpolation within the class definitions. To handle dynamic classes based on props, you should pass the logic as a function at the top level of the component instead of attempting to interpolate them within the component's class definition.twc is that it automatically handles ref prop forwarding for all generated components. When you create a component using the twc tagged template literals (e.g., twc.div or twc.span), you do not need to manually implement React.forwardRef. You can pass a ref directly to the resulting component, and it will be correctly attached to the underlying DOM element.react-twc is not a direct port of styled-components for classes. It is designed to follow modern practices while maintaining a small footprint. Key features that distinguish it from similar libraries like classed-components include:
asChild prop.react-twc is designed to improve productivity when using Tailwind CSS with React, it is not strictly tied to it. Because the library creates class-based components, you can use it to manage CSS classes in any project, even those not using Tailwind CSS.You can pass a function to a twc component factory to dynamically adapt Tailwind classes based on the component's props. This is useful for implementing states like primary, disabled, or active.
To ensure these props are not passed down to the underlying DOM element (preventing invalid HTML attributes), prefix them with a $ (e.g., $primary). These are known as transient props.
When defining types for these components, use TwcComponentProps<"element"> to include the standard props accepted by twc components (which includes asChild and className).
import { twc, TwcComponentProps } from "react-twc";
type ButtonProps = TwcComponentProps<"button"> & { $primary?: boolean };
const Button = twc.button<ButtonProps>((props) => [
"font-semibold border border-blue-500 rounded",
props.$primary ? "bg-blue-500 text-white" : "bg-white text-gray-800",
]);Install the react-twc package using npm to get started with the library.
npm i react-twcTo enable Tailwind CSS IntelliSense inside twc calls in WebStorm (version 2023.1 or later):
experimental.classRegex configuration to your Tailwind settings.All twc components accept a className prop that allows you to extend the base classes defined on the component. Because twc uses clsx internally to merge classes, you can pass any format supported by clsx, including strings, arrays, objects, or nested structures.
import { twc } from 'react-twc'
const Title = twc.h2`text-2xl font-bold`;
// Strings
<Title className="uppercase" />
// Array
<Title className={[false, 0, "uppercase"]} />
// Objects
<Title className={{ uppercase: true }} />
// Nesting
<Title className={[{ uppercase: true }, "underline"]} />You can use twc to style any component (your own or from third-party libraries like Radix or React Aria) as long as the component accepts a className prop. To do this, pass the component to the twc function and append your Tailwind CSS classes using tagged template literals.
import * as HoverCard from "@radix-ui/react-hover-card";
import { twc } from "react-twc";
const HoverCardContent = twc(
HoverCard.Content,
)`data-[side=bottom]:animate-slideUpAndFade data-[side=right]:animate-slideLeftAndFade data-[side=left]:animate-slideRightAndFade data-[side=top]:animate-slideDownAndFade w-[300px] rounded-md bg-white p-5 shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] data-[state=open]:transition-all`;