Select

Displays a list of options for the user to pick from—triggered by a button.

Fruits
Apple
Banana
Blueberry
Grapes
Pineapple
<Select>
  <SelectTrigger className="w-[180px]">
    <SelectValue placeholder="Select a fruit" />
  </SelectTrigger>
  <SelectContent className="w-[180px]">
    <SelectGroup>
      <SelectLabel>Fruits</SelectLabel>
      <SelectItem value="apple">Apple</SelectItem>
      <SelectItem value="banana">Banana</SelectItem>
      <SelectItem value="blueberry">Blueberry</SelectItem>
      <SelectItem value="grapes">Grapes</SelectItem>
      <SelectItem value="pineapple">Pineapple</SelectItem>
    </SelectGroup>
  </SelectContent>
</Select>

Installation

uvx --from basic-components components add select
pipx run --spec basic-components components add select
pip install basic-components && components add select
  • Copy Select components below to your local environment
  • Place them in the components/ui/select directory in your project
  • Configure your jinja environment for JinjaX
  • Add the cn() helper function to your global jinja environment

Usage

<Select>
  <SelectTrigger className="w-[180px]">
    <SelectValue placeholder="Select a fruit" />
  </SelectTrigger>
  <SelectContent className="w-[180px]">
    <SelectGroup>
      <SelectLabel>Fruits</SelectLabel>
      <SelectItem value="apple">Apple</SelectItem>
      <SelectItem value="banana">Banana</SelectItem>
      <SelectItem value="blueberry">Blueberry</SelectItem>
      <SelectItem value="grapes">Grapes</SelectItem>
      <SelectItem value="pineapple">Pineapple</SelectItem>
    </SelectGroup>
  </SelectContent>
</Select>

Attributes

Component Prop Type Default Description
Select name String "" The name attribute for the input field.
Select className String "" Additional CSS classes for customization.
SelectItem value String "" The form value for the item.
SelectLabel className String "" Additional CSS classes for customization.
SelectTrigger className String "" Additional CSS classes for customization.
SelectValue placeholder String "" The placeholder text.

The value of the selected item is stored in a hidden input field.

Code

