SelectNative
A styled native HTML select element with a chevron icon overlay. No JavaScript.
Quick Start
<%= kui(:select_native, name: "timezone") do %>
<option value="">Select a timezone...</option>
<option value="utc">UTC</option>
<option value="est">Eastern (ET)</option>
<option value="pst">Pacific (PT)</option>
<% end %>
Locals
| Local | Type | Default |
|---|---|---|
variant: |
Symbol |
:outline |
size: |
Symbol |
:md |
disabled: |
Boolean |
false |
css_classes: |
String |
"" |
**component_options |
Hash |
{} |
Usage
Sizes
<%= kui(:select_native, size: :sm, name: "sm") do %>
<option>Small</option>
<% end %>
<%= kui(:select_native, size: :md, name: "md") do %>
<option>Medium (default)</option>
<% end %>
<%= kui(:select_native, size: :lg, name: "lg") do %>
<option>Large</option>
<% end %>
Variants
<%= kui(:select_native, variant: :outline, name: "v") do %>
<option>Outline (default)</option>
<% end %>
<%= kui(:select_native, variant: :soft, name: "v") do %>
<option>Soft</option>
<% end %>
<%= kui(:select_native, variant: :ghost, name: "v") do %>
<option>Ghost</option>
<% end %>
With Field
Wrap in kui(:field) for labels and validation:
<%= kui(:field) do %>
<%= kui(:label, for: "role") { "Role" } %>
<%= kui(:select_native, name: "role", id: "role") do %>
<option value="member">Member</option>
<option value="admin">Admin</option>
<% end %>
<% end %>
Disabled
<%= kui(:select_native, name: "timezone", disabled: true) do %>
<option>UTC</option>
<% end %>
Option Groups
Use standard HTML <optgroup> elements:
<%= kui(:select_native, name: "city") do %>
<optgroup label="North America">
<option value="nyc">New York</option>
<option value="sf">San Francisco</option>
</optgroup>
<optgroup label="Europe">
<option value="lon">London</option>
<option value="par">Paris</option>
</optgroup>
<% end %>
When to use
Use SelectNative for simple dropdowns where the browser’s native select behavior is sufficient (timezone pickers, role selectors, country lists).
Use Select (kui(:select)) when you need custom styling for options,
search/filtering, or multi-select behavior.
Theme
SelectNativeWrapper = ClassVariants.build(
base: "relative w-full has-[select:disabled]:opacity-50"
)
SelectNative = ClassVariants.build(
base: "text-foreground w-full min-w-0 appearance-none rounded-md pr-9
outline-none transition-[color,box-shadow]
disabled:pointer-events-none disabled:cursor-not-allowed
focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary
aria-invalid:ring-error aria-invalid:focus-visible:ring-error",
variants: {
variant: {
outline: "bg-background ring ring-inset ring-accented shadow-xs",
soft: "bg-elevated/50 hover:bg-elevated focus:bg-elevated",
ghost: "bg-transparent hover:bg-elevated focus:bg-elevated"
},
size: {
sm: "h-8 px-2.5 py-1 text-sm",
md: "h-9 px-3 py-1 text-base md:text-sm",
lg: "h-10 px-3 py-2 text-base"
}
},
defaults: { variant: :outline, size: :md }
)
SelectNativeIcon = ClassVariants.build(
base: "text-muted-foreground pointer-events-none absolute top-1/2 right-3.5
size-4 -translate-y-1/2 opacity-50 select-none"
)
Accessibility
| Attribute | Element | Value |
|---|---|---|
data-slot |
wrapper | "select-native-wrapper" |
data-slot |
select | "select-native" |
data-slot |
icon | "select-native-icon" |
aria-hidden |
icon | "true" |
disabled |
select | set when disabled: true |