J3W1 / DESIGN SYSTEM
List
A selectable list of rows (an APG listbox) in single or multiple selection; the selected row is the selection fill with a check glyph and an optional metadata column.
stable · LIGHT DOM · 1.1.0
Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.
Live variants
single
- default
- extended
- high-contrast
<j3w1-list id="example-list-single"><ul class="list" role="listbox" aria-label="Profiles">
<li class="list-option" role="option" aria-selected="true" tabindex="0"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">default</span></li>
<li class="list-option list-option-demo-target" role="option" aria-selected="false" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">extended</span></li>
<li class="list-option" role="option" aria-selected="false" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">high-contrast</span></li>
<li class="list-option" role="option" aria-selected="false" aria-disabled="true" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">print</span></li>
</ul></j3w1-list>multi
- FX-320 reflow
- FX-ZOOM-200 text zoom
- FX-RM reduced motion
- FX-TOUCH pointer
<j3w1-list id="example-list-multi"><ul class="list" role="listbox" aria-label="Fixtures" aria-multiselectable="true">
<li class="list-option" role="option" aria-selected="true" tabindex="0"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">FX-320 reflow</span></li>
<li class="list-option list-option-demo-target" role="option" aria-selected="false" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">FX-ZOOM-200 text zoom</span></li>
<li class="list-option" role="option" aria-selected="true" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">FX-RM reduced motion</span></li>
<li class="list-option" role="option" aria-selected="false" aria-disabled="true" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">FX-TOUCH pointer</span></li>
</ul></j3w1-list>with-meta
- text-field
- tabs
- menu
- chart
<j3w1-list id="example-list-with-meta"><ul class="list" role="listbox" aria-label="Components">
<li class="list-option" role="option" aria-selected="true" tabindex="0"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">text-field</span><span class="list-meta">14 states</span></li>
<li class="list-option list-option-demo-target" role="option" aria-selected="false" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">tabs</span><span class="list-meta">7 states</span></li>
<li class="list-option" role="option" aria-selected="false" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">menu</span><span class="list-meta">8 states</span></li>
<li class="list-option" role="option" aria-selected="false" aria-disabled="true" tabindex="-1"><span class="list-check" aria-hidden="true">✓</span><span class="list-label">chart</span><span class="list-meta">R2</span></li>
</ul></j3w1-list>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.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/list.css';
import '@j3w1/ui/register/list';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.
Copy the complete implementation
npx --package=@j3w1/ui@1.1.0 j3w1-ui copy list --out ./vendor/j3w1/listThe 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
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
events
| Name | Type / signature | Meaning |
|---|
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
Lets the user choose one or several rows from a short, visible set. A list is a listbox: it holds a selection, it does not navigate. Rows that lead somewhere are sidebar-nav; rows with columns are a table; a long set that needs filtering is a combobox.
Anatomy
A ul with role="listbox" framed by 1px color.border.control on
color.surface.default. Each option is one row: a check gutter, the label in
color.text.default, and in the metadata variant a trailing column in
color.text.muted. Rows are separated by 1px color.border.divider. A
selected row is filled with color.interaction.selection.bg; every part of
it, including the metadata and the ✓ glyph, takes
color.interaction.selection.text.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | text color.text.default; no fill; the check gutter empty | — |
| hover | background → color.interaction.hover.bg | cursor: pointer |
| focus-visible | ring 1px dashed color.interaction.focus.ring at −2px on the option | the ring |
| selected | fill color.interaction.selection.bg; text and glyph color.interaction.selection.text | aria-selected="true"; the ✓ glyph |
| selected+focus-visible | the fill and the ring in color.interaction.focus.ring-container | both visible at once |
| selected+container-inactive | fill color.interaction.selection.inactive-bg with color.interaction.selection.inactive-text; no ring | lightness drop between the two fills; the glyph stays |
| disabled | text color.text.disabled; no fill; no hover; still reachable by arrow keys | aria-disabled="true"; cursor: not-allowed |
Precedence: disabled > selected > hover; focus-visible is always drawn.
Keyboard
Roving tabindex: the selected option (or the first) has tabindex="0", the
rest -1, so the list costs one tab stop. Up and Down move; in single
selection the selection follows focus, in multiple selection Space toggles
and Shift with the arrows extends. Home and End jump; Ctrl+A selects all in a
multi-select list; typing jumps to the next matching label. Disabled options
are reachable and announced, never skipped silently.
Accessibility
aria-label or aria-labelledby on the listbox; aria-multiselectable
when several may be chosen; aria-selected on every option, including
"false". The ✓ glyph is aria-hidden; aria-selected is the state.
Metadata is inside the option so it is read with the label. Contrast: text
8.43:1, metadata 5.66:1, selected text 12.47:1 on the fill, inactive selection
7.02:1, ring 4.57:1 on the surface and 7.48:1 on the fill, frame 4.33:1. Rows
are at least 24 CSS pixels tall with the check gutter as the leading target
area.
Portability
Rows with a background, a glyph gutter and an outline; nothing else. Hosts
with a native list view take the fill, the inactive fill and the divider
colour and keep their keyboard model. The inactive fill applies when the
list’s window or pane loses focus, which a web page detects through
:focus-within on the pane.
Non-examples
A selected row marked by a border or a check alone without the fill. Rounded row highlights. Muted metadata left on the selection fill. A list where every row is a tab stop. A list that navigates on selection. Disabled rows removed from the arrow-key order. Hover that changes the text colour. A list without a frame on the canvas.