Skip to content

Commit

Permalink
Move movements should "take over" from keyboard focus in Combobox dro…
Browse files Browse the repository at this point in the history
…pdown list, and vice versa, acting like a native select.

Fixes #2165
  • Loading branch information
it-vegard committed Aug 18, 2023
1 parent bfee5a8 commit 66d065d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 22 deletions.
8 changes: 4 additions & 4 deletions @navikt/core/css/form/combobox.css
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,15 @@
}

.navds-combobox__list-item--focus,
.navds-combobox__list-item:hover {
.navds-combobox__list--with-hover .navds-combobox__list-item:hover {
background-color: var(--ac-combobox-list-item-hover-bg, var(--a-surface-hover));
cursor: pointer;
border-left: 4px solid var(--ac-combobox-list-item-hover-border-left, var(--a-border-strong));
padding-left: calc(var(--a-spacing-3) - 4px);
}

.navds-form-field--small .navds-combobox__list-item--focus,
.navds-form-field--small .navds-combobox__list-item:hover {
.navds-combobox__list--with-hover .navds-form-field--small .navds-combobox__list-item:hover {
padding-left: calc(var(--a-spacing-2) - 4px);
}

Expand All @@ -277,7 +277,7 @@
}

.navds-combobox__list-item--selected.navds-combobox__list-item--focus,
.navds-combobox__list-item--selected:hover {
.navds-combobox__list--with-hover .navds-combobox__list-item--selected:hover {
background-color: var(--ac-combobox-list-item-selected-hover-bg, var(--a-surface-action-subtle-hover));
border-left: 4px solid var(--ac-combobox-list-item-selected-hover-border-left, var(--a-border-focus));
padding-left: calc(var(--a-spacing-3) - 4px);
Expand All @@ -291,7 +291,7 @@
gap: 0.25rem;
}

.navds-combobox__list-item__new-option:hover {
.navds-combobox__list--with-hover .navds-combobox__list-item__new-option:hover {
border-bottom: 1px solid var(--a-border-divider);
background: var(--a-surface-neutral-subtle-hover);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ const FilteredOptions = () => {
filteredOptions,
filteredOptionsIndex,
filteredOptionsRef,
isMouseLastUsedInputDevice,
setIsMouseLastUsedInputDevice,
isValueNew,
setFilteredOptionsIndex,
toggleIsListOpen,
} = useFilteredOptionsContext();
const { isMultiSelect, selectedOptions, toggleOption } =
Expand All @@ -30,6 +33,7 @@ const FilteredOptions = () => {
ref={filteredOptionsRef}
className={cl("navds-combobox__list", {
"navds-combobox__list--closed": !isListOpen,
"navds-combobox__list--with-hover": isMouseLastUsedInputDevice,
})}
id={`${id}-filtered-options`}
role="listbox"
Expand All @@ -48,6 +52,12 @@ const FilteredOptions = () => {
{isValueNew && allowNewValues && (
<li
tabIndex={-1}
onMouseMove={() => {
if (filteredOptionsIndex !== -1) {
setFilteredOptionsIndex(-1);
setIsMouseLastUsedInputDevice(true);
}
}}
onPointerUp={(event) => {
toggleOption(value, event);
if (!isMultiSelect && !selectedOptions.includes(value))
Expand Down Expand Up @@ -90,6 +100,12 @@ const FilteredOptions = () => {
id={`${id}-option-${option.replace(" ", "-")}`}
key={option}
tabIndex={-1}
onMouseMove={() => {
if (filteredOptionsIndex !== index) {
setFilteredOptionsIndex(index);
setIsMouseLastUsedInputDevice(true);
}
}}
onPointerUp={(event) => {
toggleOption(option, event);
if (!isMultiSelect && !selectedOptions.includes(option))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React, {
useCallback,
useRef,
useLayoutEffect,
SetStateAction,
} from "react";
import cl from "clsx";
import { useCustomOptionsContext } from "../customOptionsContext";
Expand Down Expand Up @@ -35,6 +36,8 @@ type FilteredOptionsContextType = {
isListOpen: boolean;
isLoading?: boolean;
filteredOptions: string[];
isMouseLastUsedInputDevice: boolean;
setIsMouseLastUsedInputDevice: React.Dispatch<SetStateAction<boolean>>;
isValueNew: boolean;
toggleIsListOpen: (newState?: boolean) => void;
currentOption: string | null;
Expand Down Expand Up @@ -84,6 +87,9 @@ export const FilteredOptionsProvider = ({ children, value: props }) => {

const previousSearchTerm = usePrevious(searchTerm);

const [isMouseLastUsedInputDevice, setIsMouseLastUsedInputDevice] =
useState(false);

useLayoutEffect(() => {
if (
shouldAutocomplete &&
Expand Down Expand Up @@ -246,6 +252,8 @@ export const FilteredOptionsProvider = ({ children, value: props }) => {
isListOpen,
isLoading,
filteredOptions,
isMouseLastUsedInputDevice,
setIsMouseLastUsedInputDevice,
isValueNew,
toggleIsListOpen,
currentOption,
Expand Down
3 changes: 3 additions & 0 deletions @navikt/core/react/src/form/combobox/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
moveFocusToInput,
moveFocusToEnd,
setFilteredOptionsIndex,
setIsMouseLastUsedInputDevice,
shouldAutocomplete,
} = useFilteredOptionsContext();

Expand Down Expand Up @@ -102,6 +103,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(

const handleKeyDown = useCallback(
(e) => {
setIsMouseLastUsedInputDevice(false);
if (e.key === "Backspace") {
if (value === "") {
const lastSelectedOption =
Expand Down Expand Up @@ -132,6 +134,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
isListOpen,
filteredOptionsIndex,
moveFocusUp,
setIsMouseLastUsedInputDevice,
]
);

Expand Down
36 changes: 18 additions & 18 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3351,7 +3351,7 @@ __metadata:
languageName: node
linkType: hard

"@navikt/aksel-icons@^5.0.1, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
"@navikt/aksel-icons@^5.0.2, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
version: 0.0.0-use.local
resolution: "@navikt/aksel-icons@workspace:@navikt/aksel-icons"
dependencies:
Expand All @@ -3378,8 +3378,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "@navikt/aksel-stylelint@workspace:@navikt/aksel-stylelint"
dependencies:
"@navikt/ds-css": ^5.0.1
"@navikt/ds-tokens": ^5.0.1
"@navikt/ds-css": ^5.0.2
"@navikt/ds-tokens": ^5.0.2
"@types/jest": ^29.0.0
concurrently: 7.2.1
copyfiles: 2.4.1
Expand All @@ -3396,7 +3396,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@navikt/aksel@workspace:@navikt/aksel"
dependencies:
"@navikt/ds-css": 5.0.1
"@navikt/ds-css": 5.0.2
"@types/inquirer": ^9.0.3
"@types/jest": ^29.0.0
axios: 1.3.6
Expand All @@ -3420,11 +3420,11 @@ __metadata:
languageName: unknown
linkType: soft

"@navikt/ds-css@*, @navikt/[email protected].1, @navikt/ds-css@^5.0.1, @navikt/ds-css@workspace:@navikt/core/css":
"@navikt/ds-css@*, @navikt/[email protected].2, @navikt/ds-css@^5.0.2, @navikt/ds-css@workspace:@navikt/core/css":
version: 0.0.0-use.local
resolution: "@navikt/ds-css@workspace:@navikt/core/css"
dependencies:
"@navikt/ds-tokens": ^5.0.1
"@navikt/ds-tokens": ^5.0.2
cssnano: 6.0.0
fast-glob: 3.2.11
lodash: 4.17.21
Expand All @@ -3437,12 +3437,12 @@ __metadata:
languageName: unknown
linkType: soft

"@navikt/ds-react@*, @navikt/[email protected].1, @navikt/ds-react@^5.0.1, @navikt/ds-react@workspace:@navikt/core/react":
"@navikt/ds-react@*, @navikt/[email protected].2, @navikt/ds-react@^5.0.2, @navikt/ds-react@workspace:@navikt/core/react":
version: 0.0.0-use.local
resolution: "@navikt/ds-react@workspace:@navikt/core/react"
dependencies:
"@floating-ui/react": 0.24.1
"@navikt/aksel-icons": ^5.0.1
"@navikt/aksel-icons": ^5.0.2
"@radix-ui/react-tabs": 1.0.0
"@radix-ui/react-toggle-group": 1.0.0
"@testing-library/dom": 8.13.0
Expand Down Expand Up @@ -3476,11 +3476,11 @@ __metadata:
languageName: unknown
linkType: soft

"@navikt/ds-tailwind@^5.0.1, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
"@navikt/ds-tailwind@^5.0.2, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
version: 0.0.0-use.local
resolution: "@navikt/ds-tailwind@workspace:@navikt/core/tailwind"
dependencies:
"@navikt/ds-tokens": ^5.0.1
"@navikt/ds-tokens": ^5.0.2
"@types/jest": ^29.0.0
color: 4.2.3
jest: ^29.0.0
Expand All @@ -3491,7 +3491,7 @@ __metadata:
languageName: unknown
linkType: soft

"@navikt/ds-tokens@^5.0.1, @navikt/ds-tokens@workspace:@navikt/core/tokens":
"@navikt/ds-tokens@^5.0.2, @navikt/ds-tokens@workspace:@navikt/core/tokens":
version: 0.0.0-use.local
resolution: "@navikt/ds-tokens@workspace:@navikt/core/tokens"
dependencies:
Expand Down Expand Up @@ -8033,11 +8033,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "aksel.nav.no@workspace:aksel.nav.no"
dependencies:
"@navikt/aksel-icons": ^5.0.1
"@navikt/ds-css": ^5.0.1
"@navikt/ds-react": ^5.0.1
"@navikt/ds-tailwind": ^5.0.1
"@navikt/ds-tokens": ^5.0.1
"@navikt/aksel-icons": ^5.0.2
"@navikt/ds-css": ^5.0.2
"@navikt/ds-react": ^5.0.2
"@navikt/ds-tailwind": ^5.0.2
"@navikt/ds-tokens": ^5.0.2
prettier-plugin-tailwindcss: ^0.2.3
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -22026,8 +22026,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "shadow-dom@workspace:examples/shadow-dom"
dependencies:
"@navikt/ds-css": 5.0.1
"@navikt/ds-react": 5.0.1
"@navikt/ds-css": 5.0.2
"@navikt/ds-react": 5.0.2
"@types/react": ^18.0.0
"@types/react-dom": ^18.0.0
"@vitejs/plugin-react": ^3.1.0
Expand Down

0 comments on commit 66d065d

Please sign in to comment.