Skip to content

Commit

Permalink
fix(combobox): fix up/down arrow press for textarea inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
chaance committed Oct 12, 2022
1 parent 7cedfd2 commit 9e1f2e6
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-bobcats-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@reach/combobox": patch
---

Fix bug that prevents caret from moving up/down on keypress events in a combobox rendered as textarea
26 changes: 21 additions & 5 deletions packages/combobox/src/reach-combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,7 @@ function useKeyDown() {
transition,
autocompletePropRef,
persistSelectionRef,
inputRef,
isControlledRef,
} = React.useContext(ComboboxContext);

Expand Down Expand Up @@ -1093,39 +1094,54 @@ function useKeyDown() {
return options[options.length - 1];
}

// In standard inputs, ArrowUp/ArrowDown will expand the options list in the
// IDLE state and prevent the browser's default behavior (mostly just
// scrolling the page). When the input is rendered as a textarea and has a
// value containing more than one line, we don't want to do that.
// ArrowUp/ArrowDown should move the caret up/dowm in multiline situations.
let textareaHasMultilineValue =
inputRef.current?.tagName.toUpperCase() === "TEXTAREA" &&
inputRef.current.value.includes(`\n`);

switch (event.key) {
case "ArrowDown":
// Don't scroll the page
event.preventDefault();
if (!options || !options.length) {
return;
}

if (state === IDLE) {
if (textareaHasMultilineValue) {
return;
}
// Opening a closed list
event.preventDefault();
transition(NAVIGATE, {
persistSelection: persistSelectionRef.current,
});
} else {
event.preventDefault();
let next = getNextOption();
transition(NAVIGATE, { value: next ? next.value : null });
}
break;

// A lot of duplicate code with ArrowDown up next, I'm already over it.
case "ArrowUp":
// Don't scroll the page
event.preventDefault();
if (!options || options.length === 0) {
if (!options || !options.length) {
return;
}

if (state === IDLE) {
if (textareaHasMultilineValue) {
return;
}
// Opening a closed list
event.preventDefault();
transition(NAVIGATE, {
persistSelection: persistSelectionRef.current,
});
} else {
event.preventDefault();
let prev = getPreviousOption();
transition(NAVIGATE, { value: prev ? prev.value : null });
}
Expand Down

0 comments on commit 9e1f2e6

Please sign in to comment.