본문으로 건너뛰기

CommandPalette

애플리케이션이 할 수 있는 모든 것을 필드 하나 뒤에 둡니다. 메뉴 바가 담을 수 있는 것보다 액션이 많아진 키보드 중심 제품이 취하는 모양입니다. 어디에 두었는지 기억하는 대신, 원하는 것을 입력합니다.

tsx
import { CommandPalette } from 'neba';

<CommandPalette
  items={[
    { value: 'deploy', label: 'Deploy production', group: 'Actions', onSelect: deploy },
    { value: 'logs', label: 'Go to logs', group: 'Navigate' }
  ]}
/>;

Props

Prop타입기본값설명
items * readonly CommandItem[]팔레트가 할 수 있는 모든 것
openboolean팔레트가 열려 있는지. onOpenChange와 함께 쓰면 controlled 컴포넌트가 됩니다
defaultOpenbooleanfalse열린 채로 시작할지 (uncontrolled)
onOpenChange(open: boolean) => void열리고 닫힐 때마다 호출됩니다
onSelect(item: CommandItem) => void명령이 실행될 때, 그 명령 자신의 onSelect 뒤에 호출됩니다. 어느 쪽이든 팔레트는 닫힙니다
shortcutstring | false'Mod+K'팔레트를 여는 키. window에 바인딩됩니다. Mod는 Mac에서 Command, 그 밖에서는 Control입니다. false는 아무것도 바인딩하지 않습니다
widthnumber | string시트가 넓어질 수 있는 한계. 숫자는 px입니다
maxHeightnumber | string320목록이 스크롤되기 전까지의 높이
size공통'xs' | 'sm' | 'md' | 'lg' | 'xl''md'타입 스케일과 필드의 높이, 시트의 너비 상한
color공통'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'표시된 행과 시트의 가장자리가 띠는 색 역할
density공통'default' | 'compact''default'행의 세로 여백만 바꿉니다
localestringBCP 47 태그. placeholder와 빈 줄, dialog의 이름을 이 언어로 씁니다
placeholderstring필드의 placeholder
emptyMessageReactNode아무것도 맞지 않았을 때 행이 있었을 자리의 문구
labelstringdialog의 접근성 이름. 보이는 제목이 없습니다
classNamestring시트에 붙는 class
classNamesNebaSlots<'backdrop' | 'viewport' | 'input' | 'list' | 'group' | 'item' | 'empty'>루트 뒤에 있는 각 파트의 class. 루트 자체는 className이 맡으므로 root 키는 없습니다

CommandItem

Prop타입기본값설명
value * string명령을 식별하는 값
label * string행에 쓰이는 말이자 검색어가 대조되는 대상
descriptionReactNode라벨 아래 한 줄, 어디로 가는지, 무엇을 바꾸는지
iconReactNode라벨 앞의 글리프
shortcutstring같은 일을 하는 키. Shortcut과 같은 표기이며, 팔레트가 바인딩하지는 않습니다
groupstring이 명령이 속한 제목. group이 바뀔 때마다 제목이 그려지므로 같은 그룹은 붙여서 나열해야 합니다
keywordsreadonly string[]검색에는 쓰이지만 그려지지 않는 단어들
disabledbooleanfalse목록에는 있지만 실행되지 않습니다
onSelect() => void실행했을 때 하는 일

Menu는 한자리에 있는 짧은 목록이라 찾기 전에 이미 모든 행이 보입니다. Combobox는 값을 돌려줍니다. 이 컴포넌트는 실행되는 동작을 돌려줍니다.

예시

items · group

명령은 주어진 순서대로 그려지고, group이 바뀔 때마다 제목이 그려집니다. 그래서 한 그룹의 명령은 붙여서 나열해야 합니다. iconshortcut이 행의 양 끝을 채우고, description은 라벨 아래 한 줄이 됩니다.

keywords

검색에는 쓰이지만 화면에는 절대 그려지지 않는 단어들입니다. 같은 명령을 다른 제품이 부르는 이름, 약어, 독자가 검색했을 법한 말. undo라고 쳐서 Roll back이 나오는 것이 팔레트를 두 번 열게 만드는 이유입니다.

shortcut

팔레트를 여는 키이며 window에 바인딩됩니다. Mod는 Mac에서 Command, 그 밖에서는 Control입니다. Shortcut이 그리는 것과 같은 표기를, 쓰는 대신 읽습니다. false는 아무것도 바인딩하지 않습니다. 키보드를 직접 관리하는 애플리케이션을 위한 것입니다.

onSelect

각 명령이 자기 onSelect를 가질 수 있고, 팔레트의 onSelect는 그 뒤에 항목과 함께 호출됩니다. 어느 쪽이든 팔레트는 닫히며, 입력한 검색어는 닫히는 길에 버려집니다.

size

size는 타입 스케일과 필드의 높이, 시트가 넓어질 수 있는 한계를 정합니다. widthmaxHeight는 뒤의 두 가지를 각각 덮어씁니다.

className · classNames

className은 시트(검색 필드와 행이 놓이는 판)에 붙습니다. 그 바깥과 안쪽은 모두 classNames로 갑니다.

tsx
<CommandPalette
  items={commands}
  className="max-w-2xl"
  classNames={{ backdrop: 'backdrop-blur-none', item: 'rounded-none' }}
/>

slot은 backdrop, viewport, input, list, group, item, empty입니다. backdropviewport는 시트 바깥에 그려지므로 시트를 기준으로 쓴 것으로는 찾을 수 없고, group은 행 사이의 heading 하나이지 그 아래 행들이 아닙니다. 넘긴 class가 컴포넌트 자신의 class와 어떻게 겨루는지는 prop 규약을 보세요.

접근성

  • 시트는 label이 이름이 되는 modal dialog입니다. 보이는 제목이 따로 없습니다. 열릴 때 focus가 필드로 들어가고, 닫힐 때 독자가 있던 자리로 되돌아갑니다.
  • 필드는 listbox 위의 combobox이며, 표시된 행은 aria-activedescendant로 전달됩니다. 포인터와 방향키가 같은 표시를 움직이므로 Enter가 표시된 것 외의 행을 실행하는 일이 없습니다.
  • Escape로 닫힙니다.
  • 팔레트가 어떤 명령에 이르는 유일한 통로가 되어서는 안 됩니다. 안에 있는 모든 것은 다른 경로로도 닿을 수 있어야 합니다. 팔레트의 존재를 모르는 독자에게 다른 기회는 없습니다.

Released under the MIT License