Navigation

Select

<oblyx-select> is a labeled dropdown composed with <oblyx-option> children, one per row. Underneath its custom trigger it mirrors those children into a real, visually hidden native <select>, so the control participates in native HTML form submission and constraint validation with zero consumer JavaScript. There is deliberately no wrapper field element: label, help and error are plain attributes on oblyx-select itself.

Basic select

Canada United States Mexico
HTMLKotlin
<oblyx-select label="Country" placeholder="Select a country">
  <oblyx-option value="ca">Canada</oblyx-option>
  <oblyx-option value="us">United States</oblyx-option>
  <oblyx-option value="mx">Mexico</oblyx-option>
</oblyx-select>
oblyxSelect(label = "Country", placeholder = "Select a country") {
  oblyxOption(value = "ca") { +"Canada" }
  oblyxOption(value = "us") { +"United States" }
  oblyxOption(value = "mx") { +"Mexico" }
}

Options and selection

Each <oblyx-option> contributes a value and a label: its rendered content, unless an explicit label attribute overrides it. value on oblyx-select seeds which option starts selected: it must match an oblyx-option value to have any visible effect. After that first render the select owns its own selection, the same way a native <select> owns selectedIndex; it fires a bubbling change event on every choice a reader makes.

Select with a preselected value

Canada United States Mexico
HTMLKotlin
<oblyx-select label="Country" value="us">
  <oblyx-option value="ca">Canada</oblyx-option>
  <oblyx-option value="us">United States</oblyx-option>
  <oblyx-option value="mx">Mexico</oblyx-option>
</oblyx-select>
oblyxSelect(label = "Country", value = "us") {
  oblyxOption(value = "ca") { +"Canada" }
  oblyxOption(value = "us") { +"United States" }
  oblyxOption(value = "mx") { +"Mexico" }
}

An option can also be disabled. A disabled option is skipped by keyboard navigation, typeahead and click, and rendered disabled on the hidden native mirror <option> too.

Select with a disabled option

1A 1B (occupied) 1C
HTMLKotlin
<oblyx-select label="Seat" placeholder="Select a seat">
  <oblyx-option value="1a">1A</oblyx-option>
  <oblyx-option value="1b" disabled>1B (occupied)</oblyx-option>
  <oblyx-option value="1c">1C</oblyx-option>
</oblyx-select>
oblyxSelect(label = "Seat", placeholder = "Select a seat") {
  oblyxOption(value = "1a") { +"1A" }
  oblyxOption(value = "1b", disabled = true) { +"1B (occupied)" }
  oblyxOption(value = "1c") { +"1C" }
}

Sizes

Select sizes

Option A Option A Option A
HTMLKotlin
<oblyx-select label="Small" size="sm">
  <oblyx-option value="a">Option A</oblyx-option>
</oblyx-select>
<oblyx-select label="Medium" size="md">
  <oblyx-option value="a">Option A</oblyx-option>
</oblyx-select>
<oblyx-select label="Large" size="lg">
  <oblyx-option value="a">Option A</oblyx-option>
</oblyx-select>
oblyxSelect(label = "Small", size = OblyxSelectSize.SM) {
  oblyxOption(value = "a") { +"Option A" }
}
oblyxSelect(label = "Medium", size = OblyxSelectSize.MD) {
  oblyxOption(value = "a") { +"Option A" }
}
oblyxSelect(label = "Large", size = OblyxSelectSize.LG) {
  oblyxOption(value = "a") { +"Option A" }
}

Disabled

Forwarded to both the visible trigger button and the hidden native mirror <select>.

Disabled select

United States
HTMLKotlin
<oblyx-select label="Country" value="us" disabled>
  <oblyx-option value="us">United States</oblyx-option>
</oblyx-select>
oblyxSelect(label = "Country", value = "us", disabled = true) {
  oblyxOption(value = "us") { +"United States" }
}

Error

Setting error puts the control in its error visual state and sets aria-invalid="true" on the trigger; non-empty text is also rendered. This is purely informational and does not call setCustomValidity.

Select with error

Canada United States
HTMLKotlin
<oblyx-select label="Country" placeholder="Select a country" error="Choose a country to continue.">
  <oblyx-option value="ca">Canada</oblyx-option>
  <oblyx-option value="us">United States</oblyx-option>
