Combobox <mv-combobox>

악센트를 구분하지 않고 필터링되는 목록, 그룹, 칩으로 표시되는 단일 또는 다중 선택, 옵션 생성, 자유 입력(자동 완성) 모드를 갖춘 검색 필드로, 양식과 연동됩니다(form-associated).

카테고리폼
유형Web Component (<mv-combobox>)
상태안정
Keywordscombobox, autocomplete, select, multiselect, tags, chips, typeahead, search, form-associated

When to use

  • A choice must be made from a long list that users would rather type to filter than scroll
  • Several values such as tags, recipients or skills are picked and shown as removable chips
  • Users may add a value that is not in the list yet, or type free text with suggestions
  • Options come from a remote source loaded as the user types

Avoid when

  • There are only a handful of options and no filtering is needed → use Select instead
  • The field is a storefront search with product thumbnails, prices and recent searches → use Search Autocomplete instead
  • The list holds app actions and navigation triggered by a keyboard shortcut → use Command instead

설치

node scripts/add.mjs combobox --out ./src/marvelous

Marvelous UI MCP 서버를 사용하는 AI 에이전트: install_components({ slugs: ["combobox"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

복사되는 파일(의존성 포함): tokens/tokens.css, core/base.css, core/dismiss.js, core/dom.js, core/element.js, core/position.js, components/combobox/combobox.js, components/combobox/combobox.css.

사용법

기본 마크업입니다. 여기서 시작해 속성, data-*, CSS 변수로 커스터마이즈하세요:

<div style="display:grid;gap:1.25rem;width:min(100%,20rem)">
  <div style="display:grid;gap:.4rem">
    <label for="combobox-demo-city" style="font-size:.875rem;font-weight:500">Departure city</label>
    <mv-combobox id="combobox-demo-city" name="city" placeholder="Search for a city…" clearable style="--mv-combobox-width:100%">
      <svg data-start viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/><circle cx="12" cy="10" r="3"/></svg>
      <optgroup label="Europe">
        <option value="london" data-hint="LHR">London</option>
        <option value="zurich" data-hint="ZRH">Zürich</option>
        <option value="berlin" data-hint="BER">Berlin</option>
      </optgroup>
      <optgroup label="Americas">
        <option value="new-york" data-hint="JFK">New York</option>
        <option value="sao-paulo" data-hint="GRU">São Paulo</option>
        <option value="montreal" data-hint="YUL">Montréal</option>
      </optgroup>
      <optgroup label="Asia-Pacific">
        <option value="tokyo" data-hint="HND">Tokyo</option>
        <option value="singapore" data-hint="SIN">Singapore</option>
        <option value="sydney" data-hint="SYD">Sydney</option>
        <option value="seoul" data-hint="ICN" disabled>Seoul (full)</option>
      </optgroup>
    </mv-combobox>
  </div>

  <div style="display:grid;gap:.4rem">
    <label for="combobox-demo-skills" style="font-size:.875rem;font-weight:500">Skills</label>
    <mv-combobox id="combobox-demo-skills" name="skills" multiple creatable placeholder="Add a skill…" style="--mv-combobox-width:100%">
      <option selected>Accessibility</option>
      <option selected>CSS</option>
      <option>JavaScript</option>
      <option>TypeScript</option>
      <option>Design systems</option>
      <option>Animation</option>
      <option>End-to-end testing</option>
      <option>SEO</option>
    </mv-combobox>
    <small style="font-size:.75rem;color:var(--mv-fg-muted)">Type a term that isn’t in the list to create it.</small>
  </div>

  <div style="display:grid;gap:.4rem">
    <label for="combobox-demo-lang" style="font-size:.875rem;font-weight:500">Language <span style="color:var(--mv-fg-subtle);font-weight:400">(free text)</span></label>
    <mv-combobox id="combobox-demo-lang" name="language" free placeholder="English, Español…" style="--mv-combobox-width:100%">
      <option>English</option><option>Français</option><option>Español</option><option>Deutsch</option><option>Italiano</option><option>Português</option><option>Nederlands</option>
    </mv-combobox>
  </div>
</div>

API

Attributes

Name유형DefaultDescription
namestringForm field name; in multiple mode, one entry per value.
valuestringInitial value (comma-separated values in multiple mode); selected as soon as its option exists, even if the options arrive later.
placeholderstringField placeholder text.
multiplebooleanMultiple selection shown as removable chips (Backspace removes the last one).
creatablebooleanOffers an “Add ‘x’” option when the input matches no option.
freebooleanAutocomplete mode: the value is the typed text, options are only suggestions.
clearablebooleanClear button once a value is chosen.
requiredbooleanNative validation (valueMissing).
disabledbooleanDisables the field.
invalidbooleanError style + aria-invalid.
loadingbooleanShows “Loading…” with a spinner in the list (async sources).
empty-textstringNo resultsMessage when nothing matches.
create-textstringAdd “{query}”Label of the create option.
placementbottom-start | top-start…bottom-startList placement (flipped when there is no room).
labelstringAccessible name without a <label for>.
data-sizesm | lgField height.

Properties

Name유형Description
valuestringValue (or text in free mode); in multiple mode, values joined by commas. A value set before its option exists is applied when the option arrives, unless the user has picked something in between.
valuesstring[]Selected values.
optionsArray<string | { value, label, group?, hint?, keywords?, disabled? }>Option source, added after the child <option>s (an option whose value is already a child is skipped). Setting it keeps the child options.
selectedOptionsobject[]Selected options (read-only).
isOpenbooleanWhether the list is open (read-only).

Methods

NameDescription
open() / close()Opens or closes the list.
clear()Clears the selection.
addOption(option)Adds an option.
focus()Focuses the field.
checkValidity() / reportValidity()Native validation.

Events

NameDescription
mv-changedetail: { value, values, option }.
mv-querydetail: { query } on every keystroke (to load remote options).
mv-createCancelable; detail: { value, label } before an option is created.
mv-open / mv-closeList opened and closed.

Content structure

NameDescription
<option> / <optgroup>Declarative options (value, label, disabled, selected, data-hint, data-keywords). They stay in the DOM, hidden, and are watched: options added, removed or edited later (Angular @for, Vue v-for, React lists) update the list.
[data-start]Icon placed at the start of the field (also when rendered after the element connects).

CSS classes

NameDescription
mv-combobox-field / -input / -chip / -popup / -option / -emptyGenerated parts.

CSS variables

NameDefaultDescription
--mv-combobox-width18remField width.
--mv-combobox-max-height16remMax list height.
--mv-combobox-radiusvar(--mv-radius-md)Field radius.

Accessibility

APG “Combobox with listbox popup” pattern: input role=combobox, aria-expanded, aria-controls, aria-autocomplete=list and aria-activedescendant (focus stays in the field). ↓/↑ open and navigate, Alt+↓ opens, Page Up/Down jump by 10, Enter selects, Escape closes then clears, Backspace removes the last chip. List role=listbox (aria-multiselectable in multiple mode), labeled role=group groups, options with aria-selected / aria-disabled. Result count and additions are announced through a polite live region.

이 페이지는 AI로 번역되었습니다. 번역 문제 신고