@@ -30,98 +30,100 @@ Comboboxes are the foundation of accessible autocompletes and command palettes f
3030
3131``` svelte
3232<script lang="ts">
33- import { createCombobox } from 'svelte-headlessui'
34- import Transition from 'svelte-transition'
35- import Selector from './Selector.svelte'
36- import Check from './Check.svelte'
33+ import { createCombobox } from 'svelte-headlessui'
34+ import Transition from 'svelte-transition'
35+ import Selector from '$icons/Selector.svelte'
36+ import Check from '$icons/Check.svelte'
37+ import { onMount } from 'svelte'
3738
38- // prettier-ignore
39- const people = [
40- { name: 'Wade Cooper' },
41- { name: 'Arlene Mccoy' },
42- { name: 'Devon Webb' },
43- { name: 'Tom Cook' },
44- { name: 'Tanya Fox' },
45- { name: 'Hellen Schmidt' },
46- ]
39+ // prettier-ignore
40+ const people = [
41+ { name: 'Wade Cooper' },
42+ { name: 'Arlene Mccoy' },
43+ { name: 'Devon Webb' },
44+ { name: 'Tom Cook' },
45+ { name: 'Tanya Fox' },
46+ { name: 'Hellen Schmidt' },
47+ ]
4748
48- const combobox = createCombobox({ label: 'Actions', selected: people[2] })
49+ const combobox = createCombobox({ label: 'People', selected: people[2] })
50+ onMount(combobox.open)
4951
50- function onChange(e: Event) {
51- console.log('select', (e as CustomEvent).detail.selected)
52- }
52+ function onChange(e: Event) {
53+ console.log('select', (e as CustomEvent).detail.selected)
54+ }
5355
54- $: filtered = people.filter((person) =>
55- person.name
56- .toLowerCase()
57- .replace(/\s+/g, '')
58- .includes($combobox.filter.toLowerCase().replace(/\s+/g, '')),
59- )
56+ let filtered = $derived(
57+ people.filter((person) =>
58+ person.name
59+ .toLowerCase()
60+ .replace(/\s+/g, '')
61+ .includes($combobox.filter.toLowerCase().replace(/\s+/g, '')),
62+ ),
63+ )
6064</script>
6165
62- <div class="flex w-full flex-col items-center justify-center">
63- <div class="fixed top-16 w-72">
64- <div class="relative mt-1">
65- <div
66- class="relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left text-sm shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300"
67- >
68- <input
69- use:combobox.input
70- on:change={onChange}
71- class="w-full border-none py-2 pl-3 pr-10 leading-5 text-gray-900 focus:ring-0"
72- value={$combobox.selected.name}
73- />
74- <!-- <span class="block truncate">{people[$listbox.selected].name}</span> -->
75- <button
76- use:combobox.button
77- class="absolute inset-y-0 right-0 flex items-center pr-2"
78- type="button"
79- >
80- <Selector class="h-5 w-5 text-gray-400" />
81- </button>
82- </div>
66+ <div class="fixed top-16 w-72">
67+ <div class="relative mt-1">
68+ <div
69+ class="relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left text-sm shadow-md focus:outline-hidden focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300"
70+ >
71+ <input
72+ use:combobox.input
73+ onchange={onChange}
74+ class="w-full border-none py-2 pr-10 pl-3 text-sm leading-5 text-gray-900 focus:ring-0"
75+ value={$combobox.selected?.name ?? ''}
76+ />
77+ <!-- <span class="block truncate">{people[$listbox.selected].name}</span> -->
78+ <button
79+ use:combobox.button
80+ class="absolute inset-y-0 right-0 flex items-center pr-2"
81+ type="button"
82+ >
83+ <Selector class="h-5 w-5 text-gray-400" />
84+ </button>
85+ </div>
8386
84- <Transition
85- show={$combobox.expanded}
86- leave="transition ease-in duration-100"
87- leaveFrom="opacity-100"
88- leaveTo="opacity-0"
89- on:after-leave={() => combobox.reset()}
90- >
91- <ul
92- use:combobox.items
93- class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
94- >
95- {#each filtered as value}
96- {@const active = $combobox.active === value}
97- {@const selected = $combobox.selected === value}
98- <li
99- class="relative cursor-default select-none py-2 pl-10 pr-4 {active
100- ? 'bg-teal-600 text-white'
101- : 'text-gray-900'}"
102- use:combobox.item={{ value }}
103- >
104- <span class="block truncate {selected ? 'font-medium' : 'font-normal'}"
105- >{value.name}</span
106- >
107- {#if selected}
108- <span
109- class="absolute inset-y-0 left-0 flex items-center pl-3 {active
110- ? 'text-white'
111- : 'text-teal-600'}"
112- >
113- <Check class="h-5 w-5" />
114- </span>
115- {/if}
116- </li>
117- {:else}
118- <li class="relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900">
119- <span class="block truncate font-normal">Nothing found</span>
120- </li>
121- {/each}
122- </ul>
123- </Transition>
124- </div>
125- </div>
87+ <Transition
88+ show={$combobox.expanded}
89+ leave="transition ease-in duration-100"
90+ leaveFrom="opacity-100"
91+ leaveTo="opacity-0"
92+ on:after-leave={() => combobox.reset()}
93+ >
94+ <ul
95+ use:combobox.items
96+ class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm ring-1 shadow-lg ring-black/5 focus:outline-hidden"
97+ >
98+ {#each filtered as value}
99+ {@const active = $combobox.active === value}
100+ {@const selected = $combobox.selected === value}
101+ <li
102+ class="relative cursor-default py-2 pr-4 pl-10 select-none {active
103+ ? 'bg-teal-600 text-white'
104+ : 'text-gray-900'}"
105+ use:combobox.item={{ value }}
106+ >
107+ <span class="block truncate {selected ? 'font-medium' : 'font-normal'}"
108+ >{value.name}</span
109+ >
110+ {#if selected}
111+ <span
112+ class="absolute inset-y-0 left-0 flex items-center pl-3 {active
113+ ? 'text-white'
114+ : 'text-teal-600'}"
115+ >
116+ <Check class="h-5 w-5" />
117+ </span>
118+ {/if}
119+ </li>
120+ {:else}
121+ <li class="relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900">
122+ <span class="block truncate font-normal">Nothing found</span>
123+ </li>
124+ {/each}
125+ </ul>
126+ </Transition>
127+ </div>
126128</div>
127129```
0 commit comments