Presets

Blocks

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.

Upgrade
JoinLogin
Presets
Monochrome
Overview
  • Introduction
  • Components
  • Installation
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • CalendarNEW
  • Card
  • CarouselNEW
  • Checkbox
  • Collapsible
  • Dialog
  • Dropdown Menu
  • Empty
  • Field
  • Input
  • Input Group
  • Item
  • Kbd
  • Label
  • Native Select
  • Scroll Area
  • SelectNEW
  • Separator
  • SwitchNEW
  • Table
  • Tabs
  • Textarea
  • TooltipNEW

Select

PreviousNext

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

1import {2  Select,3  SelectContent,4  SelectControl,

Installation

pnpm dlx sprawlify@latest add select
npx sprawlify@latest add select
yarn sprawlify@latest add select
bunx --bun sprawlify@latest add select

Install the following dependencies:

pnpm add @sprawlify/primitives @sprawlify/solid
npm install @sprawlify/primitives @sprawlify/solid
yarn add @sprawlify/primitives @sprawlify/solid
bun add @sprawlify/primitives @sprawlify/solid

Add the following files to your project:

select.tsx
1import { cn } from "@/lib/utils";2import { sprawlify } from "@sprawlify/solid";3import { Select as SelectPrimitive } from "@sprawlify/solid/select";4import { CheckIcon, ChevronsUpDownIcon } from "lucide-solid";5import { splitProps, type ComponentProps } from "solid-js";6import { Portal } from "solid-js/web";78function Select(props: ComponentProps<typeof SelectPrimitive.Root>) {9  return <SelectPrimitive.Root data-slot="select" {...props} />;10}1112function SelectControl(props: ComponentProps<typeof SelectPrimitive.Control>) {13  const [local, others] = splitProps(props, ["class", "children"]);1415  return (16    <SelectPrimitive.Control17      data-slot="select-control"18      class={cn("relative flex w-full items-center", local.class)}19      {...others}20    >21      {local.children}22    </SelectPrimitive.Control>23  );24}2526function SelectTrigger(props: ComponentProps<typeof SelectPrimitive.Trigger>) {27  const [local, others] = splitProps(props, ["class", "children"]);2829  return (30    <SelectPrimitive.Trigger31      data-slot="select-trigger"32      class={cn(33        "flex h-9 w-full items-center gap-2 rounded-md border border-input bg-input/30 py-2 pr-10 pl-3 text-sm shadow-xs transition-[border-color,box-shadow] duration-150 ease-in-out outline-none",34        "data-placeholder-shown:text-muted-foreground",35        "hover:border-ring/50",36        "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/20",37        "data-disabled:cursor-not-allowed data-disabled:opacity-50",38        "data-invalid:border-destructive data-invalid:focus-visible:ring-destructive/20",39        local.class,40      )}41      {...others}42    >43      <div class="flex gap-2">{local.children}</div>44    </SelectPrimitive.Trigger>45  );46}4748function SelectIndicatorGroup(props: ComponentProps<typeof sprawlify.div>) {49  const [local, others] = splitProps(props, ["class", "children"]);5051  return (52    <sprawlify.div53      data-slot="select-indicator-group"54      class={cn(55        "pointer-events-none absolute inset-y-0 right-0 flex items-center gap-1 px-2.5",56        local.class,57      )}58      {...others}59    >60      {local.children}61    </sprawlify.div>62  );63}6465function SelectIndicator(props: ComponentProps<typeof SelectPrimitive.Indicator>) {66  const [local, others] = splitProps(props, ["class", "children"]);6768  return (69    <SelectPrimitive.Indicator70      data-slot="select-indicator"71      class={cn(72        "pointer-events-none absolute inset-y-0 right-0 flex items-center px-2.5 text-muted-foreground/60 [&_svg]:size-4",73        local.class,74      )}75      {...others}76    >77      {local.children ?? <ChevronsUpDownIcon />}78    </SelectPrimitive.Indicator>79  );80}8182function SelectValue(props: ComponentProps<typeof SelectPrimitive.ValueText>) {83  const [local, others] = splitProps(props, ["class"]);8485  return (86    <SelectPrimitive.ValueText87      data-slot="select-value"88      class={cn("line-clamp-1 flex-1 text-left", local.class)}89      {...others}90    />91  );92}9394function SelectPositioner(props: ComponentProps<typeof SelectPrimitive.Positioner>) {95  const [local, others] = splitProps(props, ["class"]);9697  return (98    <SelectPrimitive.Positioner99      data-slot="select-positioner"100      class={cn("outline-none", local.class)}101      {...others}102    />103  );104}105106function SelectContent(props: ComponentProps<typeof SelectPrimitive.Content>) {107  const [local, others] = splitProps(props, ["class", "children"]);108109  return (110    <Portal>111      <SelectPrimitive.Positioner data-slot="select-positioner" class="outline-none">112        <SelectPrimitive.Content113          data-slot="select-content"114          class={cn(115            "z-50 flex flex-col gap-0.5 rounded-lg border bg-popover p-1 text-popover-foreground shadow-lg outline-none",116            "min-w-(--reference-width)",117            "max-h-[min(var(--available-height,300px),300px)] overflow-y-auto",118            "origin-(--transform-origin)",119            "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-[98%]",120            "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-[98%]",121            local.class,122          )}123          {...others}124        >125          {local.children}126        </SelectPrimitive.Content>127      </SelectPrimitive.Positioner>128    </Portal>129  );130}131132const SelectHiddenSelect = SelectPrimitive.HiddenSelect;133134function SelectItem(props: ComponentProps<typeof SelectPrimitive.Item>) {135  const [local, others] = splitProps(props, ["class", "children"]);136137  return (138    <SelectPrimitive.Item139      data-slot="select-item"140      class={cn(141        "relative flex w-full cursor-default items-center gap-2 rounded-md px-2 py-1.5 pr-8 text-sm outline-none select-none",142        "data-highlighted:bg-accent data-highlighted:text-accent-foreground",143        "data-[state=checked]:font-medium",144        "data-disabled:pointer-events-none data-disabled:opacity-50",145        local.class,146      )}147      {...others}148    >149      {local.children}150    </SelectPrimitive.Item>151  );152}153154const SelectItemText = SelectPrimitive.ItemText;155156function SelectItemIndicator(props: ComponentProps<typeof SelectPrimitive.ItemIndicator>) {157  const [local, others] = splitProps(props, ["class", "children"]);158159  return (160    <SelectPrimitive.ItemIndicator161      data-slot="select-item-indicator"162      class={cn("absolute right-2 flex size-4 items-center justify-center", local.class)}163      {...others}164    >165      {local.children ?? <CheckIcon />}166    </SelectPrimitive.ItemIndicator>167  );168}169170function SelectItemGroup(props: ComponentProps<typeof SelectPrimitive.ItemGroup>) {171  const [local, others] = splitProps(props, ["class"]);172173  return (174    <SelectPrimitive.ItemGroup175      data-slot="select-item-group"176      class={cn("flex flex-col", local.class)}177      {...others}178    />179  );180}181182function SelectItemGroupLabel(props: ComponentProps<typeof SelectPrimitive.ItemGroupLabel>) {183  const [local, others] = splitProps(props, ["class"]);184185  return (186    <SelectPrimitive.ItemGroupLabel187      data-slot="select-item-group-label"188      class={cn(189        "px-2 py-1.5 text-xs font-semibold tracking-wide text-muted-foreground",190        local.class,191      )}192      {...others}193    />194  );195}196197function SelectLabel(props: ComponentProps<typeof SelectPrimitive.Label>) {198  const [local, others] = splitProps(props, ["class"]);199200  return (201    <SelectPrimitive.Label202      data-slot="select-label"203      class={cn(204        "text-sm leading-none font-medium select-none data-disabled:opacity-50",205        local.class,206      )}207      {...others}208    />209  );210}211212function SelectSeparator(props: ComponentProps<typeof sprawlify.div>) {213  const [local, others] = splitProps(props, ["class"]);214215  return (216    <sprawlify.div217      data-slot="select-separator"218      class={cn("-mx-1 my-1 h-px bg-border", local.class)}219      {...others}220    />221  );222}223224const SelectContext = SelectPrimitive.Context;225const SelectRootProvider = SelectPrimitive.RootProvider;226227export {228  Select,229  SelectControl,230  SelectTrigger,231  SelectIndicator,232  SelectValue,233  SelectPositioner,234  SelectContent,235  SelectHiddenSelect,236  SelectItem,237  SelectItemText,238  SelectItemIndicator,239  SelectItemGroup,240  SelectItemGroupLabel,241  SelectLabel,242  SelectSeparator,243  SelectIndicatorGroup,244  SelectContext,245  SelectRootProvider,246};247

Update the import paths to match your project setup.

Usage

1import {
2  Select,
3  SelectClearTrigger,
4  SelectContent,
5  SelectControl,
6  SelectHiddenSelect,
7  SelectIndicator,
8  SelectIndicatorGroup,
9  SelectItem,
10  SelectItemGroup,
11  SelectItemGroupLabel,
12  SelectItemIndicator,
13  SelectItemText,
14  SelectTrigger,
15  SelectValue,
16} from "@/components/ui/select"
1const collection = createListCollection<CollectionItem>({
2  items: [
3    { label: "Item 1", value: "item-1" },
4    { label: "Item 2", value: "item-2" },
5    { label: "Item 3", value: "item-3" },
6    { label: "Item 4", value: "item-4" },
7    { label: "Item 5", value: "item-5" },
8  ],
9})
10
11<Select collection={collection}>
12  <SelectHiddenSelect />
13  <SelectControl>
14    <SelectTrigger>
15      <SelectValue placeholder="Select an item" />
16    </SelectTrigger>
17    <SelectIndicatorGroup>
18      <SelectIndicator />
19    </SelectIndicatorGroup>
20  </SelectControl>
21  <SelectContent>
22    <SelectItemGroup>
23      <SelectItemGroupLabel>Fruits</SelectItemGroupLabel>
24      {collection.items.map((item) => (
25        <SelectItem key={item.value} item={item}>
26          <SelectItemText>{item.label}</SelectItemText>
27            <SelectItemIndicator />
28          </SelectItem>
29      ))}
30    </SelectItemGroup>
31  </SelectContent>
32</Select>

Examples

Disabled

Add the disabled prop to the Select component to disable the select.

1import {2  Select,3  SelectContent,4  SelectControl,

Groups

Use the groupBy option in createListCollection to organize items into groups.

1import {2  Select,3  SelectContent,4  SelectControl,

Invalid

Use aria-invalid to show validation errors and the data-invalid attribute to the Field component for styling.

1import { Field, FieldError, FieldLabel } from "@/components/ui/field";2import {3  Select,4  SelectContent,

Scrollable

1import {2  Select,3  SelectContent,4  SelectControl,

On This Page

InstallationUsageExamplesDisabledGroupsInvalidScrollable

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.