Dropdown Menu

A dropdown menu displays a menu of items or actions that directly relate to the button's purpose.

Pro component

Requires all-access to use the source code

Apple
Apple
1

Add the following dependencies to your project:

import { Stack } from 'expo-router';
import * as React from 'react';
import { View } from 'react-native';

import { Text } from '~/components/nativewindui/Text';
import { AlertAnchor } from '~/components/nativewindui/Alert';
import { AlertRef } from '~/components/nativewindui/Alert/types';
import { Button } from '../~/components/nativewindui/Button';
import { DropdownMenu } from '~/components/nativewindui/DropdownMenu';
import { DropdownMenuRef } from '~/components/nativewindui/DropdownMenu/types';
import {
  createDropdownItem,
  createDropdownSubMenu,
} from '~/components/nativewindui/DropdownMenu/utils';
import { useColorScheme } from '~/lib/useColorScheme';

export default function DropdownMenuScreen() {
  const [checked, setChecked] = React.useState(false);
  const [isLoading, setIsLoading] = React.useState(true);
  const { colors } = useColorScheme();
  const ref = React.useRef<DropdownMenuRef>(null);
  const alertRef = React.useRef<AlertRef>(null);

  const dynamicItems = React.useMemo(() => {
    return [
      createDropdownSubMenu({ title: 'Sub Menu', iOSItemSize: 'small', loading: isLoading }, [
        createDropdownSubMenu({ title: 'Submenu 2' }, [
          { actionKey: '1', title: 'Item 1' },
          { actionKey: '2', title: 'Item 2' },
        ]),
        createDropdownItem({ actionKey: '43', title: 'Item 3' }),
      ]),
      createDropdownItem({
        actionKey: '4',
        title: 'Checkbox Item',
        state: { checked },
        keepOpenOnPress: true,
        icon: {
          namingScheme: 'sfSymbol',
          name: 'checkmark.seal',
          color: colors.primary,
        },
      }),
      createDropdownItem({
        actionKey: '5',
        title: 'Set to loading',
        keepOpenOnPress: true,
        disabled: isLoading,
      }),
    ];
  }, [checked, isLoading]);

  return (
    <>
      <Stack.Screen options={{ title: 'Dropdown Menu' }} />
      <View className="flex-1 flex-row justify-center gap-8 p-8">
        <DropdownMenu
          title="Dropdown Menu"
          items={STATIC_ITEMS}
          onItemPress={(item) => {
            alertRef.current?.alert({
              title: 'Item Pressed',
              message: `Item ${item.actionKey} pressed`,
              buttons: [{ text: 'OK' }],
              materialWidth: 350,
            });
          }}>
          <Button>
            <Text>Open Dropdown</Text>
          </Button>
        </DropdownMenu>

        <DropdownMenu
          ref={ref}
          items={dynamicItems}
          onItemPress={(item) => {
            if (item.actionKey === '4') {
              setChecked((prev) => !prev);
              return;
            }
            if (item.actionKey === '5') {
              setIsLoading(true);
              setTimeout(() => {
                setIsLoading(false);
              }, 1500);
              return;
            }
            alertRef.current?.alert({
              title: 'Item Pressed',
              message: `Item ${item.actionKey} pressed`,
              buttons: [{ text: 'OK' }],
              materialWidth: 350,
            });
          }}>
          <Button
            variant="secondary"
            onPress={() => {
              if (isLoading) {
                setTimeout(() => {
                  setIsLoading(false);
                }, 1500);
              }
            }}>
            <Text>With State</Text>
          </Button>
        </DropdownMenu>
      </View>
      <AlertAnchor ref={alertRef} />
    </>
  );
}

