I've used Tailwind extensively at previous companies and inevitably each one creates an abstraction that's akin to:<p><pre><code> const headerClasses = [(list of Tailwind classes here)];
<header className={...headerClasses}>...</header>
</code></pre>
because the complexity of reading and writing all of the classes is just too much. At that point, you've just reinvented CSS classes. Tailwind fans will tell you to not do this but if multiple companies are independently having the same problem and coming up with the same solution, the onus is not on the user anymore, it's on the creator to fix it. @apply can work but again it's really not recommended by Tailwind itself, for whatever reason.<p>These days I recommend learning CSS really well and then using Vanilla Extract (<a href="https://vanilla-extract.style" rel="nofollow">https://vanilla-extract.style</a>), a CSS in TypeScript library that compiles down to raw CSS, basically using TS as your preprocessor instead of SCSS. For dynamic styles, they have an optional small runtime.<p>They have a Stitches-like API called Recipes that's phenomenal as well, especially for design systems, you can define your variants and what CSS needs to be applied for each one, so you can map your design components 1-to-1 with your code:<p>import { recipe } from '@vanilla-extract/recipes';<p>export const button = recipe({
base: {
borderRadius: 6
},<p><pre><code> variants: {
color: {
neutral: { background: 'whitesmoke' },
brand: { background: 'blueviolet' },
accent: { background: 'slateblue' }
},
size: {
small: { padding: 12 },
medium: { padding: 16 },
large: { padding: 24 }
},
rounded: {
true: { borderRadius: 999 }
}
},
// Applied when multiple variants are set at once
compoundVariants: [
{
variants: {
color: 'neutral',
size: 'large'
},
style: {
background: 'ghostwhite'
}
}
],
defaultVariants: {
color: 'accent',
size: 'medium'
}</code></pre>
});<p>Impressive that OP still is using ReasonReact, I thought it was all but dead after ReScript.