<script lang="ts">
import { Plus } from 'phosphor-svelte';
import { Button, DropdownMenu } from 'kumo-svelte';
</script>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button icon={Plus}>Add</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item>Worker</DropdownMenu.Item>
<DropdownMenu.Item>Pages</DropdownMenu.Item>
<DropdownMenu.Item>KV Namespace</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu> Installation
Barrel
import { DropdownMenu } from 'kumo-svelte'; Granular
import { DropdownMenu } from 'kumo-svelte/components/dropdown-menu';Usage
<script> import { DropdownMenu, Button } from "kumo-svelte";</script><DropdownMenu> <DropdownMenu.Trigger> {#snippet child({ props })} <Button {...props}>Menu</Button> {/snippet} </DropdownMenu.Trigger> <DropdownMenu.Content> <DropdownMenu.Item onSelect={() => console.log("edit")}> Edit </DropdownMenu.Item> <DropdownMenu.Item onSelect={() => console.log("duplicate")}> Duplicate </DropdownMenu.Item> <DropdownMenu.Separator /> <DropdownMenu.Item variant="danger" onSelect={() => console.log("delete")} > Delete </DropdownMenu.Item> </DropdownMenu.Content></DropdownMenu>Examples
Basic Dropdown
<script lang="ts">
import { Plus } from 'phosphor-svelte';
import { Button, DropdownMenu } from 'kumo-svelte';
</script>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button icon={Plus}>Add</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item>Worker</DropdownMenu.Item>
<DropdownMenu.Item>Pages</DropdownMenu.Item>
<DropdownMenu.Item>KV Namespace</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu> Inset Items
Use inset on items without an icon to align their text with items that have one.
<script lang="ts">
import { Copy, PencilSimple, Trash } from 'phosphor-svelte';
import { Button, DropdownMenu } from 'kumo-svelte';
</script>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button>Edit</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item icon={PencilSimple}>Rename</DropdownMenu.Item>
<DropdownMenu.Item icon={Copy}>Duplicate</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item inset>Move to folder</DropdownMenu.Item>
<DropdownMenu.Item inset>Add to favorites</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item icon={Trash} variant="danger">Delete</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu> Handling Item Clicks
Use onSelect on DropdownMenu.Item to handle actions. Each item receives a standard menu select event handler.
<script lang="ts">
import { Copy, PencilSimple, Trash } from 'phosphor-svelte';
import { Button, DropdownMenu } from 'kumo-svelte';
let lastAction = $state<string | null>(null);
</script>
<div class="flex flex-col items-start gap-2">
<DropdownMenu>
<DropdownMenu.Trigger>
<Button>Actions</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item icon={Copy} onSelect={() => (lastAction = 'Duplicated')}>
Duplicate
</DropdownMenu.Item>
<DropdownMenu.Item icon={PencilSimple} onSelect={() => (lastAction = 'Renamed')}>
Rename
</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item icon={Trash} variant="danger" onSelect={() => (lastAction = 'Deleted')}>
Delete
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
{#if lastAction}
<p class="text-sm text-kumo-subtle">
Last action: <span class="text-kumo-default">{lastAction}</span>
</p>
{/if}
</div> Checkbox Items
Use DropdownMenu.CheckboxItem for toggleable options that can be
independently checked or unchecked.
<script lang="ts">
import { Button, DropdownMenu } from 'kumo-svelte';
let showSidebar = $state(true);
let showLineNumbers = $state(false);
let wordWrap = $state(true);
</script>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button>View Options</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
<DropdownMenu.Label>Display</DropdownMenu.Label>
<DropdownMenu.CheckboxItem bind:checked={showSidebar}>Show sidebar</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem bind:checked={showLineNumbers}>Show line numbers</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem bind:checked={wordWrap}>Word wrap</DropdownMenu.CheckboxItem>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu> Nested Menu with Radio Selection
Use DropdownMenu.Sub, DropdownMenu.SubTrigger, and DropdownMenu.SubContent to create nested submenus. For single-selection
lists like language or timezone, use DropdownMenu.RadioGroup and DropdownMenu.RadioItem.
<script lang="ts">
import { CreditCard, Moon, SignOut, User } from 'phosphor-svelte';
import { Button, DropdownMenu } from 'kumo-svelte';
const languages = [
{ code: 'de', label: 'Deutsch' },
{ code: 'en', label: 'English' },
{ code: 'es', label: 'Español' },
{ code: 'fr', label: 'Français' },
{ code: 'it', label: 'Italiano' },
{ code: 'pt', label: 'Português' },
{ code: 'ko', label: '한국어' },
{ code: 'ja', label: '日本語' },
{ code: 'zh-CN', label: '简体中文' },
{ code: 'zh-TW', label: '繁體中文' }
];
const timezones = [
{ value: 'America/Los_Angeles', label: 'Pacific Time (PT)' },
{ value: 'America/Denver', label: 'Mountain Time (MT)' },
{ value: 'America/Chicago', label: 'Central Time (CT)' },
{ value: 'America/New_York', label: 'Eastern Time (ET)' },
{ value: 'Europe/London', label: 'Greenwich Mean Time (GMT)' },
{ value: 'Europe/Paris', label: 'Central European Time (CET)' },
{ value: 'Asia/Tokyo', label: 'Japan Standard Time (JST)' }
];
let language = $state('en');
let timezone = $state('America/Los_Angeles');
</script>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button icon={User}>Account</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item icon={User}>Profile</DropdownMenu.Item>
<DropdownMenu.Item icon={CreditCard}>Billing</DropdownMenu.Item>
<DropdownMenu.Item icon={Moon}>Dark mode</DropdownMenu.Item>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>Language</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Group>
<DropdownMenu.RadioGroup bind:value={language}>
{#each languages as lang}
<DropdownMenu.RadioItem value={lang.code}>
{lang.label}
<DropdownMenu.RadioItemIndicator />
</DropdownMenu.RadioItem>
{/each}
</DropdownMenu.RadioGroup>
</DropdownMenu.Group>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>Set Timezone</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Group>
<DropdownMenu.RadioGroup bind:value={timezone}>
{#each timezones as tz}
<DropdownMenu.RadioItem value={tz.value}>
{tz.label}
<DropdownMenu.RadioItemIndicator />
</DropdownMenu.RadioItem>
{/each}
</DropdownMenu.RadioGroup>
</DropdownMenu.Group>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Separator />
<DropdownMenu.Item icon={SignOut} variant="danger">Log out</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu> Custom Trigger with Avatar
Use the child snippet to customize the trigger element while passing children
to render inside it. This is useful when you need a non-button trigger (like
an avatar) wrapped in an accessible button element.
<script lang="ts">
import { Gear, SignOut, User } from 'phosphor-svelte';
import { DropdownMenu } from 'kumo-svelte';
</script>
<DropdownMenu>
<DropdownMenu.Trigger>
<button type="button" class="rounded-full">
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-kumo-brand text-sm font-medium text-white">
MR
</span>
</button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item icon={User}>Profile</DropdownMenu.Item>
<DropdownMenu.Item icon={Gear}>Settings</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item icon={SignOut} variant="danger">Log out</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu> Navigation Links
Use DropdownMenu.LinkItem for menu items that navigate to a URL.
This renders a semantic <a> element with full control over link attributes like target and rel.
<script lang="ts">
import { ArrowSquareOut, BookOpen, Gear } from 'phosphor-svelte';
import { Button, DropdownMenu } from 'kumo-svelte';
</script>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button>Resources</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.LinkItem href="/settings" icon={Gear}>
Settings
</DropdownMenu.LinkItem>
<DropdownMenu.LinkItem href="/docs" icon={BookOpen}>
Documentation
</DropdownMenu.LinkItem>
<DropdownMenu.Separator />
<DropdownMenu.LinkItem
href="https://developers.cloudflare.com"
target="_blank"
icon={ArrowSquareOut}
>
Developer Docs
</DropdownMenu.LinkItem>
</DropdownMenu.Content>
</DropdownMenu> API Reference
DropdownMenu
Root component that manages the dropdown state.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | Snippet | - | Child snippet rendered by the component. |
| open | boolean | false | Controlled open state. |
| onOpenChange | (open: boolean) => void | - | Called when open state changes. |
DropdownMenu.Trigger
Button that opens the dropdown when clicked.
| Prop | Type | Default | Description |
|---|---|---|---|
| child | Snippet<[{ props: Record<string, unknown> }]> | - | child prop. |
| type | 'button' | 'submit' | 'reset' | "button" | Element or semantic type. |
DropdownMenu.Item
Individual menu item for actions.
| Prop | Type | Default | Description |
|---|---|---|---|
| href | string | - | Deprecated destination URL for legacy link items. |
| icon | Component | - | Icon rendered by the component. |
| variant | 'default' | 'danger' | "default" | Visual variant. |
| selected | boolean | false | Shows a trailing selected check indicator. |
| inset | boolean | false | Indents the item content. |
| disabled | boolean | - | Disables the component. |
DropdownMenu.LinkItem
A menu item that navigates to a URL. Renders a semantic <a> element. Use this instead of Item for navigation links.
| Prop | Type | Default | Description |
|---|---|---|---|
| href | string | - | Deprecated destination URL for legacy link items. |
| icon | Component | - | Icon rendered by the component. |
| variant | 'default' | 'danger' | "default" | Visual variant. |
| selected | boolean | false | Shows a trailing selected check indicator. |
| inset | boolean | false | Indents the item content. |
| disabled | boolean | - | Disables the component. |
DropdownMenu.CheckboxItem
A menu item that can be toggled on or off. Use for independent boolean options.
| Prop | Type | Default | Description |
|---|---|---|---|
| checked | boolean | false | Checked state. |
| onCheckedChange | (checked: boolean) => void | - | Called when checked changes. |
DropdownMenu.Sub
Root component for a nested submenu. Wrap SubTrigger and SubContent inside this.
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | false | Controlled open state. |
| onOpenChange | (open: boolean) => void | - | Called when open state changes. |
DropdownMenu.SubTrigger
Menu item that opens a nested submenu when hovered or clicked. Displays a caret icon automatically.
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | Component | - | Icon rendered by the component. |
| inset | boolean | false | Indents the item content. |
DropdownMenu.SubContent
Container for submenu items. Positioned relative to the SubTrigger.
| Prop | Type | Default | Description |
|---|---|---|---|
| sideOffset | number | 8 | Distance from the anchor. |
| side | 'top' | 'right' | 'bottom' | 'left' | - | Preferred floating side. |
| align | 'start' | 'center' | 'end' | - | Floating alignment. |
| container | HTMLElement | string | document.body | Portal container for custom roots or Shadow DOM. |
DropdownMenu.Separator
A visual divider between menu items.
| Prop | Type | Default | Description |
|---|---|---|---|
| No component-specific props. Accepts standard HTML attributes. | |||
DropdownMenu.RadioGroup
Groups radio items for single-selection behavior. Only one item can be selected at a time.
| Prop | Type | Default | Description |
|---|---|---|---|
| No component-specific props. Accepts standard HTML attributes. | |||
DropdownMenu.RadioItem
A menu item that works like a radio button. Must be used inside a RadioGroup.
| Prop | Type | Default | Description |
|---|---|---|---|
| value * | string | - | Controlled value. |
| icon | Component | - | Icon rendered by the component. |
| inset | boolean | false | Indents the item content. |
DropdownMenu.RadioItemIndicator
Shows the selected state for a RadioItem. Displays a checkmark by default.
| Prop | Type | Default | Description |
|---|---|---|---|
| No component-specific props. Accepts standard HTML attributes. | |||