ListPicker
Edits a list field, offering the vocabulary its schema declares.
It is the shared picker control with rows from the field’s valid values. The set is fixed and read once, so there is no search row unless a caller asks for one, and the control is the summary trigger: the value reads as plain text, the way a select does.
Single and multi: ListMultiPicker takes several values.
Install
Section titled “Install”pnpm dlx shadcn@latest add https://sg-widgets.vercel.app/r/react/list-picker.jsonpnpm dlx shadcn-svelte@latest add https://sg-widgets.vercel.app/r/svelte/list-picker.jsonReact
Loading the React demo…
Svelte
Loading the Svelte demo…
| chosen | emitted |
|---|---|
| a row | that row’s value, byte for byte |
| the clear control | null |
The offered set is the field’s valid values, minus its hidden values when a project id is given. A row already holding a value outside that set keeps a row of its own, labelled with the value.
| prop | type | default | meaning |
|---|---|---|---|
value | string | null | null | The stored string. Two-way in Svelte. |
onValueChange | (value: string | null) => void | — | Called on every change. |
field | Pick<FieldSchema, 'displayName' | 'mandatory' | 'validValues' | 'displayValues' | 'hiddenValues'> | null | null | Supplies the valid values, the labels and the hidden values. |
projectId | number | — | Given, the field's hidden values are removed from the list. |
options | ListOption[] | — | The set on offer, of the caller's own making. Wins over the field. |
showCode | boolean | false | Draws the stored string as a row's right-aligned secondary, where it says more than the label. |
secondary | (option) => string | the value | A row's right-aligned value, of the caller's own making. |
subLabel | (option) => string | — | The muted line under a row's label. |
loadError | string | null | null | What a caller's read failed with, drawn in place of the list. |
class / className | string | — | Merged after the widget's own classes. |
slot | string | 'list-picker' | The data-slot prefix every part of this picker carries. |
picker | string | 'list' | The data-picker the popup carries. |
searchable | boolean | false | Offers a search box, which narrows the set in the browser. |
sizefrom PickerControl | 'sm' | 'md' | 'lg' | 'md' | Control height: 7, 8 and 9. |
disabled | boolean | false | Greys the control and takes it out of the tab order. |
readonly | boolean | false | Keeps full contrast and drops the chevron, the popup and the clear control. |
invalid | boolean | false | Sets aria-invalid and the destructive ring. |
clearable | boolean | the field | Offers a control that clears the value. Unset, it follows the field: a mandatory one is never clearable. |
placeholder | string | 'Choose' | Shown while the field is unset. |
searchPlaceholder | string | 'Search values…' | Placeholder of the search box. |
openfrom PickerControl | boolean | required | React: whether the popup is showing. |
openfrom PickerControl | boolean | false | Svelte: whether the popup is showing, two-way. |
onOpenChangefrom PickerControl | (open: boolean) => void | required | React: called when the popup opens or closes. |
onOpenChangefrom PickerControl | (open: boolean) => void | — | Svelte: called when the popup opens or closes. |
loading | boolean | false | A caller's read is in flight: skeletons, and the control is inert. |
error | string | null | null | A message from the caller, drawn under the control. |
emptyLabel | string | 'No rows' | Shown when the list offers nothing. |
loadingLabel | string | 'Loading…' | Names the skeletons a read stands behind, for a screen reader. |
errorLabel | string | — | Shown in place of what the failed read said. |
clearLabelfrom PickerControl | string | 'Clear the selection' | |
triggerLabelfrom PickerControl | string | 'Show the options' |
Every other attribute is spread onto the root: id, aria-*, data-*, key handlers and a ref
to the root element.
A row is the row anatomy of the design rules: the label as the main text and, with showCode, the
stored string right-aligned. A value has no picture and no fields of its own, so the row’s leading
slot is empty unless a caller fills it and its secondary is a function rather than a field name.
The clear control follows the field. Left unset, clearable reads the field’s schema, and a field
the site flags mandatory offers no clear, since clearing it writes a value the site refuses.
Events
Section titled “Events”| event | payload | when |
|---|---|---|
onErrorChange | string | null | The message changed. |
onValueChange fires as soon as a row is chosen, and with null when the value is cleared.
onErrorChange fires with null on that same change, so a message the caller set clears when the
field is answered.
onOpenChange fires when the popup opens or closes. Svelte also binds it with bind:open.
| slot | receives | draws |
|---|---|---|
mark | the option | A row's leading mark. Given, every row carries one. |
valueChip | the chosen string | The control's value, in place of plain text. |
errorMessage | the message | The line under the control. |
Keyboard
Section titled “Keyboard”| key | does |
|---|---|
| Space, Enter, ↓ | Opens the list |
| ↑ ↓ | Move the highlight |
| typing | Narrows the list, where the picker is searchable |
| Enter | Chooses the highlighted row and closes |
| Backspace | In an empty search box, clears the value |
| Esc | Closes the list and keeps the value |
| Tab | Leaves the control, or reaches the clear control when there is one |
ArrowDown / ArrowUpfrom PickerControl | Moves the highlight, and the list scrolls it into view. |
Enterfrom PickerControl | Takes the highlighted row. A multi picker keeps the popup open. |
Escapefrom PickerControl | Closes the popup and clears the query. On a closed picker it does nothing. |
Backspacefrom PickerControl | In an empty query: takes the caret to the last chip of a multi picker; clears a single one. |
ArrowLeft / ArrowRightfrom PickerControl | On a chip, walks the row. ArrowRight past the last chip returns to the input. |
Deletefrom PickerControl | On a chip, removes it and leaves the caret on its neighbour. |
Tabfrom PickerControl | Leaves the control. |
API behaviour
Section titled “API behaviour”Despite the name a list field holds one bare string. A write outside valid_values is a 400 and
case-sensitive, down to a trailing space, so the schema’s vocabulary is the whole set a picker may
offer (field_types/list).
A filter is case-insensitive where a write is not, so a value read out of a filter is never safe to write back (field_types/list).
Hidden values reach the schema only when it is read with a project id, and REST does not enforce them on write, so the subtraction is the client’s (probe 009).