Open ContextMenu at correct location via keyboard
This commit is contained in:
parent
06c9ca9d24
commit
fd40322002
2 changed files with 41 additions and 19 deletions
|
@ -28,6 +28,12 @@
|
||||||
right: 63px;
|
right: 63px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
width: 22px;
|
width: 22px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
@include keyboard-mode {
|
||||||
|
background-color: $color-ultramarine;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__settings__button {
|
&__settings__button {
|
||||||
|
@ -44,6 +50,12 @@
|
||||||
right: 16px;
|
right: 16px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
width: 22px;
|
width: 22px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
@include keyboard-mode {
|
||||||
|
background-color: $color-ultramarine;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
|
|
|
@ -129,14 +129,24 @@ export function ContextMenu<T>({
|
||||||
}, [isMenuShowing, referenceElement, popperElement]);
|
}, [isMenuShowing, referenceElement, popperElement]);
|
||||||
|
|
||||||
const handleKeyDown = (ev: KeyboardEvent) => {
|
const handleKeyDown = (ev: KeyboardEvent) => {
|
||||||
if (!isMenuShowing) {
|
if ((ev.key === 'Enter' || ev.key === 'Space') && !isMenuShowing) {
|
||||||
if (ev.key === 'Enter') {
|
closeCurrentOpenContextMenu?.();
|
||||||
setFocusedIndex(0);
|
closeCurrentOpenContextMenu = () => setIsMenuShowing(false);
|
||||||
|
if (referenceElement) {
|
||||||
|
const box = referenceElement.getBoundingClientRect();
|
||||||
|
virtualElement.current = generateVirtualElement(box.x, box.y);
|
||||||
}
|
}
|
||||||
|
setIsMenuShowing(true);
|
||||||
|
setFocusedIndex(0);
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMenuShowing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev.key === 'ArrowDown') {
|
if (ev.key === 'ArrowDown' || ev.key === 'Tab') {
|
||||||
const currFocusedIndex = focusedIndex || 0;
|
const currFocusedIndex = focusedIndex || 0;
|
||||||
const nextFocusedIndex =
|
const nextFocusedIndex =
|
||||||
currFocusedIndex >= menuOptions.length - 1 ? 0 : currFocusedIndex + 1;
|
currFocusedIndex >= menuOptions.length - 1 ? 0 : currFocusedIndex + 1;
|
||||||
|
@ -272,19 +282,19 @@ export function ContextMenu<T>({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<FocusTrap
|
||||||
className={classNames(
|
focusTrapOptions={{
|
||||||
getClassName('__container'),
|
allowOutsideClick: true,
|
||||||
theme ? themeClassName(theme) : undefined
|
}}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{buttonNode}
|
<div
|
||||||
{isMenuShowing && (
|
className={classNames(
|
||||||
<FocusTrap
|
getClassName('__container'),
|
||||||
focusTrapOptions={{
|
theme ? themeClassName(theme) : undefined
|
||||||
allowOutsideClick: true,
|
)}
|
||||||
}}
|
>
|
||||||
>
|
{buttonNode}
|
||||||
|
{isMenuShowing && (
|
||||||
<div className={theme ? themeClassName(theme) : undefined}>
|
<div className={theme ? themeClassName(theme) : undefined}>
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
@ -301,8 +311,8 @@ export function ContextMenu<T>({
|
||||||
{optionElements}
|
{optionElements}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FocusTrap>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</FocusTrap>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue