SDA-3962: Allow to up down on reaching end start

This commit is contained in:
NguyenTranHoangSym 2022-12-29 16:48:29 +07:00 committed by Salah Benmoussati
parent 160ec9ee9a
commit ca45eb6c06
3 changed files with 141 additions and 1 deletions

View File

@ -9,6 +9,7 @@ exports[`Menu Button should show all elements 1`] = `
className="menu-button"
data-testid="undefined_MENU_BUTTON"
onClick={[Function]}
onKeyUp={[Function]}
>
<img
alt="Open menu"

View File

@ -88,4 +88,85 @@ describe('Menu Button', () => {
await waitForPromisesToResolve();
expect(wrapper.find('.menu').exists()).toBeFalsy();
});
it('should focus menu list on up', async () => {
const wrapper = mount(
<MenuButton id='snipping-tool' listItems={menuItem} />,
);
wrapper.find('[data-testid="snipping-tool_MENU_BUTTON"]').simulate('click');
wrapper.update();
wrapper
.find('[data-testid="snipping-tool_MENU_BUTTON"]')
.simulate('keyup', { key: 'ArrowUp' });
wrapper.update();
expect(
(wrapper.find('[data-testid="snipping-tool_SAVE_AS"]').instance() as any)
.dataset.isfocused,
).toBe('true');
});
it('should focus menu list on down', async () => {
const wrapper = mount(
<MenuButton id='snipping-tool' listItems={menuItem} />,
);
wrapper.find('[data-testid="snipping-tool_MENU_BUTTON"]').simulate('click');
wrapper.update();
wrapper
.find('[data-testid="snipping-tool_MENU_BUTTON"]')
.simulate('keyup', { key: 'ArrowDown' });
wrapper.update();
expect(
(
wrapper
.find('[data-testid="snipping-tool_COPY_TO_CLIPBOARD"]')
.instance() as any
).dataset.isfocused,
).toBe('true');
});
it('should go down on press down', async () => {
const wrapper = mount(
<MenuButton id='snipping-tool' listItems={menuItem} />,
);
wrapper.find('[data-testid="snipping-tool_MENU_BUTTON"]').simulate('click');
wrapper.update();
wrapper
.find('[data-testid="snipping-tool_MENU_BUTTON"]')
.simulate('keyup', { key: 'ArrowDown' });
wrapper.update();
wrapper
.find('[data-testid="snipping-tool_LIST"]')
.simulate('keyup', { key: 'ArrowDown' });
wrapper.update();
expect(
(wrapper.find('[data-testid="snipping-tool_SAVE_AS"]').instance() as any)
.dataset.isfocused,
).toBe('true');
});
it('should go up on press up', async () => {
const wrapper = mount(
<MenuButton id='snipping-tool' listItems={menuItem} />,
);
wrapper.find('[data-testid="snipping-tool_MENU_BUTTON"]').simulate('click');
wrapper.update();
wrapper
.find('[data-testid="snipping-tool_MENU_BUTTON"]')
.simulate('keyup', { key: 'ArrowUp' });
wrapper
.find('[data-testid="snipping-tool_LIST"]')
.simulate('keyup', { key: 'ArrowUp' });
wrapper.update();
expect(
(
wrapper
.find('[data-testid="snipping-tool_COPY_TO_CLIPBOARD"]')
.instance() as any
).dataset.isfocused,
).toBe('true');
});
});

View File

@ -16,6 +16,8 @@ const MenuButton: React.FunctionComponent<IMenuButtonProps> = ({
}) => {
//#region State
const [isDisplay, setDisplay] = useState(false);
const [currentFocusedItem, setCurrentFocusedItem] =
useState<HTMLButtonElement>();
const listRef = useRef<HTMLDivElement>(document.createElement('div'));
const menuButtonRef = useRef<HTMLButtonElement>(
document.createElement('button'),
@ -25,6 +27,7 @@ const MenuButton: React.FunctionComponent<IMenuButtonProps> = ({
//#region Variables
const testId = {
menu: `${id}_MENU_BUTTON`,
list: `${id}_LIST`,
};
//#endregion
@ -32,6 +35,55 @@ const MenuButton: React.FunctionComponent<IMenuButtonProps> = ({
const onClickMenuButton = () => {
setDisplay(!isDisplay);
};
const onMenuKeyUp = (event: React.KeyboardEvent) => {
let item: HTMLButtonElement | null = null;
if (event.key === 'ArrowDown') {
item = listRef.current.children[0] as HTMLButtonElement;
}
if (event.key === 'ArrowUp') {
item = listRef.current.children[
listRef.current.children.length - 1
] as HTMLButtonElement;
}
if (item) {
item.focus();
item.setAttribute('data-isfocused', 'true'); // UT Purpose
setCurrentFocusedItem(item);
}
};
const onListKeyUp = (event: React.KeyboardEvent) => {
let item: HTMLButtonElement | null = null;
if (!listRef.current) {
return;
}
currentFocusedItem?.setAttribute('data-isfocused', 'false'); // UT Purpose
if (event.key === 'ArrowUp') {
item =
(currentFocusedItem?.previousElementSibling as HTMLButtonElement) ||
(listRef.current.children[
listRef.current.children.length - 1
] as HTMLButtonElement);
}
if (event.key === 'ArrowDown') {
item =
(currentFocusedItem?.nextElementSibling as HTMLButtonElement) ||
(listRef.current.children[0] as HTMLButtonElement);
}
if (item) {
item.focus();
item.setAttribute('data-isfocused', 'true'); // UT Purpose
setCurrentFocusedItem(item);
}
};
//#endregion
//#region UseEffect
@ -94,6 +146,7 @@ const MenuButton: React.FunctionComponent<IMenuButtonProps> = ({
<>
<div className='menu-button-wrapper'>
<button
onKeyUp={onMenuKeyUp}
className={`menu-button`}
onClick={onClickMenuButton}
data-testid={testId.menu}
@ -107,7 +160,12 @@ const MenuButton: React.FunctionComponent<IMenuButtonProps> = ({
/>
</button>
{isDisplay && (
<div className='menu' ref={listRef}>
<div
className='menu'
data-testid={testId.list}
ref={listRef}
onKeyUp={onListKeyUp}
>
{renderListItems()}
</div>
)}