Select

Usage

Template macros available

This component ships a select() macro for Jinja and Nunjucks.

Include CSS

Import Tailwind and one full Basecoat style bundle.

@import "tailwindcss";
@import "basecoat-css/vega.css";

Or import only the base CSS, Select component CSS, and one style pack.

@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/select.css";
@import "basecoat-css/styles/vega.css";

Using CDN or bundler imports? See the Installation page.

Include JavaScript

Copy or serve the full Basecoat JavaScript bundle.

<script src="/assets/js/all.min.js" defer></script>

Or copy or serve the Basecoat runtime and Select script.

<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/select.min.js" defer></script>

Using CDN or bundler imports? See the Installation page.

Add your select HTML

<div id="select-theme" class="select" data-placeholder="Theme">
  <button type="button" class="w-[180px]" id="select-theme-trigger" aria-haspopup="listbox" aria-expanded="false" aria-controls="select-theme-listbox">
    <span class="truncate">Theme</span>
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down text-muted-foreground opacity-50 shrink-0"><path d="m6 9 6 6 6-6" /></svg>
  </button>
  <div id="select-theme-popover" data-popover aria-hidden="true">
    <div role="listbox" id="select-theme-listbox" aria-orientation="vertical" aria-labelledby="select-theme-trigger">
      <div role="option" data-value="light">Light</div>
      <div role="option" data-value="dark">Dark</div>
      <div role="option" data-value="system">System</div>
    </div>
  </div>
  <input type="hidden" name="theme" value="" />
</div>

HTML structure

<div class=“select”>

Select root. Add data-placeholder to show placeholder text when no value is selected. Supports data-close-on-select=“true” for multiple select and data-format=“object” for serialized object values.

<button type=“button”>
Trigger button. Use aria-haspopup=“listbox”, aria-expanded, and aria-controls.
<div data-popover aria-hidden=“true”>

Popover content. Supports data-side and data-align through the shared Popover rules.

<div role=“listbox”>

Options container. Add aria-multiselectable=“true” for multiple selection.

<div role=“option” data-value=”…” data-label=”…”>
Selectable option. data-value is submitted. data-label is optional and controls the selected display label and data-format=“object” label; when omitted, Basecoat uses trimmed text content.
<hr role=“separator”> Optional
Separator between groups or options.
<div role=“group”> Optional
Option group. Use aria-labelledby to connect it to its heading.
<span role=“heading”> Optional
Group heading.
<input type=“hidden”>
Submitted value. Empty value means no selection when the root has data-placeholder. Single select stores a string; multiple select stores a JSON array. With data-format=“object”, values are serialized as { value, label } objects.

JavaScript API

APITypeDescription
changeEventDispatched on selection changes with event.detail.value and event.detail.selected.
select.refresh()MethodRescans options after children change inside the existing role="listbox" element.

Examples

Groups

Scrollable

A select with many items that scrolls.

Disabled

Invalid

Please select a valid fruit.

RTL