Skip to content

Commit

Permalink
fix(Autocomplete): allow navigating options via keyboard
Browse files Browse the repository at this point in the history
  • Loading branch information
N00nDay committed Apr 24, 2023
1 parent a4f15d1 commit 5108f3e
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 4 deletions.
5 changes: 3 additions & 2 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ module.exports = {
},
env: {
browser: true,
es2017: true,
node: true
node: true,
es6: true,
es2021: true
}
};
1 change: 1 addition & 0 deletions src/lib/components/autocomplete/Autocomplete.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
setContext('autocomplete-name', name);
setContext('autocomplete-error', currentError);
setContext('autocomplete-value', selectedOption);
setContext('autocomplete-handleClose', handleClose);
</script>

<div
Expand Down
13 changes: 12 additions & 1 deletion src/lib/components/autocomplete/Option.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,25 @@
const handleSelect: (option: string) => void = getContext('autocomplete-handleSelect');
const value: Writable<string | undefined> = getContext('autocomplete-value');
const defaultClass = 'group text-content cursor-pointer select-none p-0.5 w-full';
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') {
e.preventDefault();
e.stopPropagation();
handleSelect(option);
}
}
const defaultClass =
'group text-content cursor-pointer select-none p-0.5 w-full !outline-none !border-none !ring-0';
$: finalClass = twMerge(defaultClass, $$props.class);
</script>

<li
class={finalClass}
use:useActions={use}
use:forwardEvents
tabindex="-1"
on:keydown={handleKeydown}
{...exclude($$props, ['use', 'class'])}
role="option"
aria-selected={$value === option}
Expand Down
44 changes: 43 additions & 1 deletion src/lib/components/autocomplete/Options.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,60 @@
<script lang="ts">
import { scale } from 'svelte/transition';
import { get_current_component } from 'svelte/internal';
import { get_current_component, getContext, onMount } from 'svelte/internal';
import { forwardEventsBuilder, useActions, type ActionArray } from '../../actions';
export let use: ActionArray = [];
import { exclude } from '../../utils/exclude';
import { twMerge } from 'tailwind-merge';
const forwardEvents = forwardEventsBuilder(get_current_component());
let list: HTMLUListElement;
// eslint-disable-next-line no-undef
let items: NodeListOf<HTMLLIElement> | never[] = [];
let focusIndex = 0;
let arrowPressedOnce = false;
const handleClose: () => void = getContext('autocomplete-handleClose');
function handleKeydown(e: KeyboardEvent) {
e.preventDefault();
e.stopPropagation();
if (e.key === 'ArrowUp') {
if (!arrowPressedOnce) {
items[focusIndex].focus();
} else {
focusIndex = focusIndex > 0 ? focusIndex - 1 : items.length - 1;
items[focusIndex].focus();
}
arrowPressedOnce = true;
} else if (e.key === 'ArrowDown') {
if (!arrowPressedOnce) {
items[focusIndex].focus();
} else {
focusIndex = focusIndex < items.length - 1 ? focusIndex + 1 : 0;
items[focusIndex].focus();
}
arrowPressedOnce = true;
} else if (e.key === 'Enter') {
console.log('Enter FIRED');
} else if (e.key === 'Escape') {
handleClose();
}
}
const defaultclass =
'origin-top-right absolute mt-1 z-10 border border-border left-0 right-0 w-full p-1 rounded-md shadow-xl py-1 bg-surface transition transform duration-150';
$: finalClass = twMerge(defaultclass, $$props.class);
onMount(() => {
items = list.querySelectorAll('li');
// items[focusIndex].focus();
});
</script>

<svelte:window on:keydown|preventDefault={handleKeydown} />

<ul
bind:this={list}
class={finalClass}
use:useActions={use}
use:forwardEvents
Expand Down

0 comments on commit 5108f3e

Please sign in to comment.