{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "title": "Select",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "A Radix select with a sized trigger, popper-positioned menu, scroll buttons, groups, labels, separators and a check indicator on the chosen item.",
  "dependencies": [
    "radix-ui",
    "lucide-react"
  ],
  "devDependencies": [
    "tw-animate-css"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.ballmac.com/r/direction.json"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/select.tsx",
      "content": "// Ballmac UI: Select. https://ui.ballmac.com/components/select\n// Based on shadcn/ui's Select (MIT, Copyright (c) 2023 shadcn), restyled with trigger sizes and tw-animate-css transitions.\n\"use client\"\n\nimport * as React from \"react\"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\nimport { Select as SelectPrimitive } from \"radix-ui\"\n\nimport { useDirection } from \"@/lib/ballmac/direction\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Select(props: React.ComponentProps<typeof SelectPrimitive.Root>) {\n  const dir = useDirection(props.dir)\n  return <SelectPrimitive.Root data-slot=\"select\" dir={dir} {...props} />\n}\n\nfunction SelectGroup(props: React.ComponentProps<typeof SelectPrimitive.Group>) {\n  return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />\n}\n\nfunction SelectValue(props: React.ComponentProps<typeof SelectPrimitive.Value>) {\n  return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />\n}\n\ntype SelectTriggerProps = React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n  /** Matches Input and Button heights: sm is h-8, default is h-9. */\n  size?: \"sm\" | \"default\"\n}\n\nfunction SelectTrigger({ className, size = \"default\", children, ...props }: SelectTriggerProps) {\n  return (\n    <SelectPrimitive.Trigger\n      data-slot=\"select-trigger\"\n      data-size={size}\n      className={cn(\n        \"flex w-fit min-w-0 items-center justify-between gap-2 whitespace-nowrap rounded-md border border-input bg-background px-3 text-sm text-foreground shadow-xs outline-none transition-[color,border-color,box-shadow] duration-150 dark:bg-input/30 dark:hover:bg-input/50\",\n        \"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20\",\n        \"disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground\",\n        \"data-[size=default]:h-9 data-[size=sm]:h-8 data-[size=sm]:px-2.5 data-[size=sm]:text-[13px]\",\n        \"*:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2\",\n        \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n      <SelectPrimitive.Icon className=\"flex\">\n        <ChevronDownIcon className=\"size-4 opacity-60\" aria-hidden=\"true\" />\n      </SelectPrimitive.Icon>\n    </SelectPrimitive.Trigger>\n  )\n}\n\ntype SelectContentProps = React.ComponentProps<typeof SelectPrimitive.Content> & {\n  /** \"popper\" opens below the trigger like a menu; \"item-aligned\" overlaps the trigger like a native select. */\n  position?: \"popper\" | \"item-aligned\"\n  /** Distance in px from the trigger when position is \"popper\". */\n  sideOffset?: number\n}\n\nfunction SelectContent({\n  className,\n  children,\n  position = \"popper\",\n  align = \"start\",\n  sideOffset = 4,\n  ...props\n}: SelectContentProps) {\n  return (\n    <SelectPrimitive.Portal>\n      <SelectPrimitive.Content\n        data-slot=\"select-content\"\n        position={position}\n        align={align}\n        sideOffset={position === \"popper\" ? sideOffset : undefined}\n        className={cn(\n          \"relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg border bg-popover text-popover-foreground shadow-[0_8px_24px_-6px_rgb(0_0_0/0.18),0_2px_6px_-2px_rgb(0_0_0/0.08)]\",\n          \"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 motion-reduce:animate-none\",\n          \"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\",\n          position === \"popper\" &&\n            \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n          className\n        )}\n        {...props}\n      >\n        <SelectScrollUpButton />\n        <SelectPrimitive.Viewport\n          className={cn(\n            \"p-1\",\n            position === \"popper\" &&\n              \"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1\"\n          )}\n        >\n          {children}\n        </SelectPrimitive.Viewport>\n        <SelectScrollDownButton />\n      </SelectPrimitive.Content>\n    </SelectPrimitive.Portal>\n  )\n}\n\nfunction SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {\n  return (\n    <SelectPrimitive.Label\n      data-slot=\"select-label\"\n      className={cn(\"px-2 pt-2 pb-1 text-xs font-medium text-muted-foreground\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) {\n  return (\n    <SelectPrimitive.Item\n      data-slot=\"select-item\"\n      className={cn(\n        \"relative flex w-full cursor-default select-none items-center gap-2 rounded-md py-1.5 pe-8 ps-2 text-sm outline-hidden\",\n        \"focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n        \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n        \"*:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n        className\n      )}\n      {...props}\n    >\n      <span data-slot=\"select-item-indicator\" className=\"absolute end-2 flex size-3.5 items-center justify-center\">\n        <SelectPrimitive.ItemIndicator>\n          <CheckIcon className=\"size-4 text-foreground\" aria-hidden=\"true\" />\n        </SelectPrimitive.ItemIndicator>\n      </span>\n      <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n    </SelectPrimitive.Item>\n  )\n}\n\nfunction SelectSeparator({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n  return (\n    <SelectPrimitive.Separator\n      data-slot=\"select-separator\"\n      className={cn(\"pointer-events-none -mx-1 my-1 h-px bg-border\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectScrollUpButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n  return (\n    <SelectPrimitive.ScrollUpButton\n      data-slot=\"select-scroll-up-button\"\n      className={cn(\"flex cursor-default items-center justify-center py-1 text-muted-foreground\", className)}\n      {...props}\n    >\n      <ChevronUpIcon className=\"size-4\" aria-hidden=\"true\" />\n    </SelectPrimitive.ScrollUpButton>\n  )\n}\n\nfunction SelectScrollDownButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n  return (\n    <SelectPrimitive.ScrollDownButton\n      data-slot=\"select-scroll-down-button\"\n      className={cn(\"flex cursor-default items-center justify-center py-1 text-muted-foreground\", className)}\n      {...props}\n    >\n      <ChevronDownIcon className=\"size-4\" aria-hidden=\"true\" />\n    </SelectPrimitive.ScrollDownButton>\n  )\n}\n\nexport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectLabel,\n  SelectScrollDownButton,\n  SelectScrollUpButton,\n  SelectSeparator,\n  SelectTrigger,\n  SelectValue,\n  type SelectContentProps,\n  type SelectTriggerProps,\n}\n",
      "type": "registry:ui",
      "target": "@components/ballmac/select.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "select",
      "dropdown",
      "form",
      "radix",
      "listbox"
    ],
    "version": "1.0.0",
    "updated": "2026-09-28",
    "ai": {
      "summary": "Pick one value from a list. Compose Select > SelectTrigger > SelectValue and SelectContent > SelectItem (group with SelectGroup + SelectLabel). The menu is portalled and keyboard navigable with typeahead.",
      "whenToUse": [
        "Choosing one option from 4 to 20 fixed values (timezone, role, region)",
        "Compact filters in toolbars (size sm)",
        "Grouped options such as regions by continent"
      ],
      "whenNotToUse": [
        "Two or three options that should stay visible (use a radio group or segmented control)",
        "Long searchable lists (use a combobox)",
        "Actions rather than values (use a dropdown menu)"
      ],
      "composesWith": [
        "label",
        "button",
        "dialog"
      ],
      "a11y": [
        {
          "keys": "Space / Enter / ArrowDown",
          "action": "Opens the menu"
        },
        {
          "keys": "ArrowUp / ArrowDown",
          "action": "Moves between items"
        },
        {
          "keys": "Enter",
          "action": "Selects the focused item"
        },
        {
          "keys": "Type a letter",
          "action": "Jumps to the matching item"
        },
        {
          "keys": "Escape",
          "action": "Closes the menu"
        }
      ],
      "customization": [
        "SelectTrigger size: sm | default",
        "SelectContent position: popper (default, below the trigger) | item-aligned",
        "Items accept icons before the text",
        "Needs the tw-animate-css classes for the open and close animation"
      ]
    },
    "source": {
      "name": "shadcn/ui Select",
      "url": "https://github.com/shadcn-ui/ui",
      "license": "MIT",
      "copyright": "Copyright (c) 2023 shadcn",
      "modified": true
    },
    "examples": [
      "select-demo",
      "select-grouped"
    ],
    "url": "https://ui.ballmac.com/components/select"
  },
  "categories": [
    "primitives"
  ],
  "type": "registry:ui"
}