Proposal: utility CSS generated by plugin-css
drwpow opened this issue · comments
Proposal
I’ve been thinking about #65 and the idea to have a Tailwind plugin, or at least a Tailwind-compatible plugin. While I think that’s probably not in the cards (I believe Tailwind is its own design system, and though you can configure it to a degree, it ultimately does impose assumptions on your DS that restrict it), I do think there’s some middle ground where we could generate Tailwind-like CSS based on your tokens.
For example, given the following tokens:
space:
$type: dimension
s:
$value: 0.25rem
m:
$value: 0.5rem
l:
$value: 1rem
You could produce the following CSS:
.mt-0 {
margin-top: 0;
}
.mt-s {
margin-top: var(--space-s);
}
.mt-m {
margin-top: var(--space-m);
}
.mt-l {
margin-top: var(--space-l);
}
/* (and so on …) */
Configuration
But the question is… how? Well, one approach could be a semi-opinionated approach that borrows words from Tailwind, and applies them in the config:
import pluginCSS from '@cobalt-ui/plugin-css';
export default {
plugins: [
pluginCSS({
utilityCSS: {
color: {
blue: 'color.core.blue',
link: 'color.semantic.link',
error: 'color.semantic.error',
},
spacing: {
s: 'space.s',
m: 'space.m',
l: 'space.l',
},
// …
}
}),
],
}
In other words, the top-level keys color
and spacing
are reserved (color
would yield .bg-*
and .text-*
utility classes, and spacing
would yield .m-*
and .p-*
utility classes).
The mapping here is a bit theoretical, but if you provided a token, it would generate a direct class, e.g. .text-error
. But if you provided a group of colors, it would produce multiple classes joined by hyphens, e.g. .text-blue-100
.
Alternative config
We could take a more automatic approach, and just have you specify globs of token groups like so:
import pluginCSS from '@cobalt-ui/plugin-css';
export default {
plugins: [
pluginCSS({
utilityCSS: {
color: ['color.core.*', 'color.semantic.*'],
spacing: ['space.*'],
}
}),
],
}
While this may not allow as much fine-tuned control over generated CSS, it would be much easier to set up.
Note that whichever API we go with (even possibly secret option C), I do somewhat like some level of “manual” specification because it would prevent generating a wasteful amount of CSS (Tailwind’s problem, unless you use treeshaking).
Questions
- Are there other Tailwind-ish words other than
color
,border
, andspacing
this should generate?- E.g.
transition
?
- E.g.
- Is there a better configuration API than either proposal?
- For example, Tailwind uses numbers for spacing, e.g.
.mt-2
, however, your design system may not use that convention. What would be a good way to describe that mapping?
- For example, Tailwind uses numbers for spacing, e.g.
- Is
utilityCSS
the right top-level term for this?
Update: I may retract my beginning statement of this not being compatible with Tailwind; perhaps a better approach is to simply customize Tailwind as much as it will allow, as this example shows. That would be preferable than trying to create + document some custom thing.
After giving it a bit more thought, I’m going to add both. I can see a utility CSS approach being useful for folks not using Tailwind (purely opt-in). But also I recognize that Tailwind users want to use the tools they have, and I think a Tailwind plugin is necessary for them.
I believe the Tailwind plugin will be its own package for easiest consumption.
Can you assign this to me!
@Mstanic05 thanks for being willing! But I’m going to add this as the API / requirements aren’t clear. But happy to ping you for a review to give your feedback & input when the PR is up 🙂.