Skip to content

Commit

Permalink
[DropdownMenu] Prevent scroll on initial menu focus (radix-ui#2762)
Browse files Browse the repository at this point in the history
  • Loading branch information
benoitgrelard authored Mar 6, 2024
1 parent 834330f commit 38f7f14
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 4 deletions.
13 changes: 13 additions & 0 deletions .yarn/versions/2ab74363.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
releases:
"@radix-ui/react-context-menu": patch
"@radix-ui/react-dropdown-menu": patch
"@radix-ui/react-menu": patch
"@radix-ui/react-menubar": patch
"@radix-ui/react-radio-group": patch
"@radix-ui/react-roving-focus": patch
"@radix-ui/react-tabs": patch
"@radix-ui/react-toggle-group": patch
"@radix-ui/react-toolbar": patch

declined:
- primitives
3 changes: 2 additions & 1 deletion packages/react/menu/src/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ const MenuContentImpl = React.forwardRef<MenuContentImplElement, MenuContentImpl
// when opening, explicitly focus the content area only and leave
// `onEntryFocus` in control of focusing first item
event.preventDefault();
contentRef.current?.focus();
contentRef.current?.focus({ preventScroll: true });
})}
onUnmountAutoFocus={onCloseAutoFocus}
>
Expand All @@ -493,6 +493,7 @@ const MenuContentImpl = React.forwardRef<MenuContentImplElement, MenuContentImpl
// only focus first item when using keyboard
if (!rootContext.isUsingKeyboardRef.current) event.preventDefault();
})}
preventScrollOnEntryFocus
>
<PopperPrimitive.Content
role="menu"
Expand Down
8 changes: 5 additions & 3 deletions packages/react/roving-focus/src/RovingFocusGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ interface RovingFocusGroupImplProps
defaultCurrentTabStopId?: string;
onCurrentTabStopIdChange?: (tabStopId: string | null) => void;
onEntryFocus?: (event: Event) => void;
preventScrollOnEntryFocus?: boolean;
}

const RovingFocusGroupImpl = React.forwardRef<
Expand All @@ -107,6 +108,7 @@ const RovingFocusGroupImpl = React.forwardRef<
defaultCurrentTabStopId,
onCurrentTabStopIdChange,
onEntryFocus,
preventScrollOnEntryFocus = false,
...groupProps
} = props;
const ref = React.useRef<RovingFocusGroupImplElement>(null);
Expand Down Expand Up @@ -180,7 +182,7 @@ const RovingFocusGroupImpl = React.forwardRef<
Boolean
) as typeof items;
const candidateNodes = candidateItems.map((item) => item.ref.current!);
focusFirst(candidateNodes);
focusFirst(candidateNodes, preventScrollOnEntryFocus);
}
}

Expand Down Expand Up @@ -314,12 +316,12 @@ function getFocusIntent(event: React.KeyboardEvent, orientation?: Orientation, d
return MAP_KEY_TO_FOCUS_INTENT[key];
}

function focusFirst(candidates: HTMLElement[]) {
function focusFirst(candidates: HTMLElement[], preventScroll = false) {
const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
for (const candidate of candidates) {
// if focus is already where we want to go, we don't want to keep going through the candidates
if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
candidate.focus();
candidate.focus({ preventScroll });
if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
}
}
Expand Down

0 comments on commit 38f7f14

Please sign in to comment.