Edit Profile

Dark Mode

Copy config

Copy and paste the following code into your global.css file to apply the styles.

Select

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

Logged in users

Installation

Run the following cli command or copy/paste the component code into your project

qwik-ui add select
import { type PropsOf, Slot, component$ } from '@builder.io/qwik';
import { Select as HeadlessSelect } from '@qwik-ui/headless';
import { cn } from '@qwik-ui/utils';
import { LuCheck, LuChevronDown } from '@qwikest/icons/lucide';
 
const Root = (props: PropsOf<typeof HeadlessSelect.Root>) => (
  <HeadlessSelect.Root
    {...props}
    selectItemComponent={Item}
    selectItemLabelComponent={ItemLabel}
    selectLabelComponent={Label}
  />
);
 
const Label = component$<PropsOf<typeof HeadlessSelect.Label>>(({ ...props }) => {
  return (
    <>
      <HeadlessSelect.Label
        {...props}
        class={cn('px-2 py-1.5 text-sm font-semibold', props.class)}
      >
        <Slot />
      </HeadlessSelect.Label>
    </>
  );
});
 
const Trigger = component$<PropsOf<typeof HeadlessSelect.Trigger>>(({ ...props }) => {
  return (
    <>
      <HeadlessSelect.Trigger
        {...props}
        class={cn(
          'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
          props.class,
        )}
      >
        <Slot />
        <LuChevronDown class="h-4 w-4 opacity-50" />
      </HeadlessSelect.Trigger>
    </>
  );
});
 
const DisplayValue = HeadlessSelect.DisplayValue;
 
const Popover = component$<PropsOf<typeof HeadlessSelect.Popover>>(({ ...props }) => {
  return (
    <>
      <HeadlessSelect.Popover
        {...props}
        class={cn(
          'w-full max-w-[15rem] data-[open]:animate-in data-[closing]:animate-out data-[closing]:fade-out-0 data-[open]:fade-in-0 data-[closing]:zoom-out-95 data-[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',
          // 'overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md',
          props.class,
        )}
      >
        <Slot />
      </HeadlessSelect.Popover>
    </>
  );
});
 
type ListboxProps = PropsOf<typeof HeadlessSelect.Listbox>;
const Listbox = component$<ListboxProps>(({ ...props }) => {
  return (
    <>
      <HeadlessSelect.Listbox
        {...props}
        class={cn(
          'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
          props.class,
        )}
      >
        <Slot />
      </HeadlessSelect.Listbox>
    </>
  );
});
 
const Group = HeadlessSelect.Group;
 
const GroupLabel = HeadlessSelect.GroupLabel;
 
const Item = component$<PropsOf<typeof HeadlessSelect.Item>>(({ ...props }) => {
  return (
    <HeadlessSelect.Item
      {...props}
      class={cn(
        'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
        'data-[highlighted]:border-base data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground',
        props.class,
      )}
    >
      <Slot />
    </HeadlessSelect.Item>
  );
});
 
const ItemIndicator = component$<PropsOf<typeof HeadlessSelect.ItemIndicator>>(
  ({ ...props }) => {
    return (
      <span class="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
        <HeadlessSelect.ItemIndicator {...props}>
          <LuCheck class="h-4 w-4" />
        </HeadlessSelect.ItemIndicator>
      </span>
    );
  },
);
 
const ItemLabel = component$<PropsOf<typeof HeadlessSelect.ItemLabel>>(({ ...props }) => {
  return (
    <HeadlessSelect.ItemLabel {...props}>
      <Slot />
    </HeadlessSelect.ItemLabel>
  );
});
 
export const Select = {
  Root,
  Label,
  Trigger,
  DisplayValue,
  Popover,
  Listbox,
  Group,
  GroupLabel,
  Item,
  ItemIndicator,
  ItemLabel,
};