Skip to content

Commit 1bc9bca

Browse files
thejacksheltonwmertens
authored andcommitted
feat(combobox): focus first option when hitting down arrow
1 parent 6b435e8 commit 1bc9bca

File tree

4 files changed

+21
-24
lines changed

4 files changed

+21
-24
lines changed

apps/website/src/routes/docs/headless/(components)/combobox/examples.tsx

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212

1313
import { PreviewCodeExample } from '../../../_components/preview-code-example/preview-code-example';
1414

15-
const trainers = [
15+
const stringsExample = [
1616
'Caleb',
1717
'Olivia',
1818
'James',
@@ -25,13 +25,13 @@ const trainers = [
2525
'Elizabeth',
2626
];
2727

28-
interface Trainer {
28+
type Trainer = {
2929
testValue: string;
3030
testLabel: string;
3131
disabled: boolean;
32-
}
32+
};
3333

34-
const ALL_OPTIONS: Array<Trainer> = [
34+
const objectExample: Array<Trainer> = [
3535
{ testValue: 'alice', testLabel: 'Alice', disabled: false },
3636
{ testValue: 'joana', testLabel: 'Joana', disabled: false },
3737
{ testValue: 'malcolm', testLabel: 'Malcolm', disabled: false },
@@ -40,41 +40,39 @@ const ALL_OPTIONS: Array<Trainer> = [
4040
];
4141

4242
export const Example01 = component$(() => {
43-
// const trainersSig = useSignal(trainers);
44-
const optionsSig = useSignal(ALL_OPTIONS);
45-
const showExample = useSignal(true);
43+
const stringsExampleSig = useSignal(stringsExample);
44+
const objectExampleSig = useSignal(objectExample);
45+
const isComboboxVisibleSig = useSignal(true);
4646

4747
const onInputChange$ = $((value: string) => {
48-
optionsSig.value = ALL_OPTIONS.filter((option) => {
48+
objectExampleSig.value = objectExample.filter((option) => {
4949
return option.testLabel.toLowerCase().includes(value.toLowerCase());
5050
});
51-
52-
console.log(optionsSig.value);
5351
});
5452

5553
return (
5654
<PreviewCodeExample>
5755
<div class="flex flex-col gap-4" q:slot="actualComponent">
5856
<button
5957
onClick$={() => {
60-
showExample.value = !showExample.value;
58+
isComboboxVisibleSig.value = !isComboboxVisibleSig.value;
6159
}}
6260
>
63-
Show them
61+
Toggle Client Side
6462
</button>
65-
{showExample.value === true && (
63+
{isComboboxVisibleSig.value && (
6664
<Combobox
67-
options={optionsSig}
65+
options={objectExampleSig}
6866
onInputChange$={onInputChange$}
6967
optionValueKey="testValue"
7068
optionLabelKey="testLabel"
71-
optionComponent$={$((option: string | Trainer, index: number) => (
69+
optionComponent$={$((option: Trainer, index: number) => (
7270
<ComboboxOption
7371
index={index}
7472
option={option}
7573
class="rounded-sm px-2 hover:bg-[#496080] focus:bg-[#496080]"
7674
>
77-
{typeof option === 'string' ? option : option.testLabel}
75+
{option.testLabel}
7876
</ComboboxOption>
7977
))}
8078
class="relative"
@@ -103,13 +101,6 @@ export const Example01 = component$(() => {
103101
</ComboboxPortal>
104102
</Combobox>
105103
)}
106-
<button
107-
// onClick$={() => {
108-
// trainersSig.value = ['One', 'Two', 'Three', 'Four', 'Five'];
109-
// }}
110-
>
111-
Change them
112-
</button>
113104
</div>
114105

115106
<div q:slot="codeExample">

packages/kit-headless/src/components/combobox/combobox-context.type.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ export interface ComboboxContext {
1717
highlightedIndexSig: Signal<number>;
1818
}
1919

20+
// Whether it is a string or an object we want to be able to access the value
2021
export type Option = ComboboxContext['options']['value'][number];

packages/kit-headless/src/components/combobox/combobox-input.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@ export const ComboboxInput = component$((props: ComboboxInputProps) => {
2525
);
2626

2727
if (e.key === 'ArrowDown') {
28+
if (!context.isListboxOpenSig.value && context.highlightedIndexSig.value === -1) {
29+
context.highlightedIndexSig.value = 0;
30+
}
31+
2832
// If the listbox is already open, move down
2933
if (context.isListboxOpenSig.value) {
3034
context.highlightedIndexSig.value === context.options.value.length - 1
3135
? (context.highlightedIndexSig.value = 0)
3236
: context.highlightedIndexSig.value++;
3337
}
38+
3439
context.isListboxOpenSig.value = true;
3540
}
3641

packages/kit-headless/src/components/combobox/combobox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export type ComboboxProps = {
1515
defaultValue?: string;
1616
placeholder?: string;
1717
// filter: boolean | ((value: string) => boolean);
18-
optionComponent$?: QRL<(option: Option, index: number) => JSXNode>;
18+
optionComponent$?: QRL<(option: any, index: number) => JSXNode>;
1919
onInputChange$?: QRL<(value: string) => void>;
2020
optionValue?: string;
2121
optionTextValue?: string;

0 commit comments

Comments
 (0)