GitHub

Select

A select component for choosing from a list of options, ready for CMS integration.

CMSPayload CMS Integration

Select fields can be configured through CMS, allowing content editors to customize labels, placeholders, and options without code changes.

CMS Demo

See how content editors configure select fields in a CMS:

Loading...
CMS ConfigurationSimulates Payload CMS select fields with localization

Payload Form Example

// In your Payload CMS form config
export const LocationForm = {
  slug: "location-form",
  fields: [
    {
      name: "countrySelect",
      type: "group",
      fields: [
        { name: "label", type: "text", localized: true, required: true },
        { name: "placeholder", type: "text", localized: true },
        {
          name: "options",
          type: "array",
          fields: [
            { name: "value", type: "text", required: true },
            { name: "label", type: "text", localized: true, required: true },
          ],
        },
        { name: "required", type: "checkbox" },
      ],
    },
  ],
}

Rendering the Form

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@mordecai-design-system/ui"

export function LocationForm({ data }) {
  const field = data.countrySelect
  return (
    <div className="space-y-2">
      <label className="text-sm font-medium">
        {field.label}
        {field.required && <span className="text-destructive ml-1">*</span>}
      </label>
      <Select>
        <SelectTrigger>
          <SelectValue placeholder={field.placeholder} />
        </SelectTrigger>
        <SelectContent>
          {field.options.map((option) => (
            <SelectItem key={option.value} value={option.value}>
              {option.label}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  )
}

Installation

pnpm add @corew500/ui

Usage

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@mordecai-design-system/ui"
<Select>
  <SelectTrigger className="w-[180px]">
    <SelectValue placeholder="Select a fruit" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="apple">Apple</SelectItem>
    <SelectItem value="banana">Banana</SelectItem>
    <SelectItem value="orange">Orange</SelectItem>
  </SelectContent>
</Select>

Examples

With Label

<div className="space-y-2">
  <label className="text-sm font-medium">Favorite Fruit</label>
  <Select>
    <SelectTrigger className="w-[200px]">
      <SelectValue placeholder="Select a fruit" />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="apple">Apple</SelectItem>
      <SelectItem value="banana">Banana</SelectItem>
      <SelectItem value="orange">Orange</SelectItem>
    </SelectContent>
  </Select>
</div>

Disabled

<Select disabled>
  <SelectTrigger className="w-[200px]">
    <SelectValue placeholder="Disabled select" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="option1">Option 1</SelectItem>
  </SelectContent>
</Select>

With Groups

<Select>
  <SelectTrigger className="w-[200px]">
    <SelectValue placeholder="Select timezone" />
  </SelectTrigger>
  <SelectContent>
    <SelectGroup>
      <SelectLabel>North America</SelectLabel>
      <SelectItem value="est">Eastern Standard Time (EST)</SelectItem>
      <SelectItem value="cst">Central Standard Time (CST)</SelectItem>
      <SelectItem value="pst">Pacific Standard Time (PST)</SelectItem>
    </SelectGroup>
    <SelectGroup>
      <SelectLabel>Europe</SelectLabel>
      <SelectItem value="gmt">Greenwich Mean Time (GMT)</SelectItem>
      <SelectItem value="cet">Central European Time (CET)</SelectItem>
    </SelectGroup>
  </SelectContent>
</Select>

Sub-components

| Component | Description | |-----------|-------------| | Select | The root component | | SelectTrigger | The button that toggles the select | | SelectValue | Displays the selected value | | SelectContent | The dropdown container | | SelectItem | An individual option | | SelectGroup | Groups related options | | SelectLabel | Label for a group | | SelectSeparator | Visual separator between items |

Props

Select

PropTypeDefaultDescription
inputRefenum—A ref to access the hidden input element.
namestring—Identifies the field when a form is submitted.
idstring—The id of the Select.
requiredenumfalseWhether the user must choose a value before submitting a form.
readOnlyenumfalseWhether the user should be unable to choose a different option from the select popup.
disabledenumfalseWhether the component should ignore user interaction.
multipleenumfalseWhether multiple items can be selected.
highlightItemOnHoverenumtrueWhether moving the pointer over items should highlight them. Disabling this prop allows CSS `:hover` to be differentiated from the `:focus` (`data-highlighted`) state.
defaultOpenenumfalseWhether the select popup is initially open. To render a controlled select popup, use the `open` prop instead.
onOpenChange(open: boolean, eventDetails: SelectRootChangeEventDetails) => void—Event handler called when the select popup is opened or closed.
onOpenChangeComplete(open: boolean) => void—Event handler called after any animations complete when the select popup is opened or closed.
openenum—Whether the select popup is currently open.
modalenumtrueDetermines if the select enters a modal state when open. - `true`: user interaction is limited to the select: document page scroll is locked and pointer interactions on outside elements are disabled. - `false`: user interaction with the rest of the document is allowed.
actionsRefRefObject<SelectRootActions>—A ref to imperative actions. - `unmount`: When specified, the select will not be unmounted when closed. Instead, the `unmount` function must be called to unmount the select manually. Useful when the select's animation is controlled by an external library.
itemsenum—Data structure of the items rendered in the select popup. When specified, `<Select.Value>` renders the label of the selected item instead of the raw value. @example ```tsx const items = { sans: 'Sans-serif', serif: 'Serif', mono: 'Monospace', cursive: 'Cursive', }; <Select.Root items={items} /> ```
itemToStringLabel(itemValue: Value) => string—When the item values are objects (`<Select.Item value={object}>`), this function converts the object value to a string representation for display in the trigger. If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
itemToStringValue(itemValue: Value) => string—When the item values are objects (`<Select.Item value={object}>`), this function converts the object value to a string representation for form submission. If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop.
isItemEqualToValue(itemValue: Value, value: Value) => boolean—Custom comparison logic used to determine if a select item value matches the current selected value. Useful when item values are objects without matching referentially. Defaults to `Object.is` comparison.
defaultValueSelectValueType<Value, Multiple>—The uncontrolled value of the select when it’s initially rendered. To render a controlled select, use the `value` prop instead.
valueSelectValueType<Value, Multiple>—The value of the select. Use when controlled.
onValueChange(value: SelectValueType<Value, Multiple> | (Multiple extends true ? never : null), eventDetails: SelectRootChangeEventDetails) => void—Event handler called when the value of the select changes.

SelectTrigger

PropTypeDefaultDescription
disabledenum—Whether the component should ignore user interaction.
nativeButtonenumfalseWhether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `true` if the rendered element is a native button.
styleenum—Style applied to the element, or a function that returns a style object based on the component’s state.
classNameenum—CSS class applied to the element, or a function that returns a class based on the component’s state.
renderenum—Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
sizeenumdefaultSize variant affecting height and spacing

SelectItem

PropTypeDefaultDescription
valueanynullA unique value that identifies this select item.
disabledenumfalseWhether the component should ignore user interaction.
labelstring—Specifies the text label to use when the item is matched during keyboard text navigation. Defaults to the item text content if not provided.
nativeButtonenumfalseWhether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `true` if the rendered element is a native button.
classNameenum—CSS class applied to the element, or a function that returns a class based on the component’s state.
styleenum—Style applied to the element, or a function that returns a style object based on the component’s state.
renderenum—Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.