Skip to content
LyEve UI v0.60.1

Form controls

Select

One value from a list of five or more. The kit draws the list itself, in the theme's colors and type, and never hands it to the browser. It takes the same border, focus ring and error treatment as Input. For two to four short choices use a SegmentedControl, and see Choosing a control for the whole rule. Reach for Autocomplete when typing is the main way in, and MultiSelect for several values at once.

Basic

Pass the rows as options and bind the value.

Value: pro

Never the browser's list

There is no native mode. A native select opens a list the operating system paints, in its own font and highlight color, and no stylesheet reaches it: on a dark page it opens white. So the trigger is a button and the panel is the kit's own, with the same keyboard model as a select. Arrow keys move, Enter picks, Escape closes, and typing a few letters jumps to a matching row.

In a form

name posts the value through a hidden input, exactly as a select would. onvaluechange fires once that input holds the new value, so a page that saves on change can submit the form from it and post the value just picked.

Pick a status and the form posts it.

A hidden input is barred from constraint validation, so required is announced through aria-required and enforced by the page and the server.

Groups

group collects a run of neighboring rows under a heading. An array that interleaves two groups shows the heading twice, which is what the array says. placeholder shows while nothing is chosen.

Value: eu-west-1

Icons

A row can carry a lucide icon before its label, and the chosen row carries a tick.

Value: email

Searching the panel

searchable adds a search box, and the letters typed become query text instead of a jump. Add it once a list passes about ten rows, as the thirteen tenants here do. keywords gives the matcher more than the label, so a row known by a machine name or a code can be found by typing it. Matching ignores case and accents. Try GBX here.

Value: (none)

filter replaces the matcher, and filter={false} switches local filtering off for a list that arrived already narrowed by a server query.

Under the keyboard, the search box turns its border the focus color, with no ring inside or around it, as the field does.

A trigger of your own

trigger fills the button rather than replacing it. The button stays, because it carries the id, the label association and the ARIA, and a button nested in another button is not markup a browser will focus.

Error state

Pick a role.

Described by text elsewhere

describedBy takes the ids of other elements that explain the control, separated by spaces. A screen reader reads them after the control's own hint or error. Use it when the explanation already sits on the page, such as a note above a form or the message a wrapping Field renders.

Shortening the window deletes older logs at the next sweep.

Applies to every stream.

Under a touch screen

Every option in the open list is 44px tall, as a Dropdown menu item is. A mouse keeps the shorter rows.

A list that would run past the side of the screen, or of the dialog or scrolling box it opens in, slides back inside it. In a container too short for it above and below, such as a one-field Modal, it opens below its field at its own height, and the container grows to hold it or scrolls down to it. The list keeps at least four rows in view, or all of them when it has fewer.

API

PropTypeDefaultDescription
value string | nullnullBindable selected value.
options SelectOption[][]The rows, as data.
placeholder string no defaultShown while nothing is selected.
searchable booleanfalseAdds a search field inside the panel.
filter FilterFn<SelectOption> | false no defaultReplaces the default matcher, or false to switch local filtering off.
trigger Snippet<[{ selected, open }]> no defaultFills the trigger. The button itself stays.
label string no defaultLabel rendered above the control.
hint string no defaultHelper text below the control. An error replaces it.
error string no defaultError message. Reddens the border.
describedBy string no defaultIds of other elements that describe the control, separated by spaces, such as a wrapping Field's message. Read after the control's own hint or error.
disabled booleanfalseDisables the control and its posted value.
required booleanfalseAnnounced through aria-required. The page and the server enforce it.
id string no defaultDOM id of the trigger, useful for matching a Label.
name string no defaultForm name, posted through a hidden input.
class string no defaultExtra classes on the field wrapper.
onvaluechange (value: string) => void no defaultFires once the hidden input holds the new value.
noAI booleanfalseKeep the value from an assistant: a FormAssist never reports it or fills it, and the control is marked data-no-ai for a browser agent.

SelectOption

PropTypeDefaultDescription
value requiredstring no defaultThe submitted value, and the key the row is rendered under.
label requiredstring no defaultWhat the user reads.
disabled boolean no defaultBlocks this row alone. A disabled control blocks every row.
icon Component no defaultA lucide component before the label.
keywords string[] no defaultExtra text the default matcher searches, for a row known by a machine name.
group string no defaultCollects a run of neighboring rows under a heading.