Command
검색 입력 + 필터된 명령 리스트(명령 팔레트 표면) — combobox + listbox를 aria-activedescendant로 연결. 검색은 label 부분 일치, 비제어(query 내부 소유).
마지막 업데이트 2026-06-11
한눈에#
Ctrl K로 여는 명령 팔레트 — 검색으로 명령을 좁히고 ↑/↓·Enter로 골라 실행합니다. 여러 액션을 모으는 단축 진입점입니다.
- 새 파일 만들기
- 프로젝트 열기
- 문서 검색
- 테마 전환
- 배포 (권한 필요)
- 설정
↑/↓로 이동(비활성 건너뜀·순환) · Enter 또는 클릭으로 선택
- ⌘K / Ctrl K 명령 팔레트
- combobox + listbox
- label 부분 일치
- 비제어 검색
입력해 필터하고 ↑/↓로 이동 후 Enter로 선택 — 포커스는 입력에 머물고 aria-activedescendant가 활성 항목을 가리킵니다
선택 결과를 보여주기 위해 데모 래퍼가 onSelect를 받습니다 — Command 자체의 검색·탐색은 핸들러 없이도 동작합니다(비제어).
사용 시점#
검색으로 좁혀 명령을 실행하는 팔레트면 Command — 검색 결과 이동이나 고정 액션 메뉴는 다른 컴포넌트입니다.
권장 — 이렇게 쓰세요
지양 — 이러지 마세요
- 새 파일 만들기
- 프로젝트 열기
- 문서 검색
- 테마 전환
- 배포 (권한 필요)
- 설정
↑/↓로 이동(비활성 건너뜀·순환) · Enter 또는 클릭으로 선택
쓴다 — ⌘K / Ctrl K 단축 진입점에서 검색으로 명령을 좁혀 ↑/↓·Enter로 실행
대신 SearchField — 결과 페이지로 이동하는 단순 검색 입력일 때
대신 SearchCommand — 문서·엔티티 검색 결과와 스니펫을 보여주는 검색 표면일 때
대신 DropdownMenu — 검색 없이 보여주는 고정 액션 메뉴일 때
플레이그라운드#
컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.
Command를 직접 조작해 보세요
속성·테마·토큰을 바꾸고 React·Flutter 코드를 확인하는 풀스크린 빌더로 엽니다.
플레이그라운드는 넓은 작업 영역이 필요해 웹·태블릿에서 편집할 수 있어요.
변형#
변형이 없습니다 — 항목 단위 disabled로 “보이지만 선택 불가” 상태를
표현합니다(키보드 탐색이 건너뛰고, 클릭·Enter가 무시됩니다). 모달 팔레트가
필요하면 Modal과 합성하세요.
크기#
단일 크기입니다 — 입력 높이 3rem, 리스트 최대 높이 20rem(초과 시 스크롤).
상태#
- 활성 항목 —
aria-activedescendant대상,color.surface-hover배경 - 빈 결과 — 일치 항목이 없으면 리스트 대신
emptyText를role="status"로 표시(검색어를 바꾸면 복귀) - Focus — 루트
:focus-within에input.border-focus보더 + 18% 링 - Disabled 항목 —
color.disabled-fg잉크 + 커서 차단
Props#
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
items | readonly CommandItem[] | — | { value, label, disabled? } 배열 — label이 검색 대상 |
onSelect | (value: string) => void | — | 항목 선택 콜백 (Enter 또는 클릭) |
placeholder | string | 검색어를 입력하세요 | 검색 입력 플레이스홀더 |
searchLabel | string | 명령 검색 | 검색 입력의 aria-label |
emptyText | string | 결과가 없습니다 | 빈 결과 문구 |
className | string | — | 루트(div)에 적용 |
ref | Ref<HTMLInputElement> | — | 검색 <input> 요소로 직접 전달되는 ref (React 19 ref-as-prop) |
접근성#
입력이 role="combobox" + aria-autocomplete="list", 리스트가
role="listbox"입니다. 포커스는 입력에 머물고 aria-activedescendant가
활성 항목 id를 가리킵니다(클릭도 mousedown을 막아 입력 포커스 유지).
| 키 | 동작 |
|---|---|
| 문자 입력 | label 부분 일치(대소문자 무시) 필터 — 활성 항목은 첫 활성 매치로 리셋 |
↓ / ↑ | 활성 항목 순환 이동 — 비활성 항목 건너뜀 |
Enter | 활성 항목 선택 — onSelect(value) 호출(빈 결과면 무시) |
- 활성 항목은
aria-selected, 비활성 항목은aria-disabled로 보고 - 빈 결과는
role="status"라이브 영역 — 필터 결과 소멸을 보조기술에 알림 - 검색 대상은
label텍스트 — 약어 별칭 검색은 지원하지 않습니다
토큰#
component 토큰 없이 Input의 component 토큰(input.border-focus)과 semantic을
직접 소비합니다(신설 기준 §4 미충족).
| 속성 | 토큰 |
|---|---|
| 루트 | color.surface + color.border · radius.lg · shadow.sm |
| 포커스 링 | input.border-focus + color.primary 18% 링 (:focus-within) |
| 검색 입력 | font.size-body-1 · placeholder color.text-placeholder |
| 검색 아이콘 | icon.size-md · color.text-muted |
| 항목 | font.size-body-2 · hover/활성 color.surface-hover · pressed color.surface-pressed |
| 비활성 항목 | color.disabled-fg |
| 빈 결과 | color.text-muted · 패딩 space.8 |
| 모션 | duration.fast + ease.standard |