Skip to content
Vy logo
  • Identitet
  • Spor
  • Resources
Components

Select

Selects are dropdown lists with custom-designed options.

FigmaGitHub

Examples

A basic Select

() => {
  const transportationTypes = createListCollection({
    items: [
      {
        label: "Train",
        value: "train",
      },
      {
        label: "Bus",
        value: "bus",
      },
      {
        label: "Boat",
        value: "boat",
      }
    ]
  })
  return (
    <Select collection={transportationTypes} label="Choose transportation">
     {transportationTypes.items.map((item, index) => (
       <SelectItem key={index} item={item}>
         {item.label}
       </SelectItem>
     ))}
    </Select>
  )
}

Items with label and description

() => {
  const transportationTypes = createListCollection({
    items: [
      {
        label: "Train",
        value: "train",
        description: "Tougher than trains",
      },
      {
        label: "Bus",
        value: "bus",
        description: "Broom brooooom brooom",
      },
      {
        label: "Boat",
        value: "boat",
        description: "Captain of the sea",
      }
    ]
  })
  return (
    <Select collection={transportationTypes} label="Choose transportation">
     {transportationTypes.items.map((item, index) => (
       <SelectItem 
         key={index} 
         item={item} 
         description={item.description}
        >
         {item.label}
       </SelectItem>
     ))}
    </Select>
  )
}

InfoSelect med ikoner og tekst

() => {
  const transportationTypes = createListCollection({
    items: [
      {
        label: "Train",
        value: "train",
        icon: TrainOutline24Icon,
      },
      {
        label: "Plane",
        value: "plane",
        icon: AirplaneOutline24Icon,
      },
      {
        label: "Scooter",
        value: "scooter",
        icon: ScooterOutline24Icon
      }
    ]
  })
  return (
    <Select collection={transportationTypes} label="Choose transportation">
     {transportationTypes.items.map((item, index) => (
       <SelectItem key={index} item={item}>
         <item.icon aria-hidden="true" marginRight={1} />
         {item.label}
       </SelectItem>
     ))}
    </Select>
  )
}

With error text and invalid, for form validation

() => {
  const transportationTypes = createListCollection({
    items: [
      {
        label: "Train",
        value: "train",
      },
      {
        label: "Bus",
        value: "bus",
      },
      {
        label: "Boat",
        value: "boat",
      }
    ]
  })
  return (
    <Select collection={transportationTypes} label="Choose transportation" invalid={true} errorText="You must choose">
     {transportationTypes.items.map((item, index) => (
       <SelectItem key={index} item={item}>
         {item.label}
       </SelectItem>
     ))}
    </Select>
  )
}

Multipleselect

() => {
  const transportationTypes = createListCollection({
    items: [
      {
        label: "Train",
        value: "train",
      },
      {
        label: "Bus",
        value: "bus",
      },
      {
        label: "Boat",
        value: "boat",
      }
    ]
  })
  return (
    <Select collection={transportationTypes} label="Choose transportation" multiple>
     {transportationTypes.items.map((item, index) => (
       <SelectItem key={index} item={item}>
         {item.label}
       </SelectItem>
     ))}
    </Select>
  )
}

Controlled

() => {
  const [color, setColor] = React.useState(["greenHaze"]);
  const colors = createListCollection({
    items: [
      {
        label: "Green haze",
        value: "greenHaze",
      },
      {
        label: "Saffron",
        value: "saffron",
      },
      {
        label: "Ocean",
        value: "ocean",
      }
    ]
  });
  return (
    <Box>
      <SmileOutline30Icon color={color} marginBottom="1"/>
      <Select 
        collection={colors} 
        label="Choose color"
        defaultValue={["greenHaze"]}
        onValueChange={(newColor) => setColor(newColor.value)}
      >
       {colors.items.map((item, index) => (
         <SelectItem 
           key={index} 
           item={item}
          >
           {item.label}
         </SelectItem>
       ))}
      </Select>
    </Box>
  )
}

Different variants

