diff --git a/components/DropdownLight/DropdownLight.jsx b/components/DropdownLight/DropdownLight.jsx
index 0d0f034e5..466c79248 100644
--- a/components/DropdownLight/DropdownLight.jsx
+++ b/components/DropdownLight/DropdownLight.jsx
@@ -210,12 +210,14 @@ const DropdownLight = ({
const [cursor, setCursor] = useState(-1);
const buttonRef = useRef();
const listOptions = useRef();
+ const ButtonIsClosedAndFocused = () =>
+ !isOpen && document.activeElement === buttonRef.current;
- const downPress = useKeyPress('ArrowDown');
- const upPress = useKeyPress('ArrowUp');
+ const downPress = useKeyPress('ArrowDown', ButtonIsClosedAndFocused);
+ const upPress = useKeyPress('ArrowUp', ButtonIsClosedAndFocused);
const enterPress = useKeyPress('Enter');
+ const escapePress = useKeyPress('Escape');
const focusedItemIndex = useKeyboardSearchItems(items, cursor, isOpen);
- const EscapeKeyPressValue = 'Escape';
const handleToggleDropdown = () => {
setIsOpen(!isOpen);
@@ -249,19 +251,33 @@ const DropdownLight = ({
}
};
- const handleEscPress = ({ key }) => {
- if (key === EscapeKeyPressValue) {
+ useEffect(() => {
+ if (isOpen && escapePress) {
setIsOpen(false);
setCursor(-1);
buttonRef.current.focus();
}
- };
+ }, [escapePress, isOpen]);
useEffect(() => {
+ const GetNextCursor = (currentCursor) =>
+ currentCursor < items.length - 1 ? currentCursor + 1 : currentCursor;
+
if (isOpen && downPress) {
- const selectedCursor = cursor < items.length - 1 ? cursor + 1 : cursor;
+ const selectedCursor = GetNextCursor(cursor);
setCursor(selectedCursor);
}
+
+ if (downPress && ButtonIsClosedAndFocused()) {
+ const selectedItemIndex = items.findIndex(
+ (item) => (item?.label || item) === selectedOptionItem,
+ );
+ const selectedCursor = GetNextCursor(selectedItemIndex);
+
+ if (selectedItemIndex !== selectedCursor) {
+ selectItem(items[selectedCursor]);
+ }
+ }
}, [downPress, items, isOpen]);
useEffect(() => {
@@ -269,24 +285,30 @@ const DropdownLight = ({
const selectedCursor = cursor - 1;
setCursor(selectedCursor);
}
+
+ if (upPress && ButtonIsClosedAndFocused()) {
+ const selectedItemIndex = items.findIndex(
+ (item) => (item?.label || item) === selectedOptionItem,
+ );
+ const previousCursor =
+ selectedItemIndex > 0 ? selectedItemIndex - 1 : selectedItemIndex;
+ const selectedCursor = previousCursor;
+
+ if (selectedItemIndex !== selectedCursor) {
+ selectItem(items[selectedCursor]);
+ }
+ }
}, [upPress, items, isOpen]);
useEffect(() => {
window.addEventListener('click', handleClickOutside);
- window.addEventListener('keydown', handleEscPress);
return () => {
window.removeEventListener('click', handleClickOutside);
- window.removeEventListener('keydown', handleEscPress);
};
}, []);
useEffect(() => {
- if (
- enterPress &&
- !isOpen &&
- document.activeElement === buttonRef.current &&
- selectedOptionItem
- ) {
+ if (enterPress && ButtonIsClosedAndFocused() && selectedOptionItem) {
const selectedItemIndex = items.findIndex(
(item) => (item?.label || item) === selectedOptionItem,
);
diff --git a/components/DropdownLight/DropdownLight.unit.test.jsx b/components/DropdownLight/DropdownLight.unit.test.jsx
index 1c708ace0..d09a56b8f 100644
--- a/components/DropdownLight/DropdownLight.unit.test.jsx
+++ b/components/DropdownLight/DropdownLight.unit.test.jsx
@@ -171,14 +171,17 @@ describe('', () => {
it('should close Dropdown Options when user press Escape', async () => {
render();
+ const dropdownButton = screen.getByRole('button', {
+ name: 'abrir lista de itens',
+ });
+ await userEvent.click(dropdownButton);
await userEvent.keyboard(ESCAPE_KEY_CODE);
expect(screen.queryByRole('list')).not.toBeInTheDocument();
- expect(
- screen.getByRole('button', { name: 'abrir lista de itens' }),
- ).toBeInTheDocument();
+ expect(dropdownButton).toBeInTheDocument();
+ expect(dropdownButton).toHaveFocus();
});
it('should allow User to select an option using only keyboard', async () => {
@@ -200,9 +203,13 @@ describe('', () => {
await userEvent.keyboard(ENTER_KEY_CODE);
const input = screen.getByRole('textbox', { hidden: true });
+ const dropdownButton = screen.getByRole('button', {
+ name: 'abrir lista de itens',
+ });
expect(input.value).toEqual(bananaItemMock);
expect(screen.queryByRole('list')).not.toBeInTheDocument();
+ expect(dropdownButton).toHaveFocus();
});
it('should allow the User to navigate between items using the keys with the initial letter of each item', async () => {
@@ -280,4 +287,36 @@ describe('', () => {
expect(selectionItemImage).toBeInTheDocument();
});
+
+ it('should allow to select an item from the list using the keyboard and without opening the list of options', async () => {
+ const onChangeMock = jest.fn();
+ render();
+
+ await userEvent.tab();
+
+ const dropdownButton = screen.getByRole('button', {
+ name: 'abrir lista de itens',
+ });
+ expect(dropdownButton).toHaveFocus();
+
+ await userEvent.keyboard(ARROW_DOWN_KEY_CODE);
+
+ expect(onChangeMock).toHaveBeenCalledWith({
+ label: 'Lemon',
+ value: 'Lemon',
+ });
+
+ expect(screen.queryByRole('list')).not.toBeInTheDocument();
+ expect(dropdownButton).toHaveFocus();
+
+ await userEvent.keyboard(ARROW_DOWN_KEY_CODE);
+
+ expect(onChangeMock).toHaveBeenCalledWith({
+ label: 'Lime',
+ value: 'Lime',
+ });
+
+ expect(screen.queryByRole('list')).not.toBeInTheDocument();
+ expect(dropdownButton).toHaveFocus();
+ });
});
diff --git a/components/DropdownLight/SubComponents/UseKeyPress.jsx b/components/DropdownLight/SubComponents/UseKeyPress.jsx
index 8a7ad4861..b0004255a 100644
--- a/components/DropdownLight/SubComponents/UseKeyPress.jsx
+++ b/components/DropdownLight/SubComponents/UseKeyPress.jsx
@@ -1,11 +1,14 @@
import { useState, useEffect } from 'react';
-const useKeyPress = (targetKey) => {
+const useKeyPress = (targetKey, isPreventDefault = () => false) => {
const [keyPressed, setKeyPressed] = useState(false);
/* istanbul ignore next */
- const downHandler = ({ key }) => {
- if (key === targetKey) {
+ const downHandler = (event) => {
+ if (event.key === targetKey) {
+ if (isPreventDefault()) {
+ event.preventDefault();
+ }
setKeyPressed(true);
}
};