Select
Displays a list of options for the user to pick from—triggered by a button.
<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
<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>