Skip to content

Commit 4c30e68

Browse files
[joy-ui][Accordion] Fix AccordionDetails tabindex when expanding (#43246)
Signed-off-by: Shrey Bhadja <[email protected]> Co-authored-by: Aarón García Hervás <[email protected]>
1 parent 4663ab4 commit 4c30e68

File tree

2 files changed

+59
-12
lines changed

2 files changed

+59
-12
lines changed

packages/mui-joy/src/AccordionDetails/AccordionDetails.test.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,51 @@ describe('<AccordionDetails />', () => {
8585
expect(screen.getByRole('button')).to.have.attribute('aria-expanded', 'true');
8686
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', 2);
8787
});
88+
89+
it('should retain the default tab index if not explicitly set', () => {
90+
render(
91+
<Accordion>
92+
<AccordionSummary>title</AccordionSummary>
93+
<AccordionDetails>
94+
<input data-testid="textbox" />
95+
</AccordionDetails>
96+
</Accordion>,
97+
);
98+
99+
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', -1);
100+
101+
fireEvent.click(screen.getByRole('button')); // open
102+
103+
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', 0);
104+
105+
fireEvent.click(screen.getByRole('button')); // close
106+
107+
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', -1);
108+
109+
fireEvent.click(screen.getByRole('button')); // reopen
110+
111+
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', 0);
112+
});
113+
114+
it('should retain the -1 tab index when explicitly set', () => {
115+
render(
116+
<Accordion>
117+
<AccordionSummary>title</AccordionSummary>
118+
<AccordionDetails>
119+
<input data-testid="textbox" tabIndex={-1} />
120+
</AccordionDetails>
121+
</Accordion>,
122+
);
123+
124+
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', -1);
125+
126+
fireEvent.click(screen.getByRole('button')); // open
127+
128+
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', -1);
129+
130+
fireEvent.click(screen.getByRole('button')); // close
131+
132+
expect(screen.getByTestId('textbox')).to.have.property('tabIndex', -1);
133+
});
88134
});
89135
});

packages/mui-joy/src/AccordionDetails/AccordionDetails.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,27 +98,28 @@ const AccordionDetails = React.forwardRef(function AccordionDetails(inProps, ref
9898
const handleRef = useForkRef(rootRef, ref);
9999

100100
React.useEffect(() => {
101-
// When accordion is closed, prevent tabbing into the details content.
102101
if (rootRef.current) {
103102
const elements = rootRef.current.querySelectorAll(
104103
'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])',
105104
);
106-
elements.forEach((elm) => {
107-
if (expanded) {
108-
const prevTabIndex = elm.getAttribute('data-prev-tabindex');
109-
const currentTabIndex = elm.getAttribute('tabindex');
110105

111-
if (currentTabIndex && prevTabIndex) {
112-
// restore tabindex
113-
elm.setAttribute('tabindex', prevTabIndex);
114-
elm.removeAttribute('data-prev-tabindex');
115-
}
106+
elements.forEach((elm) => {
107+
const currentTabIndex = elm.getAttribute('tabindex');
108+
const prevTabIndex = elm.getAttribute('data-prev-tabindex');
116109

117-
if (!prevTabIndex && !currentTabIndex) {
110+
if (expanded) {
111+
// Restore the previous tabindex if it exists, or remove it if it was "unset"
112+
if (prevTabIndex === 'unset') {
118113
elm.removeAttribute('tabindex');
114+
} else if (prevTabIndex !== null) {
115+
elm.setAttribute('tabindex', prevTabIndex);
119116
}
117+
elm.removeAttribute('data-prev-tabindex');
120118
} else {
121-
elm.setAttribute('data-prev-tabindex', elm.getAttribute('tabindex') || '');
119+
// If element has no data-prev-tabindex, store the current tabindex or "unset"
120+
if (prevTabIndex === null) {
121+
elm.setAttribute('data-prev-tabindex', currentTabIndex || 'unset');
122+
}
122123
elm.setAttribute('tabindex', '-1');
123124
}
124125
});

0 commit comments

Comments
 (0)