Best way to create reusable class combos with Tailwind CSS in React?
reactjs - what is the best pracitse to make reusable react component with different styles using tailwind? - Stack Overflow
reactjs - Simple way to reuse tailwind component in react - Stack Overflow
Tailwind reusable component className override issues?
Videos
What is the best practise to define a reusable set of Tailwind CSS utility classes and apply them as a single class in React, instead of repeating the full set of classes on each element?
I'm sharing one of my implementations using TypeScript.
You can get ideas of how you can reuse any component with tailwind. The implementation, naming and pathing usually opinionated.
// src/components/atoms/Button.tsx
import {DefaultComponent} from '$types/common';
import {NoopFn, classNames} from '@utils';
import {ReactElement} from 'react';
type ButtonUse = `primary` | `secondary` | `destructive`;
type ButtonSize = `xs` | `sm` | `md`;
type ButtonType = `button` | `submit`;
type ButtonProps = DefaultComponent & {
size?: ButtonSize;
type?: ButtonType;
use?: ButtonUse;
};
const BUTTON_SIZE: {[key in ButtonSize]: string} = {
md: `text-base px-4 py-2`,
sm: `text-sm px-3 py-2 leading-4`,
xs: `text-xs px-2.5 py-1.5`,
};
const BUTTON_COLOR: {[key in ButtonUse]: string} = {
destructive: `text-white bg-red-600 hover:bg-red-700`,
primary: `text-white bg-indigo-600 hover:bg-indigo-700`,
secondary: ``,
};
export const Button = (props: ButtonProps): ReactElement => {
const {
className = ``,
children,
use = `primary`,
size = `xs`,
type = `button`,
onClick = NoopFn,
} = props;
return (
<button
{...{onClick, type}}
className={classNames(
`inline-flex items-center border border-transparent font-medium rounded shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 justify-center`,
BUTTON_SIZE[size],
BUTTON_COLOR[use],
className,
)}>
{children}
</button>
);
};
You can use the @apply directive:
// do this in your CSS file
.my-btn {
@apply py-2 px-4 bg-green-500 text-white font-semibold rounded-lg shadow-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-opacity-75;
}
Then in your JSX code:
<button className="my-btn">Foo</button>
Also you can just create a simple component file:
// src/components/MyButton.jsx
const MyButton = ({ children }) => <button className="py-2 px-4 bg-green-500 text-white font-semibold rounded-lg shadow-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-opacity-75">{children}</button>
export default MyButton
In your App file:
import MyButton from './components/MyButton'
// ...
<MyButton>foo</MyButton>
<MyButton>bar</MyButton>
You'll need to modify MyButton if you want to pass other props too. Though, I'ld recommend using a CSS-in-JS library like styled-components or Emotion instead. There are Tailwind specific alternatives too that may interest you: twin.macro, Twind, xwind.
Simplest way - just store the classes in a string.
const myBtn = "py-2 px-4 bg-green-500 text-white font-semibold rounded-lg shadow-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-opacity-75"
// ...
<button className={`${myBtn} some-other-class-specific-to-foo`}>Foo</button>
<button className={myBtn}>Bar</button>
You can also use libraries like classnames and clsx for composing the strings.