Group Selector

Group selectors allow child elements to respond to interactions on a parent element. This is useful for creating interactive cards, list items, and other composite components.

Basic Usage

Add role="group" to a parent element, then use _groupHover, _groupFocus, or _groupActive on children:

1<Box bg="$background" borderRadius="8px" p={4} role="group">
2  <Text _groupHover={{ color: '$primary' }}>
3    This text changes color when parent is hovered
4  </Text>
5  <Box _groupHover={{ bg: '$primaryAlpha10' }} p={2}>
6    This box changes background on parent hover
7  </Box>
8</Box>
1<Box bg="$background" borderRadius="8px" p={4} role="group">
2  <Text _groupHover={{ color: '$primary' }}>
3    This text changes color when parent is hovered
4  </Text>
5  <Box _groupHover={{ bg: '$primaryAlpha10' }} p={2}>
6    This box changes background on parent hover
7  </Box>
8</Box>

Available Group Selectors

SelectorTriggered when
_groupHover

Parent with role="group" is hovered

_groupFocus

Parent with role="group" is focused

_groupActive

Parent with role="group" is active (pressed)

_groupFocusWithinAny element inside the group receives focus

Interactive Card Example

1<Box
2  _hover={{ boxShadow: '0 4px 12px rgba(0,0,0,0.15)' }}
3  bg="white"
4  borderRadius="8px"
5  boxShadow="0 1px 3px rgba(0,0,0,0.1)"
6  cursor="pointer"
7  p={4}
8  role="group"
9>
10  <Box
11    bg="$backgroundMuted"
12    borderRadius="4px"
13    h="200px"
14    overflow="hidden"
15    w="100%"
16  >
17    <Image
18      _groupHover={{ transform: 'scale(1.05)' }}
19      src="/image.jpg"
20      transition="transform 0.2s"
21    />
22  </Box>
23
24  <Text _groupHover={{ color: '$primary' }} fontWeight={600} mt={3}>
25    Card Title
26  </Text>
27
28  <Text color="$textMuted" fontSize="14px">
29    Card description goes here
30  </Text>
31
32  <Box
33    _groupHover={{ opacity: 1 }}
34    mt={3}
35    opacity={0}
36    transition="opacity 0.2s"
37  >
38    <Button>View Details</Button>
39  </Box>
40</Box>
1<Box
2  _hover={{ boxShadow: '0 4px 12px rgba(0,0,0,0.15)' }}
3  bg="white"
4  borderRadius="8px"
5  boxShadow="0 1px 3px rgba(0,0,0,0.1)"
6  cursor="pointer"
7  p={4}
8  role="group"
9>
10  <Box
11    bg="$backgroundMuted"
12    borderRadius="4px"
13    h="200px"
14    overflow="hidden"
15    w="100%"
16  >
17    <Image
18      _groupHover={{ transform: 'scale(1.05)' }}
19      src="/image.jpg"
20      transition="transform 0.2s"
21    />
22  </Box>
23
24  <Text _groupHover={{ color: '$primary' }} fontWeight={600} mt={3}>
25    Card Title
26  </Text>
27
28  <Text color="$textMuted" fontSize="14px">
29    Card description goes here
30  </Text>
31
32  <Box
33    _groupHover={{ opacity: 1 }}
34    mt={3}
35    opacity={0}
36    transition="opacity 0.2s"
37  >
38    <Button>View Details</Button>
39  </Box>
40</Box>

List Item Example

