Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

RFC: Compound Variants #8

Merged
merged 13 commits into from
Oct 24, 2022
Merged

RFC: Compound Variants #8

merged 13 commits into from
Oct 24, 2022

Conversation

vinpac
Copy link
Owner

@vinpac vinpac commented Oct 20, 2022

Overview

After thinking about #2 issue of conflicting classNames, I started thinking of a solution. I came across Compound Variants concept, but at first, it didn't look like it could solve this specific problem. I didn't want to add more classNames, I wanted to connect variants and have no conflicts. But how?

Problem

Sometimes classNames conflicts. Here's an example:

const Text = w.p('', {
  variants: {
    weight: {
      normal: 'font-normal',
      bold: 'font-bold'
    },
    size: {
      xl: 'text-8xl',
      base: 'text-base'
    },
    theme: {
      h1: 'text-8xl font-bold',
      p: 'text-base font-normal'
    },
  }
})

In the above example we could never have a working <Text theme="h1" weight="normal" /> as the evaluated className would be conflicting: text-8xl font-bold font-normal. It would depend on how the CSS was structured to know which rule would be applied. That's no good.

Solution

To solve that I'm adding compoundVariants, but a bit different from stiches' one.

const Text = w.p(``, {
  variants: {
    size: {
      base: 'text-base',
      xl: 'text-8xl',
    },
    weight: {
      normal: 'font-normal',
      bold: 'font-bold',
    },
    theme: {
      h1: '',
      base: '',
    },
  },
  defaultVariants: {
    variant: 'base',
    weight: 'normal',
    size: 'base',
  },
  compoundVariants: [
    {
      theme: 'h1',
      defaultTo: {
        size: 'xl',
        weight: 'bold',
      },
    },
    {
      theme: 'base',
      defaultTo: {
        size: 'base',
        weight: 'normal',
      },
    },
  ],
});

// Now we can use `theme` with no conflicts!
//
const Texts = <article>
  <Text theme="h1" /> {/* <p class="font-bold text-8xl" */}
  <Text theme="base" /> {/* <p class="text-8xl font-base"*/}
  <Text theme="h1" weight="normal" /> {/* <p class="font-normal text-8xl" */}
  <Text theme="h1" size="base" /> {/* <p class="text-base font-bold"*/}
</p>

The compoundVariants map tells us what to select and what to apply. It takes a combination of variants keys and values and special defaultTo and class properties.

Selection

Only 1 compound variant is selected at once. One case will override other if it is matched by more variants`

Example:

const compoundVariant1 = { theme: 'h1', class: 'color-red' };
const compoundVariant2 = {
  theme: 'h1',
  color: 'yellow',
  class: 'color-yellow',
};

For props { theme: 'h1', color: 'yellow' } the 2 will match, but only compoundVariant2 will be applied as it matches more variants. compoundVariant1 matches variant variant theme where compoundVariant2 matches theme and color.

The defaultTo updates the defaultVariants

For { defaultVariants: { weight: 'normal' } } a compoundedVariant containing { defaultTo: { weight: 'bold' } }, if matched, will override the weight default variant. This means that we can still set it, but the default is now updated for that custom selection.

The class appends classNames

A compounded variant with { class: 'xyz' } will add xyz to the evaluated classNames if matched.

@vercel
Copy link

vercel bot commented Oct 20, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
windstitch ✅ Ready (Inspect) Visit Preview Oct 24, 2022 at 4:54PM (UTC)

@github-actions
Copy link

github-actions bot commented Oct 20, 2022

size-limit report 📦

Path Size
dist/windstitch.cjs.production.min.js 1.48 KB (+9.85% 🔺)
dist/windstitch.esm.js 1.6 KB (+10.85% 🔺)

@vinpac vinpac changed the title RFC: Map Variants RFC: Compound Variants Oct 24, 2022
@vinpac vinpac merged commit f8ee401 into main Oct 24, 2022
@vinpac vinpac deleted the feature/map-variants branch October 24, 2022 16:57
@wmonecke
Copy link

wmonecke commented Apr 9, 2023

This feature is nice but still makes the user account for all different component states and props. I think adding a way to make windstitches aware of TW classes like tailwind-merge does, would make this package so much better. Is that something that would align with the vision of the project?

@vinpac
Copy link
Owner Author

vinpac commented Apr 9, 2023

@wmonecke how do you imagine that coming to life? I'm not very familiar with tailwind-merge

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants