styled-components / xstyled

A utility-first CSS-in-JS framework built for React. 💅👩‍🎤⚡️
https://xstyled.dev
MIT License
2.27k stars 106 forks source link

Add "group" utility #305

Closed AlfonzAlfonz closed 2 years ago

AlfonzAlfonz commented 3 years ago

🚀 Feature Proposal

Currently xstyled misses a way to style an element that depends on the state of some of its parents. This proposal attempts to solve this issue by adding a "group" utility prop and "group" states. Group utility marks an element that its children may depend on its state. Individual elements then can use group states to add styles.

Motivation

Provide a simple way to style elements controlled by the state of a parent element.

Example

The most common use case I can think of is a text inside of a button.

<x.button
  display="flex"
  alignItems="center"
  p={4}
  color="white"
  bg={{ _: "light-blue-600", hover: "light-blue-700" }}
  group
>
  <x.span pr={1} color={{ _: "white", groupHover: "light-blue-100" }}>
    <Check size={16} />
  </x.span>
  <x.span color={{ _: "white", groupHover: "light-blue-100" }}>
    Approve
  </x.span>
</x.button>

<x.div position="relative" w="100px" h="100px" group>
  <x.img src="http://placekitten.com/100/100" />
  <x.div
    position="absolute"
    display={{ _: "none", hover: "flex" }}
    top="0"
    left="0"
    right="0"
    bottom="0"
    alignItems="center"
    justifyContent="center"
    color="white"
    fontWeight="bold"
    bg="gray-800-a50"
  >
    <x.span>A cat</x.span>
  </x.div>
</x.div>

Gray overlay over an image.

<x.div position="relative" w="100px" h="100px" group>
  <x.img src="http://placekitten.com/100/100" />
  <x.div
    position="absolute"
    display={{ _: "none", groupHover: "flex" }}
    top="0"
    left="0"
    right="0"
    bottom="0"
    alignItems="center"
    justifyContent="center"
    color="white"
    fontWeight="bold"
    bg="gray-800-a50"
  >
    <x.span>A cat</x.span>
  </x.div>
</x.div>

Pitch

Right now xstyled is missing this feature and currently, there's no workaround, which supports all usecases. Other similar libraries also have this feature. For example Tailwind or Chakra.

gregberge commented 2 years ago

Hello @AlfonzAlfonz, it is not built-in but you can easily achieve it by customising states:

const theme = {
  ...defaultTheme,
  states: {
    ...defaultTheme.states,
    groupHover: '.group:hover &'
  },
}

<div className="group">
   <x.div display={{ _: "none", groupHover: "flex" }} />
</div>