() => {
  const transportationTypes = createListCollection({
    items: [
      {
        label: "Train",
        value: "train",
      },
      {
        label: "Plane",
        value: "plane",
      },
      {
        label: "Scooter",
        value: "scooter",
      }
    ]
  })
  return (
    <Stack gap={2}>
     <Select 
        collection={transportationTypes} 
        label="Core"
      >
       {transportationTypes.items.map((item, index) => (
         <SelectItem key={index} item={item}>
           {item.label}
         </SelectItem>
       ))}
      </Select>
      <Select 
        collection={transportationTypes} 
        label="Floating"
        variant="floating"
      >
       {transportationTypes.items.map((item, index) => (
         <SelectItem key={index} item={item}>
           {item.label}
         </SelectItem>
       ))}
      </Select>
    </Stack>
  )
}

Info label only for screen reader:

<Select isLabelSrOnly={true} label="Velg en farge">
  <SelectItem>Grønn</SelectItem>
  <SelectItem>Gul</SelectItem>
  <SelectItem>Oransje</SelectItem>
</Select>

Guidelines

Selects should be used when you want to place special emphasis on the choices. Some options may include icons or other graphical elements, such as line tags or other features.

Trenger du det egentlig?

Vurdér alltid om du egentlig trenger en info select komponent - som regel er det en bedre brukeropplevelse å bruke NativeSelect-komponenten istedenfor.

Code

<Select />

import { Select } from "@vygruppen/spor-react";

Customizable Select, with a bunch of useful props

Props

Name
Type
Required?
Description
labelstringA descriptive label of what the user is choosing
childrenReact.ReactNode | (item) => React.ReactNodeAccepts both a list of Item elements or a render function that receives each item passed in the items prop
onValueChange(selectedKey: string | number) => void
openbooleanControlling if the menu is open or not
onOpenChange(isOpen: boolean) => voidCallback for when the menu is toggled
namestringThe `name` attribute of the underlying select.
disabledboolean
widthResponsiveValue<string | number>Default 100%
isLabelSrOnlybooleanDefault false. Used to visually hide info, but keep it for screen readers.
variant"core" | "floating" | "rightSideSquare" | "leftSideSquare"Defaults to core.
readOnlybooleanDecide if the dropdown list is read only or not, default false
collectionListCollection<T>Array of items example [{label: "Train", value: "train" }]

<SelectItem />

import { SelectItem } from "@vygruppen/spor-react";

Used in a InfoSelect or Combobox

Props

Name
Type
Required?
Description
keystring
textValuestringThe text version of the item, used by screen readers
childrenReact.ReactNodeThe content of the item
valuenumber | stringThe value returned when selected
itemobject[]Example { label: "Train", value: "train", description: "Tougher than trains", icon: "arrow" }

styling

This component is built using a slot recipe.

Slot recipe for Select

To override the styles for this component globally across your project, refer to the documentation on customizing component stylesEkstern lenke.

You can also target and style specific parts of the Select component using CSS selectors.

Select component parts

  • root
  • label
  • trigger
  • indicator-group
  • indicator
  • content
  • item
  • control
  • item-text
  • item-group
  • item-group-label
  • value-text
  • item-description

To override the recipe styles for these parts, use the css prop together with the corresponding slotRecipeParts as CSS selectors.

Use the selector format:

& [data-part="part"] {
/* styles */
}
Example of customized trigger and label for Select:
() => {
    const transportationTypes = createListCollection({
        items: [
            {
                label: 'Train',
                value: 'train',
            },
            {
                label: 'Bus',
                value: 'bus',
            },
            {
                label: 'Boat',
                value: 'boat',
            },
        ],
    })
    return (
        <Select
            collection={transportationTypes}
            label="Choose transportation"
            css={{
                '& [data-part="trigger"]': {
                    backgroundColor: 'surface.tertiary',
                },
                 '& [data-part="label"]': {
                    color: 'text.inverted',
                },
            }}
        >
            {transportationTypes.items.map((item, index) => (
                <SelectItem key={index} item={item}>
                    {item.label}
                </SelectItem>
            ))}
        </Select>
    )
}