drwpow / cobalt-ui

Use W3C Design Token Community Group tokens in CI and code

Home Page:https://cobalt-ui.pages.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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, and spacing this should generate?
    • E.g. transition?
  • 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?
  • 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 🙂.