A headless, accessible, typeahead-enabled dropdown component for Svelte 5.
npm install svelte-headless-dropdown
<script>
import { Dropdown, DropdownItem } from 'svelte-headless-dropdown';
let isOpen = $state(false);
let selectedValue = $state('');
const items = ['Option 1', 'Option 2', 'Option 3'];
function handleSelect(value) {
selectedValue = value;
console.log('Selected:', value);
}
</script>
<Dropdown
{isOpen}
onclick={(open) => isOpen = open}
onSelect={handleSelect}
>
<svelte:fragment slot="trigger">
<button type="button">
{selectedValue || 'Select an option'}
</button>
</svelte:fragment>
<svelte:fragment slot="items">
{#each items as item}
<DropdownItem {value: item} />
{/each}
</svelte:fragment>
</Dropdown>
<script>
import { Dropdown, DropdownItem } from 'svelte-headless-dropdown';
let isOpen = $state(false);
let selectedUser = $state(null);
const users = [
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' },
{ id: 3, name: 'Bob Johnson', email: '[email protected]' },
];
</script>
<Dropdown
{isOpen}
onclick={(open) => (isOpen = open)}
onSelect={(user) => (selectedUser = user)}>
<svelte:fragment slot="trigger">
<button type="button">
{selectedUser?.name || 'Select a user'}
</button>
</svelte:fragment>
<svelte:fragment slot="items">
{#each users as user}
<DropdownItem value={user} displayKey="name" />
{/each}
</svelte:fragment>
</Dropdown>
<Dropdown
{isOpen}
onclick={(open) => (isOpen = open)}
containerClass="my-dropdown"
listClass="my-dropdown-list">
<!-- content -->
</Dropdown>
Prop | Type | Default | Description |
---|---|---|---|
open |
boolean |
- | Whether the dropdown is open |
onclick |
(open: boolean) => void |
- | Callback when dropdown state changes |
onSelect |
(value: string | object) => void |
- | Callback when an item is selected |
containerClass |
string |
'' |
CSS class for the container |
listClass |
string |
'' |
CSS class for the dropdown list |
Prop | Type | Default | Description |
---|---|---|---|
value |
string | object |
- | The value of the item |
displayKey |
string |
- | Key to display when value is an object |
children |
any |
- | Custom content for the item |
The component comes with minimal default styles. You can customize the appearance using CSS classes:
.my-dropdown {
position: relative;
display: inline-block;
}
.my-dropdown-list {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.dropdown-item {
padding: 8px 12px;
cursor: pointer;
}
.dropdown-item:hover,
.dropdown-item.focused {
background-color: #f0f0f0;
}
MIT