Skip to content
Vy logo
Components

Menu

A menu can be used to create an accessible dropdown menu.

Examples

A simple menu

<Menu> 
  <MenuTrigger> Menu </MenuTrigger>
  <MenuContent> 
    <MenuItem value="1"> Item 1  </MenuItem>
    <MenuItem value="2"> Item 2 </MenuItem>
    <MenuItem value="3"> Item 3 </MenuItem>
    <MenuItem value="4"> Item 4 </MenuItem>
  </MenuContent>
</Menu>

Different variants of menu

<Stack flexDirection="row" gap={2}>
  <Menu variant="core"> 
    <MenuTrigger> Core </MenuTrigger>
    <MenuContent> 
      <MenuItem value="1"> Item 1  </MenuItem>
    </MenuContent>
  </Menu>
  <Menu variant="floating"> 
    <MenuTrigger> Floating </MenuTrigger>
    <MenuContent> 
      <MenuItem value="1"> Item 1  </MenuItem>
    </MenuContent>
  </Menu>
    <Menu variant="accent"> 
    <MenuTrigger> Accent </MenuTrigger>
    <MenuContent> 
      <MenuItem value="1"> Item 1  </MenuItem>
    </MenuContent>
  </Menu>
</Stack>

Menu with a submenu

<Menu> 
    <MenuTrigger> Menu </MenuTrigger>
    <MenuContent> 
      <MenuItem value="1"> Item 1  </MenuItem>
      <Menu> 
          <MenuTriggerItem value="2" rightIcon={<DropdownRightOutline24Icon />}> Item 2 </MenuTriggerItem>
          <MenuContent> 
            <MenuItem value="submenu1">Submenu item 1</MenuItem>
            <MenuItem value="submenu2">Submenu item 2</MenuItem>
          </MenuContent>
      </Menu>
    </MenuContent>
  </Menu>

Menu with icons in the items

<Menu> 
  <MenuTrigger> Menu </MenuTrigger>
  <MenuContent> 
    <MenuItem value="1" leftIcon={<StarsOutline24Icon />}> Item 1  </MenuItem>
    <MenuItem value="2" rightIcon={<StarsOutline24Icon />}> Item 2 </MenuItem>
    <MenuItem value="3" leftIcon={<StarsOutline24Icon />} rightIcon={<StarsOutline24Icon />}> Item 3 </MenuItem>
  </MenuContent>
</Menu>

Menu with multiselect (checkboxes)

() => {
  const [checkedValues, setCheckedValues] = React.useState<string[]>(["autosave"])
const items = [
  { title: "Autosave", value: "autosave" },
  { title: "Detect Language", value: "detect-language" },
  { title: "Spellcheck", value: "spellcheck" },
]
  const toggleValue = (value: string) => {
    setCheckedValues(prev =>
      prev.includes(value)
        ? prev.filter(v => v !== value)
        : [...prev, value]
    )
  }
  const isChecked = (value: string) => checkedValues.includes(value)

  return (
    <Menu>
      <MenuTrigger>
         Features
      </MenuTrigger>
          <MenuContent>
            <MenuItemGroup label="Features">
              {items.map(({ title, value }) => (
                <MenuCheckboxItem
                  key={value}
                  value={value}
                  checked={isChecked(value)}
                  onCheckedChange={() => toggleValue(value)}
                >
                  {title}
                </MenuCheckboxItem>
              ))}
            </MenuItemGroup>
          </MenuContent>
    </Menu>
  )
}

Menu with singleselect (radiobuttons)

() => {
const [value, setValue] = React.useState("asc")

const items = [
  { label: "Ascending", value: "asc" },
  { label: "Descending", value: "desc" },
]
return <Stack textAlign="center">
    <Menu> 
    <MenuTrigger>Singleselect</MenuTrigger>
    <MenuContent> 
      <MenuRadioItemGroup
        value={value}
        onValueChange={(e) => setValue(e.value)}
      >
        {items.map((item) => (
          <MenuRadioItem key={item.value} value={item.value}>
            {item.label}
          </MenuRadioItem>
         ))}
      </MenuRadioItemGroup>
    </MenuContent>
  </Menu>
</Stack>}

Menu with items categorised in groups

<Menu> 
  <MenuTrigger> Menu </MenuTrigger>
  <MenuContent> 
    <MenuItemGroup label="Gruppe 1"> 
      <MenuItem value="1"> value 1</MenuItem>
      <MenuItem value="2"> value 2 </MenuItem>
    </MenuItemGroup>
    <MenuSeparator />
    <MenuItemGroup label="Gruppe 2"> 
      <MenuItem value="3"> value 3</MenuItem>
      <MenuItem value="4"> value 4 </MenuItem>
    </MenuItemGroup>
  </MenuContent>
</Menu>