</oblyx-select>
oblyxSelect(label = "Country", placeholder = "Select a country", error = "Choose a country to continue.") {
  oblyxOption(value = "ca") { +"Canada" }
  oblyxOption(value = "us") { +"United States" }
}

Form submission and validation

name on oblyx-select is what makes the chosen option's value appear in FormData under that key: it is forwarded to the hidden native <select name>, not the visible trigger. required forwards to that same native select, so the browser's own "please select an item" validation blocks submission and reports validity, unlike an <input type="hidden"> mirror, which the HTML spec bars from constraint validation entirely.

Select inside a form

Submit without choosing a country to see native validation block it.

Canada United States Mexico
HTMLKotlin
<form onsubmit="event.preventDefault(); const data = new FormData(this); this.querySelector('output').textContent = 'country = ' + data.get('country');">
  <oblyx-select label="Country" name="country" placeholder="Select a country" required>
    <oblyx-option value="ca">Canada</oblyx-option>
    <oblyx-option value="us">United States</oblyx-option>
    <oblyx-option value="mx">Mexico</oblyx-option>
  </oblyx-select>
  <button type="submit">Continue</button>
  <output></output>
</form>
form {
  oblyxSelect(label = "Country", name = "country", placeholder = "Select a country", required = true) {
    oblyxOption(value = "ca") { +"Canada" }
    oblyxOption(value = "us") { +"United States" }
    oblyxOption(value = "mx") { +"Mexico" }
  }
  button(type = ButtonType.submit) { +"Continue" }
}

Reference

<oblyx-select>

AttributeTypeDefaultDescription
labelstring | undefinedLabel text, always rendered and associated with the trigger via a real <label for>. This works even though the trigger is a <button>, not an <input>: <button> is a "labelable" element per the HTML spec, so the browser's own accessible-name computation resolves a <label for> pointing at it exactly like it would for oblyx-input. Required for an accessible name; omitting it is a defect and is flagged loudly.
helpstring | undefinedHelp text, rendered between the label and the control and wired into the trigger's aria-describedby.
errorstring | undefinedError message. Presence alone puts the control in its error visual state and sets aria-invalid="true" on the trigger; non-empty text is also rendered and wired into aria-describedby, mirroring oblyx-input's error contract exactly.
sizesmmdlgmdForm-control height.
namestring | undefinedForwarded verbatim to the native <select name>. This is what makes the value appear in FormData/receiveParameters().
valuestring | undefinedInitial selected value only. Seeds the first render rather than acting as a fully-controlled value. Must match an <oblyx-option value> to have any visible effect.
placeholderstring | undefinedSelect…Shown in the trigger when nothing is selected.
requiredbooleanfalseForwarded to the native mirror <select required>, enforcing real constraint validation via a real <select> rather than a hidden input.
disabledbooleanfalseNative disabled state, forwarded to both the trigger button and the native mirror <select>.

Events

EventTypeDescription
changeEvent

<oblyx-option>

AttributeTypeDefaultDescription
valuestring | undefinedThe value this option contributes to the select. Required, like a native <option value>. Missing it is a defect and is flagged loudly rather than silently omitting the row from <oblyx-select>'s model.
labelstring | undefinedOptional explicit label for the trigger's collapsed display and the hidden native <select> mirror's <option> text. Falls back to the rendered content, since that is what is visually true for a light-DOM row that may contain more than plain text. See displayLabel.
disabledbooleanfalseForwarded to the native mirror <option disabled> and to this row's own aria-disabled/click handling. A disabled option is skipped by keyboard navigation, typeahead and click.
selectedbooleanfalseDriven by the parent <oblyx-select>, true for the one row whose value matches the select's current value. Reflected so oblyx-option[selected] is a CSS hook, and so an author can pre-select a row with a plain selected attribute the same way a native <option selected> works.
highlightedbooleanfalseDriven by the parent <oblyx-select>, true for the row the keyboard/mouse cursor currently rests on. Purely visual; aria-activedescendant on the trigger is the real accessibility signal, this is just its CSS-visible counterpart.