ProjectPicker
Searches projects on the server, showing each one’s thumbnail and status.
Single and multi: ProjectMultiPicker takes several projects.
Install
Section titled “Install”pnpm dlx shadcn@latest add https://sg-widgets.vercel.app/r/react/project-picker.jsonpnpm dlx shadcn-svelte@latest add https://sg-widgets.vercel.app/r/svelte/project-picker.jsonThe item installs the single picker alone. A caller who installed it for ProjectMultiPicker takes
the project-multi-picker item instead; this note stands for one release.
React
Loading the React demo…
Svelte
Loading the Svelte demo…
| prop | type | default | meaning |
|---|---|---|---|
includeArchived | boolean | false | Offer projects whose archived checkbox is set. |
contextfrom EntityPicker | SgContext | required | The widget context. Every read goes through it, so widgets on a page share one cache. |
valuefrom EntityPicker | EntityRef | null | null | The chosen row. Two-way in Svelte. |
labelFieldfrom EntityPicker | string | display-name chain | Field holding the row label. |
searchFieldsfrom EntityPicker | SearchFieldSpec[] | ((query) => SearchFieldSpec[]) | — | Fields matched on top of the display-name chain. A function is called with the query. |
secondaryFieldfrom EntityPicker | string | CollectionColumn | null | null | Field shown right-aligned, drawn by its data type. A resolved column renders it by type. |
secondaryfrom EntityPicker | (row) => string | — | Right-aligned text of your own. Wins over secondaryField. |
subLabelFieldfrom EntityPicker | string | CollectionColumn | null | null | Field shown under the label, drawn by its data type: a status reads its display name. |
subLabelfrom EntityPicker | (row) => string | the type, when several are searched | Computes the sub-label. |
thumbnailfrom EntityPicker | string | false | 'image' | Field holding the thumbnail URL. false hides the leading slot. |
roundThumbnailfrom EntityPicker | boolean | false | Draws the thumbnail as a circle. |
showCodefrom EntityPicker | boolean | false | Shows the row's code beside the label when the two differ. |
siteUrlfrom EntityPicker | string | the context's | The site the status sprite is served from, for a secondary that is a status. |
fieldsfrom EntityPicker | string[] | — | Extra fields to request. |
filtersfrom EntityPicker | FilterGroup | WireGroup | null | null | Pre-filter, merged into every search with and. |
projectIdfrom EntityPicker | number | — | Scopes to one project. |
excludefrom EntityPicker | EntityRef[] | — | Rows kept out of the results. |
minQueryLengthfrom EntityPicker | number | 0 | Under it the query carries no name condition. |
pageSizefrom EntityPicker | number | 20 | Rows a page, with a load more row under them. |
debounceMsfrom EntityPicker | number | 250 | Wait after the last keystroke before searching. |
class / classNamefrom EntityPicker | string | — | Merged after the widget's own classes. |
sizefrom PickerControl | 'sm' | 'md' | 'lg' | 'md' | Control height: 7, 8 and 9. |
disabledfrom PickerControl | boolean | false | |
readonlyfrom EntityPicker | boolean | false | Keeps full contrast and drops the affordances. |
invalidfrom EntityPicker | boolean | false | Sets aria-invalid and the destructive ring. |
clearablefrom EntityPicker | boolean | true | Shows the clear control. |
placeholder | string | 'Search for a project' | Shown in the control while nothing is chosen. |
searchPlaceholderfrom EntityPicker | string | 'Search…' | Shown in the query input once something is chosen. |
openfrom PickerControl | boolean | required | React: whether the popup is showing. |
openfrom PickerControl | boolean | false | Svelte: whether the popup is showing, two-way. |
emptyLabelfrom EntityPicker | string | 'No match' | Shown when a query matches nothing. |
loadingLabelfrom EntityPicker | string | 'Loading…' | Names the skeletons a read stands behind, for a screen reader. |
errorLabelfrom EntityPicker | string | — | Shown in place of what the failed read said. |
The sub-label is the project’s status, so an active project can be told from a bidding one.
Events
Section titled “Events”| event | payload | when |
|---|---|---|
onValueChange | EntityRef | null, PickerRow | null | The selection changed. |
onErrorfrom EntityPicker | Error | A read failed. The list shows it inline as well. |
onOpenChangefrom EntityPicker | boolean | The popup opened or closed. Svelte also binds it with bind:open. |
None.
Keyboard
Section titled “Keyboard”| key | does |
|---|---|
| any textfrom EntityPicker | Opens the list and searches the server. |
Enter, Spacefrom EntityPicker | On the chevron, opens the list. |
Up, Downfrom EntityPicker | Moves the highlight through the rows and keeps it in view, including across a load more page. The last row holds it rather than wrapping. |
ArrowDown / ArrowUpfrom PickerControl | Moves the highlight, and the list scrolls it into view. |
Enterfrom EntityPicker | Chooses the highlighted row, or loads the next page on the load more row. |
Escapefrom EntityPicker | Closes the list and clears the query. On a closed picker it does nothing. |
Backspacefrom EntityPicker | In an empty search box, clears the value. |
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 EntityPicker | Moves to the clear control, then the chevron, then out. |
API behaviour
Section titled “API behaviour”Project’s status field is sg_status, a plain list with no Status row behind it, where every other
type uses sg_status_list (entity_types/Project).
sg_status is not a liveness filter and is null on most projects; archived, is_template and
is_demo are the discriminators, which is why hiding archived projects filters on archived
(018_project_listing).
Project is site-wide and has no project field, so projectId adds nothing on this picker.
Reference
Section titled “Reference”The row, chip and checkbox anatomy follows shadcn’s Base UI Combobox, read through shadcn 4.21.0. The primitive underneath is Base UI Combobox 1.8.0 in React and Bits UI Combobox 2.19.1 in Svelte. shadcn-svelte ships no combobox item, so each widget composes the headless primitive of its framework and both draw the same rows, the same classes and the same states.