Styled-system: Use pseudo-classing within `system`

Created on 24 Mar 2020  路  4Comments  路  Source: styled-system/styled-system

It would be nice to be able to use system to produce pseudo-classed styling. There are different ways you could do this, perhaps:

system({
  colorHover: { property: "color", scale: "colors", pseudo: "hover" },
  bgHover: { property: "backgroundColor", scale: "colors", pseudo: "hover" },
  borderColorHover: { property: "borderColor", scale: "colors", pseudo: "hover" }
})

(or perhaps using object or dot notation in the property properties)

becoming

&:hover {
  color: <colorHover prop>;
  background: <bgHover prop>;
  borderColor: <borderColorHover prop>;
}
enhancement

Most helpful comment

Thanks! An earlier version of Styled System had pseudo selector support, but it was dropped due to the complexity of the API and the fact that pseudo states rarely need to change dynamically based on props

All 4 comments

馃憤 Would be great if this could be supported inside the library, ideally with some kind of solution for React Native, etc, too (escape hatch or something). For now, I'm applying a transformation before the props reach styled-components. The hover is handled by React state/hooks, not by the CSS pseudo-selector, but this is what I'm doing for now:

const withStyles = (Component, fn) => (props) => {
  const styles = fn(props);

  const baseStyles = {};
  const pseudoStyles = {};

  for (const att in styles) {
    if (styles[att]) {
      const value = styles[att];

      if (att.startsWith(':')) {
        pseudoStyles[att.slice(1)] = value;
      } else {
        baseStyles[att] = value;
      }
    }
  }

  return (
    <Component {...baseStyles} styles={pseudoStyles} {...props} />
  );
};
const _Box = styled.div`
  ${spacing}
  ${color}
`;

// pseudoState can be idle, hover, focus, etc

const BaseBox = ({ styles, ...props }) => {
  const [pseudoState] = usePseudoState();

  const attributes = pseudoState !== 'idle' ? {
    ...(styles[pseudoState])
  } : {};

  return (
    <_Box {...props} {...attributes} />
  );
};

const Box = withStyles(BaseBox, () => ({
  bg: 'green',
  '&:hover': {
    bg: 'greens.7',
  },
}));

I mainly use Styled System for atomic styling, similar to Tailwindcss, and I wonder if it would be viable to extend the library to accept objects like so:

<Box
  bg={{ _: 'red', hover: 'green' }}
> 
<Box
  bg={[{ _: 'red', hover: 'green' }, { _: 'green', hover: 'red' , focus: 'blue' }]}
> 

@jxnblk What are your thoughts on this feature? I think it's worth noting that prevalent styled-system users, like Chakra, create their own solution for supporting pseudo-selectors, and it would be nice if it were built-in, too.

Chakra's PseudoBox, that adds pseudo selector props. And its source

EDIT: I'd be interested in opening a PR to add this feature, just curious if any of the above solutions, or another solution, would be the most likely to get merged.

Thanks! An earlier version of Styled System had pseudo selector support, but it was dropped due to the complexity of the API and the fact that pseudo states rarely need to change dynamically based on props

Was this page helpful?
0 / 5 - 0 ratings