WANTED: VSCode and/or Prettier plugin to ease the suffering of editing`class` attributes in a Tailwind project

RMAG news

If the title of this post speaks to you, 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>
)
}