Overview
1. Define styling tools
import { createTools, type Tailwindest } from "tailwindest"
/**
* Custom type definition of tailwindest
* @see {@link https://tailwindest.vercel.app/apis/Tailwindest api reference}
*/
type TailwindCustom = Tailwindest<{}, {}>
/**
* Full type definition of `tailwindcss`
*/
type Tailwind = Required<TailwindCustom>
const tw = createTools<TailwindCustom>()
export { tw, type Tailwind }
2. Styling tools
A. Define style - style
// Define style sheet
const box = tw.style({
display: "flex",
alignItems: "items-center",
justifyContent: "justify-center",
paddingX: "px-[2.25px]",
paddingY: "py-1",
borderColor: "border-transparent",
borderBottomWidth: "border-b",
backgroundColor: "bg-transparent",
transition: "transition",
transitionDuration: "duration-75",
":hover": {
opacity: "hover:opacity-90",
},
})
// Use it in component
const Box = ({ children }) => <div className={box.class}>{children}</div>
B. Conditional styling - toggle
If you want to change the style based on a single boolean
condition, use toggle
.
// Define toggle style
const themeBtn = tw.toggle({
truthy: {}, // 🌝 light mode
falsy: {}, // 🌚 dark mode
base: {}, // [optional] base style
})
// Use it in component
const ThemeBtn = ({ children }) => {
const [isLight, setIsLight] = useState(false)
return <button className={themeBtn.class(isLight)}>{children}</button>
}
C. Conditional styling - rotary
If you need to change styles based on three or more conditions within a single category, use rotary
.
// Define rotary style
const btn = tw.rotary({
default: {},
success: {},
warning: {},
base: {}, // [optional] base style
})
// Get rotary type with GetVariants
interface BtnProps {
onClick: () => void
children: ReactNode
type?: GetVariants<typeof btn>
}
// Use it in component
const Btn = ({ onClick, children, type = "default" }: BtnProps) => (
<button className={btn.class(type)} onClick={onClick}>
{children}
</button>
)
D. Conditional styling - variants
Use variants
for combinations of rotary, where each style condition is defined within several categories.
// Define variants style
const btn = tw.variants({
variants: {
type: {
default: {},
success: {},
warning: {},
},
size: {
sm: {},
md: {},
lg: {},
},
},
base: {}, // [optional] base style
})
// Get variants type with GetVariants
interface BtnProps extends GetVariants<typeof btn> {
onClick: () => void
children: ReactNode
}
// Use it in component
const Btn = ({
children,
size = "md",
type = "default",
onClick,
}: BtnProps) => (
<button className={btn.class({ size, type })} onClick={onClick}>
{children}
</button>
)
E. Utility - mergeProps
Use it for merging input styleSheet
.
- define base style
const text = tw.style({
color: "text-gray-950",
fontWeight: "font-bold",
fontSize: "text-base/normal",
"@dark": {
color: "dark:text-gray-100",
},
})
- case A: add specific prop
const SpecificPropsText = ({
children,
...option
}: PropsWithChildren<{
color?: Tailwindest["color"]
fontWeight?: Tailwindest["fontWeight"]
}>) => (
<p
className={tw.mergeProps(
text.style,
option // override color and fontWeight
)}
>
{children}
</p>
)
const Some = () => (
<SpecificPropsText color="text-amber-300" fontWeight="font-bolder">
It is SpecificPropsText
</SpecificPropsText>
)
- case B: add styleSheet as props
interface UniversalTextProps {
children: React.ReactNode
tw?: Tailwindest
}
const UniversalText = ({ children, tw }: UniversalTextProps) => (
<p
className={tw.mergeProps(
text.style,
tw // override new styleSheet
)}
>
{children}
</p>
)
const Some = (
<UniversalText
tw={{
fontFamily: "font-mono",
}}
>
It is UniversalText
</UniversalText>
)