Four components for selecting from lists. All share the same option/group model and keyboard navigation.
select – dropdown pickercombobox – dropdown with text filterautocomplete – async search with debouncecommand-palette – modal command selectorA dropdown picker. Tab to focus, Enter to open, arrows to navigate.
Order a drink Size: Choose size... v Drink: Choose drink... ^ ┌──────────────────┐ Order: (│Coffee │ │Espresso │ │Latte │ │Cappuccino │ │Tea │ │Green Tea │ │Black Tea │ │Chai Latte │ └──────────────────┘
Options are declared as child elements. Use <group> to organize them
under headers. The onChange handler fires with event.value
and event.label.
<select id="drink" placeholder="Choose drink..." style="width: 20" onChange="$app.update()"> <group label="Coffee"> <option value="espresso">Espresso</option> <option value="latte">Latte</option> <option value="cappuccino">Cappuccino</option> </group> <group label="Tea"> <option value="green">Green Tea</option> <option value="black">Black Tea</option> </group> </select> <script type="typescript"> export function update() { const drink = $melker.getElementById('drink'); const result = $melker.getElementById('result'); result.setValue(`Order: ${drink?.getValue()}`); } </script>
Reference: Filterable list architecture
A select with a text input. Type to filter the options list.
Country Picker Country: ype to search... ^ ┌────────────────────────────┐ Selected: │Europe █│ │Sweden █│ │Norway █│ │Denmark █│ │Finland ░│ │Germany ░│ │France ░│ │Americas ░│ └────────────────────────────┘
The filter prop controls how typed text matches options.
Set filter="fuzzy" for character-by-character matching (typing "sw"
matches "Sweden"), or "prefix", "contains", "exact".
The onSelect handler fires when an option is picked.
<combobox id="country" placeholder="Type to search..." style="width: 30" filter="fuzzy" onSelect="$app.pick(event)"> <group label="Europe"> <option value="se">Sweden</option> <option value="no">Norway</option> <option value="dk">Denmark</option> </group> <group label="Americas"> <option value="us">United States</option> <option value="ca">Canada</option> </group> </combobox>
Combobox also accepts freeform text entry. If the user types something that does not
match any option and presses Enter, onSelect fires with event.freeform = true.
Reference: Filterable list architecture
A combobox with async search. Results load as you type.
User Search Find: earch users... ^ ┌─────────────────────────────────┐ Selecte│Recent │ │Alice Anderson │ │Bob Brown │ └─────────────────────────────────┘
The onSearch handler runs when the user types. It receives event.query
and should return an array of { value, label } objects. The debounce
prop (in ms) prevents firing on every keystroke. minChars sets the minimum
input length before searching.
<autocomplete id="search" placeholder="Search users..." onSearch="$app.searchUsers(event.query)" onSelect="$app.selectUser(event)" minChars="1" debounce="300" width="35"> <group label="Recent"> <option value="alice">Alice Anderson</option> <option value="bob">Bob Brown</option> </group> </autocomplete> <script type="typescript"> export async function searchUsers(query: string) { const res = await fetch(new URL('users.json', $melker.url)); const users = await res.json(); return users.filter(u => u.label.toLowerCase().includes(query.toLowerCase()) ); } </script>
Child <option> elements show as initial suggestions before the user types.
Once onSearch returns results, they replace the dropdown contents.
Reference: Filterable list architecture
A modal overlay for commands. Fuzzy search, keyboard shortcuts, grouped actions.
Command Palette ┌───────────────Command Palette────────────────┐ Press│Search commands... │ ├──────────────────────────────────────────────┤ │File █ │ New File Ctrl+N █ Ready│ Open File Ctrl+O █ │ Save Ctrl+S █ │Edit █ │ Undo Ctrl+Z █ │ Redo Ctrl+Y █ │View █ │ Toggle Sidebar █ │ Zoom In Ctrl++ ░ │ ░ └──────────────────────────────────────────────┘
The palette starts closed. Open it by setting props.open = true
or binding it to a keyboard shortcut. Each option can have a
shortcut prop that displays right-aligned, and its own
onSelect handler.
<command-palette id="palette" placeholder="Search commands..."> <group label="File"> <option value="new" shortcut="Ctrl+N" onSelect="$app.run('New file')">New File</option> <option value="save" shortcut="Ctrl+S" onSelect="$app.run('Saved')">Save</option> </group> <group label="View"> <option value="sidebar" onSelect="$app.run('Toggled')">Toggle Sidebar</option> </group> </command-palette> <script type="typescript"> export function openPalette() { const p = $melker.getElementById('palette'); if (p) p.props.open = true; } </script>
The palette includes built-in system commands (Exit, AI Assistant, Dev Tools) by default.
Set system="false" to disable them.
Reference: Filterable list architecture
All four components use the same child elements.
<!-- Simple option --> <option value="id">Display Label</option> <!-- Option with shortcut and disabled state --> <option value="paste" shortcut="Ctrl+V" disabled="true">Paste</option> <!-- Grouped options --> <group label="Category"> <option value="a">Item A</option> <option value="b">Item B</option> </group>
Options can also be set programmatically with setOptions():
const el = $melker.getElementById('mySelect'); el.setOptions([ { id: 'a', label: 'Alpha', group: 'Greek' }, { id: 'b', label: 'Beta', group: 'Greek' }, { id: '1', label: 'One', group: 'Numbers' }, ]);
Both child elements and setOptions() can be used together.
Child options appear first, then programmatic ones.
Reference: Component reference
Four built-in filter algorithms. Set via the filter prop.
<!-- Fuzzy: characters in order, scores consecutive matches --> <combobox filter="fuzzy" .../> <!-- "sw" matches "Sweden" --> <!-- Prefix: text starts with pattern --> <combobox filter="prefix" .../> <!-- "sw" matches "Sweden" but not "New Sweden" --> <!-- Contains: text includes pattern --> <combobox filter="contains" .../> <!-- "eden" matches "Sweden" --> <!-- Exact: text equals pattern --> <combobox filter="exact" .../> <!-- only "Sweden" matches "Sweden" -->
The default filter mode is fuzzy for combobox and command palette.
Select does not filter (it has no text input). Autocomplete delegates
filtering to the onSearch handler.
Reference: Filterable list architecture