LearnNewsExamplesServices
Frontmatter
id17312
titleBuild form.field.Chip as a real multi-select over list.Chip
stateClosed
labels
enhancementaicore
assigneesneo-gpt
createdAtAug 17, 2026, 8:21 PM
updatedAtAug 25, 2026, 10:10 AM
githubUrlhttps://github.com/neomjs/neo/issues/17312
authorneo-fable-clio
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 25, 2026, 10:10 AM

Build form.field.Chip as a real multi-select over list.Chip

Closed Backlog/active-chunk-17 enhancementaicore
neo-fable-clio
neo-fable-clio commented on Aug 17, 2026, 8:21 PM

Context

Operator code-read (2026-08-17, while the compose-surface work surfaced the need): "while list.Chip looks pretty advanced, form.field.Chip was never finished => just extending a combobox with listConfig => useCheckboxes: true. now this would be real engine work." Verified in source — the assessment is exact.

The immediate consumer waiting on it: #17311 (operator compose recipients want removable-chip multi-select); the in-code comment there already documents the gap from the consumer side: the ComboBox/Chip primitive "collapses its value to one scalar (getSelection()[0]) and cannot express 'several peers'".

The Problem

src/form/field/Chip.mjs is 29 lines: class Chip extends ComboBox + className/ntype + listConfig: {useCheckBoxes: true}. Nothing else. No chip rendering of selected values, no multi-value model, no per-chip remove, no keyboard interaction — a ComboBox costume whose dropdown shows checkboxes while the FIELD half of "chip field" does not exist.

Meanwhile src/list/Chip.mjs (107 lines) is the finished rendering substrate: ComponentList-based, component itemDefaults, stacked_ mode, proper neo-chip-list cls chain — and the field never composes it.

The Architectural Reality

  • form.field.ComboBox's value contract is scalar — the base the stub extends structurally cannot carry "several selected records".
  • list.Chip already solves chip RENDERING; what is missing is the FIELD: an array-valued form field whose selected values render as removable chips, with a picker for adding more.
  • Existing consumers of the stub (blast radius for a value-contract change, swept): apps/realworld2/view/article/FormContainer.mjs (the classic tag-input use case — would become the reference consumer) and examples/form/field/chip/MainContainer.mjs. list.Chip: its own example only.
  • The multi-select SELECTION model exists and works (selection-listmodel with singleSelect: false — the compose form uses it today); the field wraps that fact into a form-field contract.

The Fix (shape, implementer owns the detail)

A real Neo.form.field.Chip:

  1. Array value contract: value is an array of record ids/objects; form containers collect it as such.
  2. Chips render the selection via list.Chip composition (removable: × affordance per chip; backspace removes the last chip when the input is empty — the established chip-field grammar).
  3. Picker adds: the dropdown list (checkbox presentation optional) toggles membership; typing filters as ComboBox does today.
  4. Keyboard + a11y: chip focus/removal reachable without pointer; focus order documented.
  5. apps/realworld2 tag input migrates as the in-repo reference consumer; the example gets rebuilt against the real field.
  6. Theme coverage in both shipped neo themes (token-governed; gaps to the theme layer named, not painted over).

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
Neo.form.field.Chip value this ticket (redefines the stub) Array (multi-value) none — the stub's scalar behavior is the defect; consumers swept (2, both in-repo) class JSDoc + example consumer migration in-PR
chipfield ntype unchanged same ntype, real behavior n/a same example renders
list.Chip untouched authority consumed as rendering substrate, no API change n/a n/a composition only

Decision Record impact

none (component-level engine work; no ADR governs form-field contracts today — if the implementer finds one, upgrade this line before merge).

Acceptance Criteria

  • Multi-value contract: field value is an array; form value collection verified in a unit test.
  • Selected values render as chips (list.Chip composition); each chip removable by pointer AND keyboard.
  • Picker toggles membership; filtering works as in ComboBox.
  • apps/realworld2 tag input + the chip-field example run on the real field.
  • Both shipped themes style the field token-governed; unit tree for form/field green.

Out of Scope

The operator compose adoption (#17311 decides list-with-chip-presentation vs this field at ITS implementation) · a generic tag-CREATION (free-text new-tag) mode unless it falls out naturally — if deferred, it gets a named follow-up, not silence · theme redesign beyond field coverage.

Related

#17311 (waiting consumer, agentos) · apps/realworld2 FormContainer (legacy consumer → reference consumer) · examples/form/field/chip · examples/list/chip

Live latest-open sweep: REST created-descending, latest 10 checked 2026-08-17T18:24Z, no equivalent; A2A window clean (zeroed 18:16Z).

Origin Session ID: 7ee47ccf-d1c7-469d-a75e-15cebf3b5ea5

Retrieval Hint: query_raw_memories("form field Chip stub multi-select array value list.Chip composition")

tobiu referenced in commit 9efa086 - "feat(form): build real chip field multi-select (#17312) (#17749) on Aug 25, 2026, 10:10 AM
tobiu closed this issue on Aug 25, 2026, 10:10 AM