{#def
    name: str = "select",
#}
<div
    x-data="{ open: false, selectedValue: '', selectedLabel: '' }"
>
  <input
      type="hidden"
      name="{{ name }}"
      :value="selectedValue"
      {{ attrs.render() }}
  />
  {{ content }}
</div>
{#def
    className: str = ""
#}
<div
    x-data="{
        canScrollUp: false,
        canScrollDown: false,
        checkScroll() {
            const el = this.$refs.viewport;
            this.canScrollUp = el.scrollTop > 0;
            this.canScrollDown = el.scrollHeight > el.clientHeight + el.scrollTop;
        }
    }"
    x-show="open"
    x-cloak
    @click.away="open = false"
    @scroll="checkScroll()"
    x-init="checkScroll()"
    class="absolute z-50 mt-2 max-h-96 min-w-[8rem] rounded-md border border-zinc-200 bg-white text-zinc-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50 {{ className }}"
>
  <SelectScrollUpButton
      x-show="canScrollUp"
      @mouseenter="$refs.viewport.scrollBy({ top: -40, behavior: 'smooth' }); checkScroll()"
      class="flex items-center justify-center py-1 cursor-pointer"
  >
    <ChevronUpIcon class="h-4 w-4" />
  </SelectScrollUpButton>

  <div
      x-ref="viewport"
      @scroll="checkScroll()"
      class="p-1 max-h-80 overflow-y-auto"
  >
    {{ content }}
  </div>

  <SelectScrollDownButton
      x-show="canScrollDown"
      @mouseenter="$refs.viewport.scrollBy({ top: 40, behavior: 'smooth' }); checkScroll()"
      class="flex items-center justify-center py-1 cursor-pointer"
  >
    <ChevronDownIcon class="h-4 w-4" />
  </SelectScrollDownButton>
</div>
<div>
  {{ content }}
</div>
{#def value: str = "" #}
<div
    @click="selectedValue = '{{ value }}'; selectedLabel = '{{ content }}'; open = false"
    class="relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm hover:bg-zinc-100 dark:hover:bg-zinc-800"
>
  <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center" x-show="selectedValue === '{{ value }}'">
    <CheckIcon className="h-4 w-4" />
  </span>
  <span>{{ content }}</span>
</div>
{#def className: str = "" #}
<div class="py-1.5 pl-8 pr-2 text-sm font-semibold {{ className }}">
  {{ content }}
</div>
<div
    x-show="canScrollDown"
    @mouseenter="
        scrollInterval = setInterval(() => {
            $refs.viewport.scrollBy({ top: 40, behavior: 'smooth' });
            checkScroll();
        }, 30);
    "
    @mouseleave="clearInterval(scrollInterval)"
    class="flex items-center justify-center py-1 cursor-pointer"
>
  <ChevronDownIcon class="h-4 w-4" />
</div>
<div
    x-show="canScrollUp"
    @mouseenter="
        scrollInterval = setInterval(() => {
            $refs.viewport.scrollBy({ top: -40, behavior: 'smooth' });
            checkScroll();
        }, 30);
    "
    @mouseleave="clearInterval(scrollInterval)"
    class="flex items-center justify-center py-1 cursor-pointer"
>
  <ChevronUpIcon class="h-4 w-4" />
</div>
{#def className: str = "" #}
<div class="relative">
<button id="selectTrigger"
    @click="open = !open"
    class="flex h-10 w-full items-center justify-between rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm ring-offset-white focus:outline-none dark:border-zinc-800 dark:bg-zinc-950 dark:ring-offset-zinc-950 placeholder:text-muted-foreground {{ className }}"
    {{ attrs.render() }}
>
  {{ content }}
  <ChevronDownIcon className="h-4 w-4 opacity-50" />
</button>
</div>
{#def
    placeholder: str = ""
#}
<span x-text="selectedLabel || '{{ placeholder }}'"></span>

Examples

Scrollable

North America
Eastern Standard Time (EST)
Central Standard Time (CST)
Mountain Standard Time (MST)
Pacific Standard Time (PST)
Alaska Standard Time (AKST)
Hawaii Standard Time (HST)
Europe & Africa
Greenwich Mean Time (GMT)
Central European Time (CET)
Eastern European Time (EET)
Western European Summer Time (WEST)
Central Africa Time (CAT)
East Africa Time (EAT)
Asia
Moscow Time (MSK)
India Standard Time (IST)
China Standard Time (CST)
Japan Standard Time (JST)
Korea Standard Time (KST)
Indonesia Central Standard Time (WITA)
Australia & Pacific
Australian Western Standard Time (AWST)
Australian Central Standard Time (ACST)
Australian Eastern Standard Time (AEST)
New Zealand Standard Time (NZST)
Fiji Time (FJT)
South America
Argentina Time (ART)
Bolivia Time (BOT)
Brasilia Time (BRT)
Chile Standard Time (CLT)
<Select>
  <SelectTrigger className="w-[280px]">
    <SelectValue placeholder="Select a timezone" />
  </SelectTrigger>
  <SelectContent className="w-[280px]">
    <SelectGroup>
      <SelectLabel>North America</SelectLabel>
      <SelectItem value="est">Eastern Standard Time (EST)</SelectItem>
      <SelectItem value="cst">Central Standard Time (CST)</SelectItem>
      <SelectItem value="mst">Mountain Standard Time (MST)</SelectItem>
      <SelectItem value="pst">Pacific Standard Time (PST)</SelectItem>
      <SelectItem value="akst">Alaska Standard Time (AKST)</SelectItem>
      <SelectItem value="hst">Hawaii Standard Time (HST)</SelectItem>
    </SelectGroup>
    <SelectGroup>
      <SelectLabel>Europe & Africa</SelectLabel>
      <SelectItem value="gmt">Greenwich Mean Time (GMT)</SelectItem>
      <SelectItem value="cet">Central European Time (CET)</SelectItem>
      <SelectItem value="eet">Eastern European Time (EET)</SelectItem>
      <SelectItem value="west">
        Western European Summer Time (WEST)
      </SelectItem>
      <SelectItem value="cat">Central Africa Time (CAT)</SelectItem>
      <SelectItem value="eat">East Africa Time (EAT)</SelectItem>
    </SelectGroup>
    <SelectGroup>
      <SelectLabel>Asia</SelectLabel>
      <SelectItem value="msk">Moscow Time (MSK)</SelectItem>
      <SelectItem value="ist">India Standard Time (IST)</SelectItem>
      <SelectItem value="cst_china">China Standard Time (CST)</SelectItem>
      <SelectItem value="jst">Japan Standard Time (JST)</SelectItem>
      <SelectItem value="kst">Korea Standard Time (KST)</SelectItem>
      <SelectItem value="ist_indonesia">
        Indonesia Central Standard Time (WITA)
      </SelectItem>
    </SelectGroup>
    <SelectGroup>
      <SelectLabel>Australia & Pacific</SelectLabel>
      <SelectItem value="awst">
        Australian Western Standard Time (AWST)
      </SelectItem>
      <SelectItem value="acst">
        Australian Central Standard Time (ACST)
      </SelectItem>
      <SelectItem value="aest">
        Australian Eastern Standard Time (AEST)
      </SelectItem>
      <SelectItem value="nzst">New Zealand Standard Time (NZST)</SelectItem>
      <SelectItem value="fjt">Fiji Time (FJT)</SelectItem>
    </SelectGroup>
    <SelectGroup>
      <SelectLabel>South America</SelectLabel>
      <SelectItem value="art">Argentina Time (ART)</SelectItem>
      <SelectItem value="bot">Bolivia Time (BOT)</SelectItem>
      <SelectItem value="brt">Brasilia Time (BRT)</SelectItem>
      <SelectItem value="clt">Chile Standard Time (CLT)</SelectItem>
    </SelectGroup>
  </SelectContent>
</Select>