Skip to content

Commit b0d61a2

Browse files
committed
Update role group
1 parent 5806b1f commit b0d61a2

21 files changed

Lines changed: 200 additions & 102 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"changes":{"bindings/devup-ui-wasm/package.json":"Patch","packages/components/package.json":"Patch","packages/react/package.json":"Patch","packages/vite-plugin/package.json":"Patch","packages/next-plugin/package.json":"Patch","packages/webpack-plugin/package.json":"Patch","packages/rsbuild-plugin/package.json":"Patch","packages/bun-plugin/package.json":"Patch","packages/plugin-utils/package.json":"Patch"},"note":"Migrate group selector to data-group attribute. The compiler now emits a single :is([role=group],[data-group]):<pseudo> & selector for _groupHover/_groupFocus/_groupActive/_groupDisabled and the Tailwind group-* variants, so existing role=\"group\" markup keeps working alongside the new data-group form. role=\"group\" matching is deprecated and will be removed in v2 — migrate to data-group. The bundled Toggle component now uses data-group.","date":"2026-05-25T00:00:00.000000000Z"}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ test-results
2222
playwright-report
2323
.omc
2424
.playwright-mcp
25+
.omo

SKILL.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,22 @@ All CSS pseudo-classes and pseudo-elements from `csstype` are supported with `_c
180180

181181
### Group Selectors
182182

183-
Style children based on parent state:
183+
Mark a parent with the `data-group` attribute, then children can react to that parent's state:
184184

185185
```tsx
186-
<Box _groupHover={{ color: "blue" }} />
187-
<Box _groupFocus={{ outline: "2px solid" }} />
188-
<Box _groupActive={{ bg: "darkblue" }} />
186+
<Box data-group>
187+
<Text _groupHover={{ color: "blue" }}>Changes when parent hovered</Text>
188+
<Box _groupFocus={{ outline: "2px solid" }} />
189+
<Box _groupActive={{ bg: "darkblue" }} />
190+
</Box>
189191
```
190192

193+
Available: `_groupHover`, `_groupFocus`, `_groupActive`, `_groupDisabled`.
194+
195+
> The legacy `role="group"` parent marker is still matched for backward
196+
> compatibility but will be removed in v2. Use `data-group` for new code so
197+
> `role="group"` stays reserved for genuine ARIA grouping semantics.
198+
191199
### Theme Selectors
192200

193201
```tsx

apps/landing/src/app/(detail)/docs/RightIndex.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ function IndexMenu({
1919
<Flex
2020
alignItems="center"
2121
cursor="pointer"
22+
data-group
2223
gap="10px"
2324
onClick={onClick}
2425
p={sub ? '4px 10px 4px 30px' : '4px 10px'}
25-
role="group"
2626
>
2727
{selected && <Box bg="$primary" borderRadius="50%" boxSize="6px" />}
2828
<Text
@@ -116,8 +116,8 @@ export function RightIndex() {
116116
textDecorationColor: '$text',
117117
},
118118
})}
119+
data-group
119120
href={editUrl}
120-
role="group"
121121
target="_blank"
122122
>
123123
<Flex gap="4px">

apps/landing/src/app/(detail)/docs/api/group-selector/page.mdx

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ Group selectors allow child elements to respond to interactions on a parent elem
2020

2121
## Basic Usage
2222

23-
Add `role="group"` to a parent element, then use `_groupHover`, `_groupFocus`, or `_groupActive` on children:
23+
Add the `data-group` attribute to a parent element, then use `_groupHover`, `_groupFocus`, or `_groupActive` on children:
2424

2525
```tsx
26-
<Box bg="$background" borderRadius="8px" p={4} role="group">
26+
<Box bg="$background" borderRadius="8px" data-group p={4}>
2727
<Text _groupHover={{ color: '$primary' }}>
2828
This text changes color when parent is hovered
2929
</Text>
@@ -33,6 +33,13 @@ Add `role="group"` to a parent element, then use `_groupHover`, `_groupFocus`, o
3333
</Box>
3434
```
3535

