j3w1 / SelectVue · HTML · React · Astro

J3W1 / DESIGN SYSTEM

Select

A themed single-choice combobox or multiple-choice list backed by a native select for forms and the no-JavaScript fallback.

stable · LIGHT DOM · 1.1.0

Theme-owned combobox/listbox presentation backed by the original native select for FormData, constraints, defaults and reset. The native control is visible only before enhancement or without JavaScript.

Live variants

default

New windows open here.

✕ Choose a workspace.

<j3w1-select id="example-select-default"><div class="select">
  <label class="select-label" for="example-select-default-sel-workspace">Workspace <span class="select-required" aria-hidden="true">*</span><span class="select-required sr-only"> required</span></label>
  <div class="select-root">
    <select class="select-control" id="example-select-default-sel-workspace" aria-describedby="example-select-default-sel-workspace-help example-select-default-sel-workspace-message" name="example-select-default-sel-workspace">
      <option value="">Choose a workspace</option>
      <option value="1" selected="">1: terminal</option>
      <option value="2">2: editor</option>
      <option value="3">3: browser</option>
    </select>
    <svg class="select-chevron" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M4 6.5l4 4 4-4"></path></svg>
  </div>
  <p class="select-help" id="example-select-default-sel-workspace-help">New windows open here.</p>
  <p class="select-message" id="example-select-default-sel-workspace-message">✕ Choose a workspace.</p>
</div></j3w1-select>

with-groups

Fallbacks use recorded size-adjust metrics.

✕ That font is not installed.

<j3w1-select id="example-select-with-groups"><div class="select">
  <label class="select-label" for="example-select-with-groups-sel-font">Font <span class="select-required" aria-hidden="true">*</span><span class="select-required sr-only"> required</span></label>
  <div class="select-root">
    <select class="select-control" id="example-select-with-groups-sel-font" aria-describedby="example-select-with-groups-sel-font-help example-select-with-groups-sel-font-message" name="example-select-with-groups-sel-font">
      <optgroup label="Installed">
        <option value="scp" selected="">SauceCodePro NFM</option>
        <option value="cascadia">Cascadia Mono</option>
      </optgroup>
      <optgroup label="Fallbacks">
        <option value="consolas">Consolas</option>
        <option value="dejavu">DejaVu Sans Mono</option>
      </optgroup>
    </select>
    <svg class="select-chevron" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M4 6.5l4 4 4-4"></path></svg>
  </div>
  <p class="select-help" id="example-select-with-groups-sel-font-help">Fallbacks use recorded size-adjust metrics.</p>
  <p class="select-message" id="example-select-with-groups-sel-font-message">✕ That font is not installed.</p>
</div></j3w1-select>

multiple

Click or Space toggles an option; Shift+arrows selects a range. The native fallback uses Ctrl/Command+click.

✕ Choose at least one output.

<j3w1-select id="example-select-multiple"><div class="select">
  <label class="select-label" for="example-select-multiple-sel-outputs">Outputs <span class="select-required" aria-hidden="true">*</span><span class="select-required sr-only"> required</span></label>
  <div class="select-root">
    <select class="select-control select-control-multiple" id="example-select-multiple-sel-outputs" multiple="" size="4" aria-describedby="example-select-multiple-sel-outputs-help example-select-multiple-sel-outputs-message" name="example-select-multiple-sel-outputs">
      <option value="dp1" selected="">DP-1 (2560×1440)</option>
      <option value="dp2" selected="">DP-2 (2560×1440)</option>
      <option value="hdmi">HDMI-1 (1920×1080)</option>
      <option value="edp">eDP-1 (laptop)</option>
    </select>
  </div>
  <p class="select-help" id="example-select-multiple-sel-outputs-help">Click or Space toggles an option; Shift+arrows selects a range. The native fallback uses Ctrl/Command+click.</p>
  <p class="select-message" id="example-select-multiple-sel-outputs-message">✕ Choose at least one output.</p>
</div></j3w1-select>

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

