Select

A native <select> with a shadcn chevron. Uses the browser's dropdown โ€” no JS, works with form submissions automatically.

Installation

bin/rails g shadcnrb:component select

Usage

<%= sui.layout.stack gap: 2, class: "max-w-xs" do %>
  <%= sui.label "Plan", for: "plan" %>
  <%= sui.select(id: "plan", name: "plan") do %>
    <%= options_for_select([["Hobby", "hobby"], ["Pro", "pro"], ["Team", "team"]], "pro") %>
  <% end %>
<% end %>
<%= sui.select(name: "small", size: :sm, class: "w-fit") do %>
  <%= options_for_select(["Small size", "Second"]) %>
<% end %>

Themed list

The browser draws a native select's option list, so the theme stops at the closed control. Chromium's customizable select, appearance: base-select on the select and on its ::picker(select), turns the list into an ordinary box that CSS styles like a popover. Engines without it keep their own list, so this is pure enhancement: the same markup, one class.

app/assets/tailwind/application.css

/* Native select with a themed option list: Chromium's customizable select.
   Goes on `sui.select class:`, which lands on the wrapper. */
.select-themed select,
.select-themed select::picker(select) {
  appearance: base-select;
}

.select-themed select::picker-icon {
  display: none;
}

.select-themed select::picker(select) {
  margin-top: 0.25rem;
  width: anchor-size(width);
  padding: 0.25rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-popover);
  color: var(--color-popover-foreground);
  box-shadow: var(--shadow-md);
}

.select-themed option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.375rem 0.5rem;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
}

.select-themed option:hover,
.select-themed option:focus-visible {
  outline: none;
  background: var(--color-accent);
  color: var(--color-accent-foreground);
}

.select-themed option:checked {
  font-weight: 500;
}

.select-themed option::checkmark {
  order: 1;
  margin-left: auto;
  color: var(--color-muted-foreground);
}
<%= sui.layout.stack gap: 2, class: "max-w-xs" do %>
  <%= sui.label "Plan", for: "themed-plan" %>
  <%= sui.select(id: "themed-plan", name: "themed_plan", class: "select-themed w-56") do %>
    <%= options_for_select([["Hobby", "hobby"], ["Pro", "pro"], ["Team", "team"]], "pro") %>
  <% end %>
<% end %>