Skip to content

Commit a2ac691

Browse files
mj12albertJanpot
andauthored
[utils] Explicitly register roving tab items with parent (#48122)
Co-authored-by: Jan Potoms <2109932+Janpot@users.noreply.github.com>
1 parent 709d924 commit a2ac691

47 files changed

Lines changed: 2767 additions & 1249 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/data/material/components/menus/GroupedMenu.js

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,9 @@ import Menu from '@mui/material/Menu';
55
import MenuItem from '@mui/material/MenuItem';
66
import { styled } from '@mui/material/styles';
77

8-
const StyledListHeader = Object.assign(
9-
styled(ListSubheader)({
10-
backgroundImage: 'var(--Paper-overlay)',
11-
}),
12-
{
13-
// IMPORTANT: The base ListSubheader component sets `muiSkipListHighlight = true`
14-
// by default, but wrapping it with `styled(ListSubheader)` does not preserve
15-
// that static field. We re-declare it here so the menu list continues to skip
16-
// highlighting this non-focusable subheader when navigating with the keyboard.
17-
muiSkipListHighlight: true,
18-
},
19-
);
8+
const StyledListHeader = styled(ListSubheader)({
9+
backgroundImage: 'var(--Paper-overlay)',
10+
});
2011

2112
export default function GroupedMenu() {
2213
const [anchorEl, setAnchorEl] = React.useState(null);

docs/data/material/components/menus/GroupedMenu.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,9 @@ import Menu from '@mui/material/Menu';
55
import MenuItem from '@mui/material/MenuItem';
66
import { styled } from '@mui/material/styles';
77

8-
const StyledListHeader = Object.assign(
9-
styled(ListSubheader)({
10-
backgroundImage: 'var(--Paper-overlay)',
11-
}),
12-
{
13-
// IMPORTANT: The base ListSubheader component sets `muiSkipListHighlight = true`
14-
// by default, but wrapping it with `styled(ListSubheader)` does not preserve
15-
// that static field. We re-declare it here so the menu list continues to skip
16-
// highlighting this non-focusable subheader when navigating with the keyboard.
17-
muiSkipListHighlight: true,
18-
},
19-
);
8+
const StyledListHeader = styled(ListSubheader)({
9+
backgroundImage: 'var(--Paper-overlay)',
10+
});
2011

2112
export default function GroupedMenu() {
2213
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);

docs/data/material/components/selects/selects.md

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -141,67 +141,6 @@ Display categories with the `ListSubheader` component or the native `<optgroup>`
141141

142142
{{"demo": "GroupedSelect.js"}}
143143

144-
:::warning
145-
If you wish to wrap the ListSubheader in a custom component, you'll have to annotate it so Material UI can handle it properly when determining focusable elements.
146-
147-
You have two options for solving this:
148-
Option 1: Define a static boolean field called `muiSkipListHighlight` on your component function, and set it to `true`:
149-
150-
```tsx
151-
function MyListSubheader(props: ListSubheaderProps) {
152-
return <ListSubheader {...props} />;
153-
}
154-
155-
MyListSubheader.muiSkipListHighlight = true;
156-
export default MyListSubheader;
157-
158-
// elsewhere:
159-
160-
return (
161-
<Select>
162-
<MyListSubheader>Group 1</MyListSubheader>
163-
<MenuItem value={1}>Option 1</MenuItem>
164-
<MenuItem value={2}>Option 2</MenuItem>
165-
<MyListSubheader>Group 2</MyListSubheader>
166-
<MenuItem value={3}>Option 3</MenuItem>
167-
<MenuItem value={4}>Option 4</MenuItem>
168-
{/* ... */}
169-
</Select>
170-
```
171-
172-
Option 2: Place a `muiSkipListHighlight` prop on each instance of your component.
173-
The prop doesn't have to be forwarded to the ListSubheader, nor present in the underlying DOM element.
174-
It just has to be placed on a component that's used as a subheader.
175-
176-
```tsx
177-
export default function MyListSubheader(
178-
props: ListSubheaderProps & { muiSkipListHighlight: boolean },
179-
) {
180-
const { muiSkipListHighlight, ...other } = props;
181-
return <ListSubheader {...other} />;
182-
}
183-
184-
// elsewhere:
185-
186-
return (
187-
<Select>
188-
<MyListSubheader muiSkipListHighlight>Group 1</MyListSubheader>
189-
<MenuItem value={1}>Option 1</MenuItem>
190-
<MenuItem value={2}>Option 2</MenuItem>
191-
<MyListSubheader muiSkipListHighlight>Group 2</MyListSubheader>
192-
<MenuItem value={3}>Option 3</MenuItem>
193-
<MenuItem value={4}>Option 4</MenuItem>
194-
{/* ... */}
195-
</Select>
196-
);
197-
```
198-
199-
We recommend the first option as it doesn't require updating all the usage sites of the component.
200-
201-
Keep in mind this is **only necessary** if you wrap the ListSubheader in a custom component.
202-
If you use the ListSubheader directly, **no additional code is required**.
203-
:::
204-
205144
## Accessibility
206145

207146
To properly label your `Select` input you need an extra element with an `id` that contains a label.

docs/data/material/migration/upgrade-to-v9/upgrade-to-v9.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,20 +286,28 @@ The `StepButton` has:
286286

287287
### Tabs
288288

289-
The `tabindex` attribute for each tab will be changed on Arrow Key or Home / End navigation. Previously, we only moved the focus on keyboard navigation. Now, we move the focus and also add the `tabindex="0"` to the focused element. The previously focused element will have its `tabindex` updated to `-1` in order to keep only one focusable `Tab` at a time.
289+
The `tabindex` attribute for each tab will be changed on Arrow Key or Home / End navigation. Previously, keyboard navigation moved DOM focus without updating `tabindex` on the focused `Tab`. Now, we move DOM focus and also add the `tabindex="0"` to the focused `Tab`. Other tabs will have `tabindex="-1"` to keep only one focusable `Tab` at a time.
290290

291291
Selecting a `Tab` will update the focus and `tabindex` as before.
292292

293-
### Menu and MenuList
293+
`Tab`s not placed inside `Tabs` will now throw an error.
294294

295-
The `tabindex` attribute for each menu item will be changed on Arrow Key, Home / End or Character Key navigation. Previously, we only moved the focus on keyboard navigation. Now, we move the focus and also add the `tabindex="0"` to the focused element. The previously focused element will have its `tabindex` updated to `-1` in order to keep only one focusable `MenuItem` at a time.
295+
### Menu and MenuList
296296

297-
This change also applies to the `Menu` since it uses `MenuList`.
297+
When using `variant="selectedMenu"`, the `tabindex` attribute for each menu item will change on Arrow Key, Home / End or Character Key navigation. Previously, keyboard navigation moved DOM focus without updating `tabindex` on focused items. Now, we move DOM focus and also add `tabindex="0"` to the focused element. The previously focused element will have its `tabindex` updated to `-1` in order to keep only one focusable `MenuItem` at a time.
298298

299-
Selecting a `MenuItem` will update the focus and `tabindex` as before.
299+
This change also applies both `Menu` and `MenuList` with `variant="selectedMenu"`.
300300

301301
The `autoFocus` prop in `MenuList` does not set `tabindex="0"` on the `List` component anymore. It will always stay as `-1`.
302302

303+
`MenuItem`s will throw an error when rendered outside of `Menu` or `MenuList`.
304+
305+
Keyboard navigation now supports `MenuItem`s inside `React.Fragment`.
306+
307+
Custom non-interactive menu content such as `ListSubheader` or `Divider` no longer need to set `muiSkipListHighlight` to opt-out of the menu's focus management.
308+
309+
Custom children that set `role="menuitem"` but do not wrap the `MenuItem` component are no longer supported inside `Menu` or `MenuList`.
310+
303311
## Deprecated APIs removed (Breaking)
304312

305313
APIs that were deprecated earlier have been removed in v9.

0 commit comments

Comments
 (0)