const STATIC_ITEMS = [
  createDropdownSubMenu({ title: 'Submenu 1', iOSItemSize: 'small', loading: false }, [
    createDropdownSubMenu({ title: 'Sub', iOSItemSize: 'small' }, [
      { actionKey: '10', title: 'Select Me' },
      { actionKey: '20', title: 'No! Select Me!' },
    ]),
    createDropdownItem({
      actionKey: '430',
      title: 'Item 430',
      icon: { name: 'checkmark.seal', namingScheme: 'sfSymbol' },
    }),
  ]),
  createDropdownSubMenu({ title: 'Hello', iOSItemSize: 'small' }, [
    createDropdownItem({
      actionKey: '30',
      icon: { name: 'checkmark.seal', namingScheme: 'sfSymbol' },
    }),
    createDropdownItem({
      actionKey: '31',
      icon: { name: 'checkmark.seal', namingScheme: 'sfSymbol' },
    }),
    createDropdownItem({
      actionKey: '32',
      icon: { name: 'checkmark.seal', namingScheme: 'sfSymbol' },
    }),
    createDropdownItem({
      actionKey: '33',
      icon: { name: 'checkmark.seal', namingScheme: 'sfSymbol' },
    }),
  ]),
  createDropdownSubMenu({ title: '', iOSType: 'inline', iOSItemSize: 'small' }, [
    createDropdownItem({
      actionKey: '130',
      title: '💧',
    }),
    createDropdownItem({
      actionKey: '131',
      title: '💧',
    }),
    createDropdownItem({
      actionKey: '132',
      title: '💧',
    }),
    createDropdownItem({
      actionKey: '133',
      title: '💧',
    }),
  ]),
  createDropdownItem({
    actionKey: '40',
    title: 'Delete Computer',
    destructive: true,
    image: { url: 'https://picsum.photos/id/2/100', cornerRadius: 30 },
  }),
];
Logo

Unlock All Pro Screens & Components

Elevate your app with powerful, native-feeling components and templates. Build faster with beautiful ready-to-use designs.

Get all-access

Usage

The Dropdown-Menu is not compatible with the new architecture yet .

The child component needs to accept Pressable props to ensure compatibility on Android.

import { DropdownMenu } from '~/components/nativewindui/DropdownMenu';
import {
  createDropdownItem,
  createDropdownSubMenu,
} from '~/components/nativewindui/DropdownMenu/utils';
<DropdownMenu
  items={[
    createDropdownItem({
      actionKey: 'first',
      title: 'Item 1',
    }),
    createDropdownSubMenu({ title: 'Submenu 1', iOSItemSize: 'small' }, [
      createDropdownItem({
        actionKey: 'sub-first',
        title: 'Sub Item 1',
      }),
      createDropdownItem({
        actionKey: 'sub-second',
        title: 'Sub Item 2',
      }),
    ]),
  ]}
  onItemPress={(item) => {
    console.log('Item Pressed', item);
  }}>
  <Button>
    <Text>Open Dropdown</Text>
  </Button>
</DropdownMenu>

Props

DropdownMenu

Inherits all the props from React Native's View component.

PropTypeDefaultDescription
titlestringThe title of the dropdown menu.
items(DropdownItem | DropdownSubMenu)[]The items or submenus to display in the dropdown.
iOSItemSize'small' | 'medium' | 'large'The preferred item size on iOS.
childrenReact.ReactNodeThe child component to render inside the dropdown menu. It needs to accept Pressable props to ensure compatibility on Android
onItemPress(item: Omit<DropdownItem, 'icon'>, isUsingActionSheetFallback?: boolean) => voidCallback function triggered when an item is pressed.
enabledbooleantrueWhether the dropdown menu is enabled.
materialPortalHoststringThe host for the Android portal.
materialSideOffsetnumber2Side offset for Android dropdown.
materialAlignOffsetnumberAlignment offset for Android dropdown.
materialAlign'start' | 'center' | 'end'Alignment for Android dropdown.
materialWidthnumberWidth for the Android dropdown.
materialMinWidthnumberMinimum width for the Android dropdown.
materialLoadingTextstringText to display while the dropdown is loading.
materialSubMenuTitlePlaceholderstringPlaceholder title for the Android submenu.
materialOverlayClassNamestringClass name for the Android overlay.

Utils

createDropdownSubMenu: A utility function to create a dropdown sub-menu.


createDropdownItem: A utility function to create a dropdown item.


import { createDropdownSubMenu, createDropdownItem } from '~/components/nativewindui/DropdownMenu/utils';

const MENU = [
  createDropdownSubMenu({ title: 'Submenu' }, [
    createDropdownItem({ actionKey: '1', title: 'Item 1' }),
    createDropdownItem({ actionKey: '2', title: 'Item 2' }),
  ]),
];
© Ronin Technologies LLC 2024