Skip to content
React NativeBeta

Menu

Action menus with checkbox and radio items and submenus. An action sheet on phones, a popover on tablets.

Beta. React Native support is in beta. APIs may change or break between prereleases (npm tag native).

On this page
Web preview — real device may differ
tsx
import { useState } from "react";
import { Text } from "react-native";
import { Button } from "@/component-lib/button";
import {
  Menu,
  MenuCheckboxItem,
  MenuGroup,
  MenuItem,
  MenuRadioGroup,
  MenuRadioItem,
  MenuSeparator,
  MenuSub,
} from "@/component-lib/menu";
import { useKitTheme } from "@/component-lib/shared/native";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo
 
export function MenuDemo() {
  const { tokens } = useKitTheme();
  const [last, setLast] = useState("—");
  const [wrap, setWrap] = useState(true);
  const [density, setDensity] = useState("comfortable");
 
  const items = (
    <>
      <MenuGroup label="Invoice">
        <MenuItem onSelect={() => setLast("Edit")} shortcut="⌘E">
          Edit
        </MenuItem>
        <MenuItem onSelect={() => setLast("Duplicate")}>Duplicate</MenuItem>
        <MenuSub label="Export as">
          <MenuItem onSelect={() => setLast("PDF")}>PDF</MenuItem>
          <MenuItem onSelect={() => setLast("CSV")}>CSV</MenuItem>
          <MenuSub label="Spreadsheet">
            <MenuItem onSelect={() => setLast("XLSX")}>Excel (.xlsx)</MenuItem>
            <MenuItem disabled>Google Sheets</MenuItem>
          </MenuSub>
        </MenuSub>
        <MenuItem disabled>Send reminder</MenuItem>
      </MenuGroup>
      <MenuSeparator />
      <MenuCheckboxItem checked={wrap} onCheckedChange={setWrap}>
        Wrap long lines
      </MenuCheckboxItem>
      <MenuRadioGroup label="Density" value={density} onValueChange={setDensity}>
        <MenuRadioItem value="compact">Compact</MenuRadioItem>
        <MenuRadioItem value="comfortable">Comfortable</MenuRadioItem>
      </MenuRadioGroup>
      <MenuSeparator />
      <MenuItem destructive onSelect={() => setLast("Delete")}>
        Delete invoice
      </MenuItem>
    </>
  );
 
  return (
    <Section title="Menu · items, groups, submenus">
      <Row>
        <Menu trigger={<Button variant="outline">Actions (auto)</Button>} label="Invoice actions">
          {items}
        </Menu>
        <Menu trigger={<Button variant="outline">As popover</Button>} presentation="popover">
          {items}
        </Menu>
      </Row>
      <Text style={{ color: tokens.muted }}>
        Last: {last} · wrap {wrap ? "on" : "off"} · {density}
      </Text>
    </Section>
  );
}

Install

npx @grampro/kit@native add Menu

Usage

tsx
import { Menu, MenuItem } from "@/component-lib/menu";
 
<Menu trigger={<Button variant="outline">Actions</Button>}>
  <MenuItem onSelect={duplicate}>Duplicate</MenuItem>
  <MenuItem onSelect={archive}>Archive</MenuItem>
</Menu>

Props

PropTypeDescription
trigger (required)ReactElement<TriggerProps>The element that opens the menu, cloned with a ref (to measure where it is) and an onPress. Any Kit button, or any Pressable, works.
children (required)ReactNode
openbooleanControlled open state.
defaultOpenbooleanOpen to begin with, when you are not controlling open.
onOpenChange(open: boolean, reason?: MenuCloseReason) => voidreason is outside (tap outside or Android back), trigger, select or api, and undefined when opening.
labelstringNames the menu for screen readers. Defaults to the locale text.
sideMenuSideDefault bottom. Popover presentation only.
alignMenuAlignDefault start. Popover presentation only.
gapnumberDistance from the trigger. Default 4.
closeOnSelectbooleanClose the menu when an item is chosen. Default true.
presentation"auto" | "sheet" | "popover"auto (default): an action sheet on phones, a popover on tablets. Or force sheet or popover.
styleStyleProp<ViewStyle>The list's style.
stylesMenuStyles
localeTextPartial<MenuLocaleText>
PropTypeDescription
onSelect() => voidCalled when the item is chosen.
closeOnSelectbooleanKeep the menu open after choosing. Defaults to the Menu's closeOnSelect.
children (required)ReactNode
iconReactNodeDrawn before the label.
shortcutReactNodeA hint such as ⌘K, for hardware keyboards. The menu shows it; binding the key is up to you.
disabledboolean
destructivebooleanStyles it as a destructive action.
styleStyleProp<ViewStyle>
PropTypeDescription
label (required)ReactNodeThe label of the item that opens the submenu.
children (required)ReactNode
iconReactNodeDrawn before the submenu's label.
disabledboolean
styleStyleProp<ViewStyle>

Native and web

  • In a sheet, a submenu replaces the list with a back row.
  • Web version: Menu on the web.