36+
> **Migrating from `role="group"`**: previous versions used `role="group"` to mark
37+
> group parents. Both forms are supported today, but `role="group"` carries ARIA
38+
> semantics that should be reserved for actual semantic groups (e.g. a `<fieldset>`
39+
> replacement), not for styling hooks. Prefer `data-group` going forward. The
40+
> `role="group"` form will be removed in v2 — see the
41+
> [CHANGELOG](https://github.com/dev-five-git/devup-ui/blob/main/CHANGELOG.md).
42+
3643
## Available Group Selectors
3744

3845
<Table>
@@ -48,23 +55,23 @@ Add `role="group"` to a parent element, then use `_groupHover`, `_groupFocus`, o
4855
<code>_groupHover</code>
4956
</TableCell>
5057
<TableCell>
51-
Parent with <code>role=&quot;group&quot;</code> is hovered
58+
Parent with <code>data-group</code> is hovered
5259
</TableCell>
5360
</TableRow>
5461
<TableRow>
5562
<TableCell>
5663
<code>_groupFocus</code>
5764
</TableCell>
5865
<TableCell>
59-
Parent with <code>role=&quot;group&quot;</code> is focused
66+
Parent with <code>data-group</code> is focused
6067
</TableCell>
6168
</TableRow>
6269
<TableRow>
6370
<TableCell>
6471
<code>_groupActive</code>
6572
</TableCell>
6673
<TableCell>
67-
Parent with <code>role=&quot;group&quot;</code> is active (pressed)
74+
Parent with <code>data-group</code> is active (pressed)
6875
</TableCell>
6976
</TableRow>
7077
<TableRow>
@@ -85,8 +92,8 @@ Add `role="group"` to a parent element, then use `_groupHover`, `_groupFocus`, o
8592
borderRadius="8px"
8693
boxShadow="0 1px 3px rgba(0,0,0,0.1)"
8794
cursor="pointer"
95+
data-group
8896
p={4}
89-
role="group"
9097
>
9198
<Box
9299
bg="$backgroundMuted"
@@ -131,8 +138,8 @@ Add `role="group"` to a parent element, then use `_groupHover`, `_groupFocus`, o
131138
_hover={{ bg: '$backgroundMuted' }}
132139
as="li"
133140
borderBottom="1px solid $border"
141+
data-group
134142
p={3}
135-
role="group"
136143
>
137144
<Flex align="center" justify="space-between">
138145
<Text _groupHover={{ color: '$primary' }}>{item.title}</Text>
@@ -149,12 +156,7 @@ Add `role="group"` to a parent element, then use `_groupHover`, `_groupFocus`, o
149156

150157
```tsx
151158
<Box as="nav">
152-
<Box
153-
_hover={{ bg: '$backgroundMuted' }}
154-
borderRadius="4px"
155-
p={2}
156-
role="group"
157-
>
159+
<Box _hover={{ bg: '$backgroundMuted' }} borderRadius="4px" data-group p={2}>
158160
<Flex align="center" gap={2}>
159161
<Box
160162
_groupHover={{ bg: '$primary' }}
@@ -177,7 +179,7 @@ Add `role="group"` to a parent element, then use `_groupHover`, `_groupFocus`, o
177179
Group selectors can be combined with responsive arrays:
178180

179181
```tsx
180-
<Box p={[2, null, 4]} role="group">
182+
<Box data-group p={[2, null, 4]}>
181183
<Text
182184
_groupHover={{
183185
color: ['$primary', null, '$secondary'],
@@ -191,13 +193,13 @@ Group selectors can be combined with responsive arrays:
191193

192194
## Nested Groups
193195

194-
For nested groups, the selector applies to the nearest parent with `role="group"`:
196+
For nested groups, the selector applies to the nearest parent with `data-group`:
195197

196198
```tsx
197-
<Box bg="white" p={4} role="group">
199+
<Box bg="white" data-group p={4}>
198200
<Text _groupHover={{ color: 'blue' }}>Responds to outer group</Text>
199201

200-
<Box bg="$backgroundMuted" mt={2} p={2} role="group">
202+
<Box bg="$backgroundMuted" data-group mt={2} p={2}>
201203
<Text _groupHover={{ color: 'red' }}>Responds to inner group</Text>
202204
</Box>
203205
</Box>
@@ -206,23 +208,29 @@ For nested groups, the selector applies to the nearest parent with `role="group"
206208
## CSS Output
207209

208210
```tsx
209-
<Box role="group">
211+
<Box data-group>
210212
<Box _groupHover={{ bg: 'red' }} />
211213
</Box>
212214
```
213215

214216
Generates CSS like:
215217

216218
```css
217-
[role='group']:hover .a {
219+
:is([role='group'], [data-group]):hover .a {
218220
background-color: red;
219221
}
220222
```
221223

224+
The `:is()` wrapper matches both the new `data-group` attribute and the legacy
225+
`role="group"` attribute with a single rule, so existing markup keeps working
226+
during the migration window.
227+
222228
## Best Practices
223229

224-
1. **Use semantic HTML**: Add `role="group"` to semantically appropriate elements
225-
2. **Keep interactions discoverable**: Don't hide critical content behind group hover
226-
3. **Consider touch devices**: Group hover doesn't work on touch - provide alternative interactions
227-
4. **Use transitions**: Add `transition` prop for smooth state changes
228-
5. **Accessibility**: Ensure interactive elements are keyboard accessible
230+
1. **Use `data-group` for styling hooks**: Reserve `role="group"` for elements that
231+
genuinely form an ARIA group; use the data attribute for visual grouping that
232+
has no a11y semantics.
233+
2. **Keep interactions discoverable**: Don't hide critical content behind group hover.
234+
3. **Consider touch devices**: Group hover doesn't work on touch — provide alternative interactions.
235+
4. **Use transitions**: Add `transition` prop for smooth state changes.
236+
5. **Accessibility**: Ensure interactive elements are keyboard accessible.

apps/landing/src/app/GetStartedButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export function GetStartedButton() {
1919
alignItems="center"
2020
bg="$text"
2121
borderRadius="100px"
22+
data-group
2223
gap="20px"
2324
p="16px 40px"
24-
role="group"
2525
w="fit-content"
2626
>
2727
<Box

apps/landing/src/app/SponsorButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ export default function SponsorButton() {
2323
bg="$containerBackground"
2424
border="1px solid $imageBorder"
2525
borderRadius="12px"
26+
data-group
2627
gap="10px"
2728
pl="16px"
2829
pr="20px"
2930
py="10px"
30-
role="group"
3131
transition="all 0.1s ease-in-out"
3232
>
3333
<Image

apps/landing/src/app/StarButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ export default function StarButton() {
113113
border="1px solid $imageBorder"
114114
borderRadius="12px"
115115
cursor="pointer"
116+
data-group
116117
h="100%"
117-
role="group"
118118
transition="all 0.1s ease-in-out"
119119
>
120120
<Flex

apps/landing/src/components/Header/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ export function Header() {
158158
gap: '4px',
159159
alignItems: 'center',
160160
})}
161+
data-group
161162
href="/storybook/index.html"
162163
prefetch={false}
163-
role="group"
164164
>
165165
<Menu keyword="storybook">Storybook</Menu>
166166
<Box

apps/landing/src/components/showcase/ShowcaseCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface ShowcaseCardProps {
66
}
77
export function ShowcaseCard({ name, image }: ShowcaseCardProps) {
88
return (
9-
<VStack cursor="pointer" gap="8px" role="group">
9+
<VStack cursor="pointer" data-group gap="8px">
1010
<Box h="auto" overflow="hidden" w="100%">
1111
<Image
1212
_groupHover={{ transform: 'scale(1.1)' }}

0 commit comments

Comments
 (0)