Write tailwind with confidence 🦾
- Type-safe
tailwind
- Provide full type definition of
tailwind
properties - Solid conditional styling, inspired by
cva
Useful features 🔮
- Support all JS-frameworks
- Zero dependencies
768B
, tiny bundle size- Support custom type, defined in
tailwind.config.js
tailwind
doc site link embedded viaJSDoc
Start with docs 📖
Overview 🚀
0. Install package
npm i tailwindest
1. Define styling tools
import { createTools, type Tailwindest } from "tailwindest"
// name it whatever you want
export const tw = createTools<Tailwindest>()
2. Use styling tools
A. Basic style
Define basic style sheet with style
.
const box = tw.style({
display: "flex",
alignItems: "items-center",
justifyContent: "justify-center",
paddingX: "px-[2.25px]",
paddingY: "py-1",
":hover": {
opacity: "hover:opacity-90",
},
"@sm": {
paddingX: "sm:px-[4.5px]",
paddingY: "sm:py-2",
},
})
const Box = ({ children }) => <div className={box.class}>{children}</div>
B. Toggling
If you want to change the style based on a single boolean
condition, use toggle
.
const themeBtn = tw.toggle({
truthy: {}, // 🌝 light mode
falsy: {}, // 🌚 dark mode
base: {}, // [optional] base style
})
const ThemeBtn = ({ children }) => {
const [isLight, setIsLight] = useState(false)
return <button className={themeBtn.class(isLight)}>{children}</button>
}
C. Various conditions
If you need to change styles based on three or more conditions within a single category, use rotary
.
import { type GetVariants } from "tailwindest"
const btn = tw.rotary({
default: {},
success: {},
warning: {},
base: {}, // [optional] base style
})
interface BtnProps {
onClick: () => void
children: ReactNode
type?: GetVariants<typeof btn>
}
const Btn = ({ onClick, children, type = "default" }: BtnProps) => (
<button className={btn.class(type)} onClick={onClick}>
{children}
</button>
)
Variants
D.const btn = tw.variants({
variants: {
type: {
default: {},
success: {},
warning: {},
},
size: {
sm: {},
md: {},
lg: {},
},
border: {
true: {},
false: {},
},
},
base: {}, // [optional] base style
})
interface BtnProps extends GetVariants<typeof btn> {
onClick: () => void
children: ReactNode
}
const Btn = ({
children,
size = "md",
type = "default",
border = true,
onClick,
}: BtnProps) => (
<button className={btn.class({ size, type, border })} onClick={onClick}>
{children}
</button>
)
E. Merging styles
Use mergeProps
to merge multiple styles and make prop-injectable universal components.
const text = tw.style({
// text base style
})
interface TextProps {
color?: Tailwindest["color"]
fontWeight?: Tailwindest["fontWeight"]
}
export const UniversalText = ({
children,
...textOptions
}: React.PropsWithChildren<TextProps>) => (
<p
className={tw.mergeProps(
text.style,
textOptions
// override color and fontWeight
)}
>
{children}
</p>
)
const SomeComponent = () => (
<>
<UniversalText color="text-red-100" fontWeight="font-medium">
color: red-100 & fontWeight: font-medium
</UniversalText>
<UniversalText color="text-blue-300" fontWeight="font-bold">
color: blue-300 & fontWeight: font-bold
</UniversalText>
</>
)
LICENSE 👻
MIT