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

[FEATURE] add dynamic modifiers functionality #43

Closed andrewtpoe closed 7 months ago

andrewtpoe commented 4 years ago

EXPECTED BEHAVIOR

What's the behavior you're expecting to see?

The current API for styled-components-modifiers requires a configuration object with a pre-defined mapping of modifier styles. Sometimes though, the modifiers styles could be just as easily calculated at runtime with a simple function. A good example of this is any time you have a style modification done where the modifier name is essentially a multiplier for a single or set of values. With the current API, you must handle that by creating a configuration object for every value or apply the modifiers directly to the styled component.

Why put this in styled-components-modifiers?

Responsiveness. applyStyleModifiers is a flexible tool that lets you select one or more modifiers based on the value of a size prop. The logic that makes this prop selection is tricky, and definitely not something that should be repeated unless necessary. If you apply a dynamic or calculated modifier directly to a styled component, you lose that responsive logic.

ACTUAL BEHAVIOR

What's actually happening instead?

There is no tool in styled-components-modifiers like the one suggested.

SUGGESTED SOLUTION

Do you have any feedback on how this problem should be solved?

I see two viable options for adding this functionality:

  1. Create a new utility called applyDynamicModifier.
    • This utility would accept the following arguments:
    • dynamicModifierFunc: A function very similar to the ModifierConfigValue type currently present. It accepts the component props and returns a SimpleInterpolation.
    • customModifierPropName: the name of the prop where the modifier values will be provided.
    • customBreakpointPropName: the name of the prop used to determine which responsive modifier value should be used.
    • Create a new propType validator for dynamic proptypes that can accept an array of valid values, or a proptype validator (say any string is valid, just give it PropTypes.string).
  2. Enhance the existing applyStyleModifier utility to accept a function or a modifier config object as the first argument.
    • Enhance styleModifierPropTypes as described above.

NOTE: With either approach, we could perhaps enable a typescript override as well to make the function optional. If omitted, the modifier prop name will be used as the CSS attribute name for the supplied value. Essentially, the prop would become passthrough CSS attrs. height="10px" -> { height: 10px; }.

I have a preference toward the second option, but have also already built most of the functionality for the first option current applications I'm working on. My concern with the second approach is overburdening that single function to do so much it becomes confusing.