Decisiv / styled-components-modifiers

A library to enable BEM flavored modifiers (and responsive modifiers) in styled components.
MIT License
298 stars 11 forks source link

Enhance `modifiers` prop #31

Closed jpbelo closed 4 years ago

jpbelo commented 5 years ago

EXPECTED BEHAVIOR

More consistency on the modifiers prop.

SUGGESTED SOLUTION

An approach similar to https://github.com/JedWatson/classnames would work great for using both conditions and sizes in one format.

The key would be the modifier name, and the value would be the condition. We could have a reserved word, like size, so this would be possible:

<Button
  modifiers={{
    default: size.all,                  // applies to all "other" sizes (medium in this case)
    small: size.isSmall,                // applies to small
    intermediate: size.isBig || size.isBiggest,     // applies to big and biggest
    hover: this.state.isHover,              // uses hover if this.state.isHover is true
    primary: !hasModifier('secondary') &&  hasModifier('primary'),
    secondary: hasModifier('secondary'),
  }}
/>

// usage
<Button modifiers="secondary">Test</Button>
<Button modifiers={["secondary"]}>Test</Button>
<Button modifiers={{secondary:true}}>Test</Button>

// also replacing this
modifiers={['large', isLoading && 'loading']}
// with this
modifiers={{ large: true, loading: isLoading }}

sorry if the suggestion is too messy. I can edit if it's not clear.

andrewtpoe commented 4 years ago

Currently, the modifiers prop already accepts an object. This is what triggers the responsive logic within the modifiers. This tool will look for a size prop, then attempt to match that with a key in the modifiers object. I don't think the current behavior would be compatible with this proposal.

There is one other alternative that I make use of regularly. applyStyleModifiers takes a second argument for the prop name. See here.

With this technique you could do something like this:

const variantModifiers = {
  primary: () => css`/* ... */`;
  secondary: () => css`/* ... */`;
}

const Button = styled.button`
  ${applyStyleModifiers(variantModifiers, 'variant')}
`

<Button variant="secondary">Test</Button>

I'm not sure if that helps your use case or not, but I find it very valuable.