Skip to content

Commit 93364ca

Browse files
committed
Support focus loop
1 parent 1e53b78 commit 93364ca

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

docs/data/api/accordion-root.json

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"default": "0"
88
},
99
"disabled": { "type": { "name": "bool" }, "default": "false" },
10+
"loop": { "type": { "name": "bool" }, "default": "true" },
1011
"onOpenChange": { "type": { "name": "func" } },
1112
"openMultiple": { "type": { "name": "bool" }, "default": "true" },
1213
"render": { "type": { "name": "union", "description": "element<br>&#124;&nbsp;func" } },

docs/data/translations/api-docs/accordion-root/accordion-root.json

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
"description": "The default value representing the currently open <code>Accordion.Item</code> This is the uncontrolled counterpart of <code>value</code>."
1212
},
1313
"disabled": { "description": "If <code>true</code>, the component is disabled." },
14+
"loop": {
15+
"description": "If <code>true</code>, focus will loop when moving focus between <code>Trigger</code>s using the arrow keys."
16+
},
1417
"onOpenChange": {
1518
"description": "Callback fired when an Accordion section is opened or closed. The value representing the involved section is provided as an argument."
1619
},

packages/mui-base/src/Accordion/Root/AccordionRoot.tsx

+8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot(
2828
direction,
2929
disabled = false,
3030
htmlHidden,
31+
loop,
3132
onOpenChange,
3233
openMultiple = true,
3334
orientation,
@@ -52,6 +53,7 @@ const AccordionRoot = React.forwardRef(function AccordionRoot(
5253
direction,
5354
disabled,
5455
defaultValue,
56+
loop,
5557
orientation,
5658
onOpenChange,
5759
openMultiple,
@@ -158,6 +160,12 @@ AccordionRoot.propTypes /* remove-proptypes */ = {
158160
* @ignore
159161
*/
160162
htmlHidden: PropTypes.oneOf(['hidden', 'until-found']),
163+
/**
164+
* If `true`, focus will loop when moving focus between `Trigger`s using
165+
* the arrow keys.
166+
* @default true
167+
*/
168+
loop: PropTypes.bool,
161169
/**
162170
* Callback fired when an Accordion section is opened or closed.
163171
* The value representing the involved section is provided as an argument.

packages/mui-base/src/Accordion/Root/useAccordionRoot.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export function useAccordionRoot(
4242
animated = true,
4343
disabled = false,
4444
direction = 'ltr',
45+
loop = true,
4546
onOpenChange = NOOP,
4647
orientation = 'vertical',
4748
openMultiple = true,
@@ -102,11 +103,19 @@ export function useAccordionRoot(
102103
const thisIndex = triggers.indexOf(event.target as HTMLButtonElement);
103104

104105
function toNext() {
105-
nextIndex = Math.min(thisIndex + 1, lastIndex);
106+
if (loop) {
107+
nextIndex = thisIndex + 1 > lastIndex ? 0 : thisIndex + 1;
108+
} else {
109+
nextIndex = Math.min(thisIndex + 1, lastIndex);
110+
}
106111
}
107112

108113
function toPrev() {
109-
nextIndex = thisIndex - 1;
114+
if (loop) {
115+
nextIndex = thisIndex === 0 ? lastIndex : thisIndex - 1;
116+
} else {
117+
nextIndex = thisIndex - 1;
118+
}
110119
}
111120

112121
switch (event.key) {
@@ -154,7 +163,7 @@ export function useAccordionRoot(
154163
},
155164
});
156165
},
157-
[direction, orientation],
166+
[direction, loop, orientation],
158167
);
159168

160169
return React.useMemo(
@@ -214,6 +223,12 @@ export namespace useAccordionRoot {
214223
* @default 'ltr'
215224
*/
216225
direction?: Direction;
226+
/**
227+
* If `true`, focus will loop when moving focus between `Trigger`s using
228+
* the arrow keys.
229+
* @default true
230+
*/
231+
loop?: boolean;
217232
/**
218233
* Callback fired when an Accordion section is opened or closed.
219234
* The value representing the involved section is provided as an argument.

0 commit comments

Comments
 (0)