Skip to content

StatusPicker

Picks one status code for an entity type, offering only the codes the project it is scoped to allows.

It is the list picker configured with a status row and a badge for its value: the same control, popup, press rule and keyboard as every other picker.

Single and multi: StatusMultiPicker takes several codes.

Terminal window
pnpm dlx shadcn@latest add https://sg-widgets.vercel.app/r/react/status-picker.json
Terminal window
pnpm dlx shadcn-svelte@latest add https://sg-widgets.vercel.app/r/svelte/status-picker.json
StatusPicker: per-project options, unknown codes, states and sizes

React

Loading the React demo…

Svelte

Loading the Svelte demo…

proptypedefaultmeaning
contextSgContextrequiredThe widget context. The options and the status table are read through it, once per page.
entityTypestringrequiredThe type whose status field is offered.
projectIdnumber—Offer the codes this project allows.
projectIdsnumber[]—Offer the codes every one of these projects allows.
fieldstringstatus fieldA list or status field other than the type's own.
valuestring | nullnullThe selected code, or null when nothing is chosen. bind:value in Svelte, value with onValueChange in React.
placeholderstring'Select a status'Shown with no selection.
emptyLabelstring'No rows'Shown when the field offers nothing.
loadingLabelstring'Loading…'Names the skeletons a read stands behind, for a screen reader.
errorLabelstring—Shown in place of what the failed read said.
clearablebooleanthe fieldOffers a control that clears the value. Unset, it follows the field: a mandatory one is never clearable.
readonlybooleanfalseKeeps full contrast and drops the chevron, the popup and the clear control.
disabledbooleanfalseGreys the control and takes it out of the tab order.
invalidbooleanfalseSets aria-invalid and the destructive ring.
showCodebooleantrueDraws the code as a row's right-aligned secondary, when it says more than the label.
secondary(option) => stringthe codeA row's right-aligned value, of the caller's own making.
subLabel(option) => string—The muted line under a row's label.
siteUrlstringthe context'sPassed to every badge, for a sprite cell outside the status icon set.
size'sm' | 'md' | 'lg''md'Control height: 7, 8 and 9.
openbooleanfalseWhether the popup is showing. Two-way in Svelte.
class / classNamestring—Merged after the widget's own classes.

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 status icon as the leading mark, the display name as the row’s text, and the code right-aligned. It is what the filter bar draws for a status facet, so a page listing statuses twice lists them the same way. A status has one display name and one icon, so the row’s labelField and thumbnail are fixed, and it has no fields of its own, so its secondary is a function rather than a field name. The control keeps the badge, where a status is a value rather than an option.

Without a project the options are the site vocabulary, which hides nothing. projectIds offers the intersection of what each project allows, in the first project’s order.

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. Set it and your answer stands, except that a mandatory field is never clearable.

The root carries the size and, while the options load, data-loading.

eventpayloadwhen
onValueChangestring | nullA status was chosen, or the clear control was pressed.
onOpenChangebooleanThe popup opened or closed.

onValueChange fires with the code, or with null when the selection is cleared. It also fires once with null when a new option set drops the selected code, which is what a project change does.

onOpenChange fires when the popup opens or closes. Svelte also binds it with bind:open.

None. The rows are the shared picker row; the closed state is a status badge.

keydoes
Space, Enter, ↓Opens the list
↑ ↓Moves the highlight
EnterSelects the highlighted status and closes
BackspaceIn an empty search box, clears the status
EscCloses and keeps the selection
TabLeaves the control, or reaches the clear control when there is one

A project’s usable statuses are valid_values minus hidden_values, read with project_id. valid_values is the site’s whole vocabulary and is byte-identical at every scope, so reading it alone tells you nothing about a project (probe 009).

REST does not enforce hidden_values on write: a hidden status writes and reads back. Subtracting is right for offering a choice and wrong for testing a row, so a code outside the option set still renders here, as itself, and stays removable (field_types/status_list).

Labels come from display_values, and a missing key falls back to the raw code rather than dropping the option (probe 009).

Status lists are per entity type: Version and Task overlap on five codes only, so the options are read per type and per field (probe 009).

Project’s status field is sg_status, a plain list rather than a status_list. There is no Status row behind a list, so those options carry no icon and no colour (entity_types/Project).