Skip to content

Commit

Permalink
Merge 80b42da into cd3859a
Browse files Browse the repository at this point in the history
  • Loading branch information
it-vegard authored Nov 1, 2023
2 parents cd3859a + 80b42da commit a4f8207
Show file tree
Hide file tree
Showing 10 changed files with 699 additions and 748 deletions.
5 changes: 5 additions & 0 deletions .changeset/weak-dodos-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@navikt/ds-react": patch
---

Added useVirtualFocus hook - used in Combobox for now
4 changes: 2 additions & 2 deletions @navikt/core/react/src/form/combobox/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const Combobox = forwardRef<

const toggleListButtonRef = useRef<HTMLButtonElement>(null);

const { currentOption, toggleIsListOpen } = useFilteredOptionsContext();
const { activeDecendantId, toggleIsListOpen } = useFilteredOptionsContext();
const { selectedOptions } = useSelectedOptionsContext();

const {
Expand Down Expand Up @@ -92,7 +92,7 @@ export const Combobox = forwardRef<
"navds-combobox__wrapper-inner navds-text-field__input",
{
"navds-combobox__wrapper-inner--virtually-unfocused":
currentOption !== null,
activeDecendantId !== null,
}
)}
onClick={focusInput}
Expand Down
3 changes: 1 addition & 2 deletions @navikt/core/react/src/form/combobox/ComboboxProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const ComboboxProvider = forwardRef<HTMLInputElement, ComboboxProps>(
size,
}}
>
<CustomOptionsProvider>
<CustomOptionsProvider value={{ isMultiSelect }}>
<SelectedOptionsProvider
value={{
allowNewValues,
Expand All @@ -81,7 +81,6 @@ const ComboboxProvider = forwardRef<HTMLInputElement, ComboboxProps>(
filteredOptions,
isListOpen,
isLoading,
isMultiSelect,
options,
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useSelectedOptionsContext } from "../SelectedOptions/selectedOptionsCon
import { useInputContext } from "../Input/inputContext";
import { Loader } from "../../../loader";
import { BodyShort, Label } from "../../../typography";
import filteredOptionsUtil from "./filtered-options-util";

const FilteredOptions = () => {
const {
Expand All @@ -18,25 +19,25 @@ const FilteredOptions = () => {
isLoading,
isListOpen,
filteredOptions,
filteredOptionsIndex,
filteredOptionsRef,
setFilteredOptionsRef,
isMouseLastUsedInputDevice,
setIsMouseLastUsedInputDevice,
isValueNew,
setFilteredOptionsIndex,
toggleIsListOpen,
activeDecendantId,
virtualFocus,
} = useFilteredOptionsContext();
const { isMultiSelect, selectedOptions, toggleOption } =
useSelectedOptionsContext();

return (
<ul
ref={filteredOptionsRef}
ref={setFilteredOptionsRef}
className={cl("navds-combobox__list", {
"navds-combobox__list--closed": !isListOpen,
"navds-combobox__list--with-hover": isMouseLastUsedInputDevice,
})}
id={`${id}-filtered-options`}
id={filteredOptionsUtil.getFilteredOptionsId(id)}
role="listbox"
tabIndex={-1}
>
Expand All @@ -45,7 +46,8 @@ const FilteredOptions = () => {
className="navds-combobox__list-item--loading"
role="option"
aria-selected={false}
id={`${id}-is-loading`}
id={filteredOptionsUtil.getIsLoadingId(id)}
data-no-focus="true"
>
<Loader aria-label="Søker..." />
</li>
Expand All @@ -54,8 +56,12 @@ const FilteredOptions = () => {
<li
tabIndex={-1}
onMouseMove={() => {
if (filteredOptionsIndex !== -1) {
setFilteredOptionsIndex(-1);
if (
activeDecendantId !== filteredOptionsUtil.getAddNewOptionId(id)
) {
virtualFocus.moveFocusToElement(
filteredOptionsUtil.getAddNewOptionId(id)
);
setIsMouseLastUsedInputDevice(true);
}
}}
Expand All @@ -64,10 +70,10 @@ const FilteredOptions = () => {
if (!isMultiSelect && !selectedOptions.includes(value))
toggleIsListOpen(false);
}}
id={`${id}-combobox-new-option`}
id={filteredOptionsUtil.getAddNewOptionId(id)}
className={cl("navds-combobox__list-item__new-option", {
"navds-combobox__list-item__new-option--focus":
filteredOptionsIndex === -1,
activeDecendantId === filteredOptionsUtil.getAddNewOptionId(id),
})}
role="option"
aria-selected={false}
Expand All @@ -86,24 +92,30 @@ const FilteredOptions = () => {
className="navds-combobox__list-item__no-options"
role="option"
aria-selected={false}
id={`${id}-no-hits`}
id={filteredOptionsUtil.getNoHitsId(id)}
data-no-focus="true"
>
Ingen søketreff
</li>
)}
{filteredOptions.map((option, index) => (
{filteredOptions.map((option) => (
<li
className={cl("navds-combobox__list-item", {
"navds-combobox__list-item--focus": index === filteredOptionsIndex,
"navds-combobox__list-item--focus":
activeDecendantId === filteredOptionsUtil.getOptionId(id, option),
"navds-combobox__list-item--selected":
selectedOptions.includes(option),
})}
id={`${id}-option-${option.replace(" ", "-")}`}
id={filteredOptionsUtil.getOptionId(id, option)}
key={option}
tabIndex={-1}
onMouseMove={() => {
if (filteredOptionsIndex !== index) {
setFilteredOptionsIndex(index);
if (
activeDecendantId !== filteredOptionsUtil.getOptionId(id, option)
) {
virtualFocus.moveFocusToElement(
filteredOptionsUtil.getOptionId(id, option)
);
setIsMouseLastUsedInputDevice(true);
}
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const normalizeText = (text: string): string =>
typeof text === "string" ? text.toLocaleLowerCase().trim() : "";

const isPartOfText = (value, text) =>
normalizeText(text).startsWith(normalizeText(value ?? ""));

const isValueInList = (value, list) =>
list?.find((listItem) => normalizeText(value) === normalizeText(listItem));

const getMatchingValuesFromList = (value, list) =>
list?.filter((listItem) => isPartOfText(value, listItem));

const getFilteredOptionsId = (comboboxId: string) =>
`${comboboxId}-filtered-options`;

const getOptionId = (comboboxId: string, option: string) =>
`${comboboxId.toLocaleLowerCase()}-option-${option
.replace(" ", "-")
.toLocaleLowerCase()}`;

const getAddNewOptionId = (comboboxId: string) =>
`${comboboxId}-combobox-new-option`;

const getIsLoadingId = (comboboxId: string) => `${comboboxId}-is-loading`;

const getNoHitsId = (comboboxId: string) => `${comboboxId}-no-hits`;

export default {
normalizeText,
isPartOfText,
isValueInList,
getMatchingValuesFromList,
getFilteredOptionsId,
getAddNewOptionId,
getOptionId,
getIsLoadingId,
getNoHitsId,
};
Loading

0 comments on commit a4f8207

Please sign in to comment.