1<Box as="ul" listStyle="none" m={0} p={0}>
2  {items.map((item) => (
3    <Box
4      key={item.id}
5      _hover={{ bg: '$backgroundMuted' }}
6      as="li"
7      borderBottom="1px solid $border"
8      p={3}
9      role="group"
10    >
11      <Flex align="center" justify="space-between">
12        <Text _groupHover={{ color: '$primary' }}>{item.title}</Text>
13        <Box _groupHover={{ opacity: 1 }} opacity={0}>
14          <Button size="sm">Edit</Button>
15        </Box>
16      </Flex>
17    </Box>
18  ))}
19</Box>
1<Box as="ul" listStyle="none" m={0} p={0}>
2  {items.map((item) => (
3    <Box
4      key={item.id}
5      _hover={{ bg: '$backgroundMuted' }}
6      as="li"
7      borderBottom="1px solid $border"
8      p={3}
9      role="group"
10    >
11      <Flex align="center" justify="space-between">
12        <Text _groupHover={{ color: '$primary' }}>{item.title}</Text>
13        <Box _groupHover={{ opacity: 1 }} opacity={0}>
14          <Button size="sm">Edit</Button>
15        </Box>
16      </Flex>
17    </Box>
18  ))}
19</Box>

Navigation Menu Example

1<Box as="nav">
2  <Box
3    _hover={{ bg: '$backgroundMuted' }}
4    borderRadius="4px"
5    p={2}
6    role="group"
7  >
8    <Flex align="center" gap={2}>
9      <Box
10        _groupHover={{ bg: '$primary' }}
11        bg="$textMuted"
12        borderRadius="50%"
13        h="8px"
14        w="8px"
15      />
16      <Text _groupHover={{ color: '$primary' }}>Menu Item</Text>
17      <Box _groupHover={{ opacity: 1 }} ml="auto" opacity={0}>
1819      </Box>
20    </Flex>
21  </Box>
22</Box>
1<Box as="nav">
2  <Box
3    _hover={{ bg: '$backgroundMuted' }}
4    borderRadius="4px"
5    p={2}
6    role="group"
7  >
8    <Flex align="center" gap={2}>
9      <Box
10        _groupHover={{ bg: '$primary' }}
11        bg="$textMuted"
12        borderRadius="50%"
13        h="8px"
14        w="8px"
15      />
16      <Text _groupHover={{ color: '$primary' }}>Menu Item</Text>
17      <Box _groupHover={{ opacity: 1 }} ml="auto" opacity={0}>
1819      </Box>
20    </Flex>
21  </Box>
22</Box>

Combining with Responsive Styles

Group selectors can be combined with responsive arrays:

1<Box p={[2, null, 4]} role="group">
2  <Text
3    _groupHover={{
4      color: ['$primary', null, '$secondary'],
5      fontSize: ['16px', null, '18px'],
6    }}
7  >
8    Responsive group hover
9  </Text>
10</Box>
1<Box p={[2, null, 4]} role="group">
2  <Text
3    _groupHover={{
4      color: ['$primary', null, '$secondary'],
5      fontSize: ['16px', null, '18px'],
6    }}
7  >
8    Responsive group hover
9  </Text>
10</Box>

Nested Groups

For nested groups, the selector applies to the nearest parent with role="group":

1<Box bg="white" p={4} role="group">
2  <Text _groupHover={{ color: 'blue' }}>Responds to outer group</Text>
3
4  <Box bg="$backgroundMuted" mt={2} p={2} role="group">
5    <Text _groupHover={{ color: 'red' }}>Responds to inner group</Text>
6  </Box>
7</Box>
1<Box bg="white" p={4} role="group">
2  <Text _groupHover={{ color: 'blue' }}>Responds to outer group</Text>
3
4  <Box bg="$backgroundMuted" mt={2} p={2} role="group">
5    <Text _groupHover={{ color: 'red' }}>Responds to inner group</Text>
6  </Box>
7</Box>

CSS Output

1<Box role="group">
2  <Box _groupHover={{ bg: 'red' }} />
3</Box>
1<Box role="group">
2  <Box _groupHover={{ bg: 'red' }} />
3</Box>

Generates CSS like:

1[role='group']:hover .a {
2  background-color: red;
3}
1[role='group']:hover .a {
2  background-color: red;
3}

Best Practices

  1. Use semantic HTML: Add role="group" to semantically appropriate elements
  2. Keep interactions discoverable: Don't hide critical content behind group hover
  3. Consider touch devices: Group hover doesn't work on touch - provide alternative interactions
  4. Use transitions: Add transition prop for smooth state changes
  5. Accessibility: Ensure interactive elements are keyboard accessible