Components · Forms

Tag picker

The free-tag sibling of the entity picker: type + Enter (or comma) to mint a tag, Backspace on an empty field to drop the last, click the × on any chip. A thin layer over the DS TagInput that adds the value hygiene callers want — transform, validate, and optional one-click suggestions in a recessed Surface tray.

free-tag · entered chips + input caret · one-click suggestions
foster transport microchip-scan vacc

Press Enter or comma to add; Backspace on an empty field removes the last.

Intake profile — Marisol Vega. The caret sits after the in-progress vacc; Enter commits it (→ vaccine-clinic once suggested). Suggestion chips already present in the field are hidden, and the whole tray disappears once maxTags is hit.

transform + validate · invalid ring + error · at cap · resting
transform · lower-kebab slugs
beagle senior-dog special-needs Add a slug tag…

transform lowercases, strips a leading #, and collapses spaces to hyphens before the tag commits — “Special Needs” → special-needs.

validate · rejected → error ring
beagle Vet Tech!
maxTags=5 · at cap → suggestions hidden
urgent review follow-up vetted donor

Five of five tags — the field stops accepting input and the suggestion tray is withheld until one is removed.

resting · helpText + placeholder
Add a label…

Empty and un-focused — helpText sits under the field until an error replaces it.

value / onChange
Controlled string[] of tags; onChange fires with the next list on add or remove. The component holds no tags of its own.
transform?
(raw) => string. Normalises a raw tag before it commits — e.g. lowercase, strip a leading #, collapse spaces to hyphens. Applied before the dedupe + validate checks.
validate?
(tag, existing) => true | false | string. Rejects a tag; a string is shown as the inline error and the field flips to invalid styling.
suggestions?
One-click quick-add chips rendered below the field in a recessed surface-2 tray; already-present tags are hidden and the tray disappears at maxTags.
maxTags / invalid / helpText
maxTags caps the count (DS TagInput max); invalid forces the error styling from outside; helpText sits under the field until an error replaces it.

Source · ds/forms/TagPicker.tsx@phauna/ds/overlays TagInput (create-on-enter chips + trim/dedupe/max) with a value-hygiene layer (transform / validate) and optional suggestions, on the Surface primitive.