Command palette
패키지 네임스페이스가 아니라 레시피입니다. Dialog가 팔레트를 담고, useCombobox가 입력, 필터링, 활성 옵션, id를 맡습니다. CommandPalette.* export는 없습니다.
dialog 표시 방식을 쓰고 getDialogProps()를 Dialog.Root에 펼치세요. 팔레트가 열릴 때 훅이 입력을 비우고 첫 행을 활성으로 만들며, 팔레트가 닫히는 동안 고른 명령은 다시 실행되지 않습니다. value를 null로 두고 onValueChange에서 명령을 실행하면, 명령을 골라도 선택된 것이 남지 않습니다.
const cb = useCombobox({
options: commands,
presentation: 'dialog',
value: null,
onValueChange: (value: string | null) => { if (value) run(value) },
})
useHotkey(['Control+K', 'Meta+K'], () => !cb.open && cb.setOpen(true))
<Button.Root {...cb.getTriggerProps()} aria-keyshortcuts="Control+K Meta+K">
Search commands
</Button.Root>
<Dialog.Root {...cb.getDialogProps()} aria-label="Commands">
<Field.Root id={cb.ids.input} aria-label="Command">
<Field.TextInput {...cb.getInputProps()} placeholder="Type a command" />
</Field.Root>
<OptionList.Root {...cb.getListboxProps()} hidden={cb.isEmpty}>
{cb.items.map((item) => (
<OptionList.Option key={item.id} {...cb.getOptionProps(item)} />
))}
</OptionList.Root>
<Text role="status">{cb.isEmpty ? 'No matching commands.' : ''}</Text>
</Dialog.Root>
Press Ctrl+K or ⌘K, or use the button.
단축키는 useHotkey로, Ctrl+K나 ⌘K에서 팔레트를 엽니다. 트리거의 aria-keyshortcuts가 보조 기술에 단축키를 알려 줍니다. Escape나 배경 클릭으로 대화 상자가 닫히고, 포커스는 팔레트가 열릴 때 포커스가 있던 요소로, 포커스가 없었다면 트리거로 돌아갑니다. 빈 결과 메시지는 role="status" 영역에 있어 스크린 리더가 읽어 줍니다.
언제 쓰나요
언제: 앱 전체에서 동작을 찾아 실행하는 한 곳이 필요할 때.
쓰지 않을 때: 폼 필드의 값 고르기 → Combobox 레시피. 짧고 고정된 동작 목록 → Menu.