npm install --save-exact @j3w1/ui@1.1.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/select.css';
import '@j3w1/ui/register/select';

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@1.1.0 j3w1-ui copy select --out ./vendor/j3w1/select

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

Public API

attributes

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.
valueCustomEventForwards value to the primary native control.
requiredCustomEventForwards required to the primary native control.
readonlyCustomEventForwards readonly to the primary native control.
checkedCustomEventForwards checked to the primary native control.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.
valuestringPrimary native value; assignment does not fabricate user events.
checkedbooleanNative checkbox state.
requiredbooleanNative required constraint.
readOnlybooleanNative readonly property.
formHTMLFormElement | nullOwning native form. Read only.
valuesstring[]Selected values of a multiple native select.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.
checkValidity(): booleanCheck owned native constraints.
reportValidity(): booleanReport the first invalid owned control.
clear(): voidClear an editable primary input and emit native input/change.

events

NameType / signatureMeaning
j3w1-changeCustomEventNative change from an owned control, alongside the original native event.

Dependencies and verification

Registered components: none. Style dependencies: none.

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

Full implementation manifest, API and token dependency closure

Canonical specification

Purpose

Choosing one option, or several, from a fixed list. D-025 requires theme-owned choice surfaces in web applications. The native select remains the form-value and constraint source. A searchable or asynchronous list is the separate combobox component.

Anatomy

Label above; a theme-owned trigger and listbox for single choices, or an always-visible multiselectable listbox. Each selected option has a check mark and the canonical selection fill. The hidden native <select> retains its name, options, current values and defaults. Help and validation are linked to the visible control. Without JavaScript the original native control is visible.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; value color.text.default; chevron color.icon.defaultthe chevron
hoverbackground → color.interaction.hover.bg; border unchangedcursor: default; hover-capable pointers only
focus-visibleborder → color.border.active; ring 1px dashed color.interaction.focus.ring at −2pxthe ring
required* after the label in color.status.danger.text plus visually hidden “required”required; the mark
invalidborder 2px color.status.danger.border; message with the ✕ glyphborder width 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and the ring in color.interaction.focus.ring-container at −4pxdouble boundary
disabledtext and chevron color.text.disabled; border color.border.disabled; background color.interaction.disabled.bgdisabled; cursor: not-allowed

Inside the theme-owned list, a selected option is color.interaction.selection.bg with color.interaction.selection.text and group labels are color.text.muted on color.surface.raised. Precedence: disabled > invalid > hover; focus-visible is always drawn.

Keyboard

The single control follows the select-only combobox pattern: arrows open and move the active option, Home/End reach the ends, typing finds an option, and Enter/Space commits. Escape and Tab close without committing. Multiple choices use arrows, Space or click to toggle, Shift with arrows for a range, and Ctrl/Command+A to select or clear all enabled choices. No modifier is required for ordinary multiple selection. The native fallback uses host keyboard behavior.

Accessibility

A programmatic label is required; the first option is a real choice or a placeholder option that is disabled and selected with text such as “Choose a workspace”, never an empty string. aria-invalid="true" only after interaction or submit. Help and message through aria-describedby. The themed popup uses the declared contrast roles. The visible control receives the label, required/invalid state and descriptions. A failed native constraint focuses that visible control and exposes a theme-owned error. Disabled options, optgroups and fieldsets remain unavailable. Current values and defaults survive reconnection, programmatic updates and form reset. Automated evidence records its actual environments; it does not imply a manual screen-reader pass.

Portability

Use the packaged behavior and complete copy closure for web implementations. The supported enhancement can apply the same renderer to existing selects without moving them or duplicating form values. Native platforms keep the mappings listed above; no-JavaScript pages expose the native fallback.

Non-examples

An unthemed browser popup presented as a fully themed implementation. A background-image chevron in a literal colour. Rounded corners. A select whose first option is blank. A select that triggers navigation on change. Invalid shown by colour alone. A glow instead of the ring. Disabling by opacity.

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • DEMO Vue application demo
  • SPEC Complete UI theme specification