I'm curious what sorts of workflows you might have developed for dealing with oodles and oodles of classes on a single element, often amongst many others within a single component.
I figured I'd share what I currently do, and maybe others can show me how they'd do it differently. Or maybe I can at least inspire someone else with my examples:
import { ComponentProps, useState } from 'react'
import { twMerge } from 'tailwind-merge'
// A TypeScript template literal tag function for Tailwind classes
// Usually imported from a folder of other utilities
function tw(strings: TemplateStringsArray, ...values: any[]) {
return String.raw({ raw: strings }, ...values)
}
// Sometimes this is exported from a file of its own if things get hairy
// For even simpler components, this wouldn't even be a function
// and instead I'd just have the object itself, named `classNames` or something
function getClassNames({ someCondition = false }) {
return {
container: twMerge(
someCondition &&
`
bg-red-400
text-red-600
`,
`
flex
h-full
flex-col
items-center
justify-center
`,
),
someSemanticallyNamedElement: tw`
text-lg
`,
}
}
// Most of my components still accept a className prop,
// so I merge it with the lovely `tailwind-merge` library
export function MyComponent({
className,
...otherProps
}: ComponentProps<'div'>) {
const [someCondition, setSomeCondition] = useState(false)
const classes = getClassNames({ someCondition })
return (
<div
// ⛙ Merge the classes. The incoming classes take precedence
// but sometimes I pass them first if I need to ensure
// specific classes can't be overridden
className={twMerge(classes.container, className)}
{...otherProps}
>
<div className={classes.someSemanticallyNamedElement}>Hello, world!</div>
</div>
)
}
Top comments (0)