Command Menu
Dialog와 입력 필드를 조합해 빠른 이동과 작업 실행을 위한 미니 command menu를 구성합니다.
빠른 명령
작업 이름이나 설명을 입력해 후보를 좁혀 보세요.
대시보드 열기 오늘의 핵심 지표로 이동해요. G D
새 리포트 만들기 빈 리포트 초안을 시작해요. N R
팀 초대 워크스페이스 멤버를 추가해요. I T
토큰 문서 보기 디자인 토큰 기준을 확인해요. G T
<script lang="ts">
import * as Combobox from '@odbd/svelte/combobox'
import { useListCollection } from '@odbd/svelte/combobox'
import * as Dialog from '@odbd/svelte/dialog'
interface Command {
value: string
title: string
description: string
shortcut: string
}
const commands: Command[] = [
{
value: 'dashboard',
title: '대시보드 열기',
description: '오늘의 핵심 지표로 이동해요.',
shortcut: 'G D',
},
{
value: 'new-report',
title: '새 리포트 만들기',
description: '빈 리포트 초안을 시작해요.',
shortcut: 'N R',
},
{
value: 'invite',
title: '팀 초대',
description: '워크스페이스 멤버를 추가해요.',
shortcut: 'I T',
},
{
value: 'tokens',
title: '토큰 문서 보기',
description: '디자인 토큰 기준을 확인해요.',
shortcut: 'G T',
},
]
let dialogOpen = $state(false)
// 커맨드 팔레트는 목록이 항상 펼쳐진 combobox다 — 필터·하이라이트·방향키·
// Enter 선택을 머신이 제공하므로 수제 리스트로 만들지 않는다.
const palette = useListCollection({
initialItems: commands,
itemToString: (item: Command) => item.title,
itemToValue: (item: Command) => item.value,
filter: (itemText: string, filterText: string) =>
itemText.toLowerCase().includes(filterText.toLowerCase()),
})
</script>
<Dialog.Root
open={dialogOpen}
onOpenChange={(details: { open: boolean }) => (dialogOpen = details.open)}
>
<Dialog.Trigger class="odbd-button" data-variant="solid" data-size="md">
명령 메뉴 열기
</Dialog.Trigger>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content class="examples-command">
<div>
<Dialog.Title>빠른 명령</Dialog.Title>
<Dialog.Description>작업 이름이나 설명을 입력해 후보를 좁혀 보세요.</Dialog.Description>
</div>
<Combobox.Root
collection={palette.collection()}
open
inputBehavior="autohighlight"
selectionBehavior="clear"
onInputValueChange={(details: { inputValue: string }) => palette.filter(details.inputValue)}
onValueChange={() => (dialogOpen = false)}
>
<Combobox.Control>
<Combobox.Input
class="examples-command__search"
placeholder="명령을 검색하세요"
aria-label="명령 검색"
/>
</Combobox.Control>
<Combobox.Content class="examples-command__list">
<Combobox.List>
<Combobox.Empty class="examples-command__empty">일치하는 명령이 없어요.</Combobox.Empty>
{#each palette.collection().items as command (command.value)}
<Combobox.Item item={command} class="examples-command__item">
<span>
<strong>{command.title}</strong>
<small>{command.description}</small>
</span>
<kbd>{command.shortcut}</kbd>
</Combobox.Item>
{/each}
</Combobox.List>
</Combobox.Content>
</Combobox.Root>
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>