Select
Trigger + chevron, a floating panel of options, check-marked selection.
A bordered trigger showing the current choice; clicking it opens a floating
panel over the content beneath — built on the shared portal primitive (Floating),
so it escapes any parent clipping, paints above everything, and wins the pointer. Picking an
option, pressing anywhere else, or Escape closes it; the panel opens aligned to the current
selection. Web-specific composition (SelectTrigger/SelectValue
sub-components) and RTL are "from the web": Go structs replace composition, and RTL layout is
not yet supported by the underlying toolkit.
Installation
Use the module import (the default), or own the source: lotusui add
vendors the component into your app and lotusui update keeps the copy mergeable —
see Registry.
go get github.com/ikaito-com/lotusui
# or vendor the source into your app:
go run github.com/ikaito-com/lotusui/cmd/lotusui add select
Usage
Options carry a Label (what the user reads) and a
Value (what your app stores) — SelectOpts builds label-only lists. Call
Clear() for the placeholder state; read the choice with Value(),
never an index. Open the demo's panel: it floats over whatever is beneath.
fruit := lotusui.Select{
Options: lotusui.SelectOpts("Apple", "Banana", "Blueberry", "Grapes", "Pineapple"),
Placeholder: "Select a fruit",
}
fruit.Clear() // start on the placeholder
fruit.Layout(th, gtx, "Fruit")
chosen := fruit.Value() // "Banana"
Align item with trigger
AlignItemWithTrigger overlays the open panel so the SELECTED row
sits directly over the trigger — the native-select feel — instead of dropping below. Long
lists still scroll; the alignment accounts for scrolled-away rows.
font := lotusui.Select{Options: fonts, AlignItemWithTrigger: true}
font.SetValue("Roboto")
Groups
Groups renders options under muted labels with separators between
groups. Value() reads the choice whichever group it came from — grouping is
presentation, not identity.
produce := lotusui.Select{
Groups: []lotusui.SelectGroup{
{Label: "Fruits", Options: lotusui.SelectOpts("Apple", "Banana", "Cherry")},
{Label: "Vegetables", Options: lotusui.SelectOpts("Carrot", "Leek", "Spinach")},
},
Placeholder: "Pick a produce…",
}
produce.Clear()
Scrollable
The panel caps at seven rows; longer lists scroll inside it, and the panel opens scrolled to the current selection — the align-with-trigger behavior, transposed.
tz := lotusui.Select{Options: timezones}
tz.SetValue("Europe/Paris") // the panel opens scrolled to it
Meta
SelectOption.Meta is optional secondary text on the far right of
an option row (and on the closed trigger) — a count, shortcut, … Empty omits it. The selected
check still sits after Meta.
lotusui.Select{Options: []lotusui.SelectOption{
{Label: "roteland", Value: "r", Meta: "1"},
{Label: "test", Value: "t", Meta: "2"},
}}
Disabled
Freezes the control on its current choice — identity fields that cannot change after creation.
engine.Disabled = true
Invalid
Danger chrome on the trigger — pair it with a Field error message.
size.Invalid = true
Sizes
All seven shared Size presets on the trigger frame.
sel.Size = lotusui.Size2XS // … through lotusui.Size2XL
API
| Option | Type | Description |
|---|---|---|
Options | []SelectOption | The choices: Label is what the user reads, Value what your app stores (HTML's <option value>). Empty Value = the Label is the value; SelectOpts("a","b") builds label-only lists. |
SelectOption.Meta | string | Optional secondary text on the far right of the option row and closed trigger. Empty omits it; the selected check still sits after Meta. |
Groups | []SelectGroup | Wins over Options: options under muted labels, separators between groups, flattened in order. |
Size | Size | The shared size presets for the trigger frame. |
Value() / SetValue(v) | string | Read and write the CHOICE — never an index, so reordering or rewording the options cannot change what stored data means. An unknown SetValue clears the choice. |
Clear() / Chosen() | — | Back to the placeholder state; whether anything is chosen. The zero value selects the first option, like a <select> with no selected attribute. |
Placeholder | string | Shown in muted ink while nothing is chosen. |
AlignItemWithTrigger | bool | Open the panel with the selected row over the trigger. |
Invalid | bool | Danger chrome on the trigger. |
Disabled | bool | Freezes the control: no pointer cursor, no opening, dimmed value. |