Beautiful, native menus for React Native + Web, inspired by Radix UI

Last update: Jun 17, 2022

Frame 32

Beautiful, native menus for React Native + Web, inspired by Radix UI.

  • 🕺 Radix UI on Web
  • 🛫 Native elements on iOS/Android (where possible)
  • 🌲 Same API cross-platform
  • 🌊 Works with Solito and Next.js
  • 🤖 Supports Expo (with custom dev clients)
  • 🍦 Vanilla React Native too
  • 🎨 100% unstyled components

Installation

yarn add zeego

Install peer dependencies

If you're in a monorepo, you should install these in the directory of your native app.

iOS

yarn add react-native-ios-context-menu

Android

yarn add @react-native-menu/menu

Solito

As shown above, sure to install react-native-ios-context-menu and @react-native-menu/menu in your Expo folder (apps/expo).

You should also follow the Next.js steps below.

Next.js

You need to add zeego to your next-transpile-modules in next.config.js.

Expo

You need to use a custom development client, since react-native-ios-context-menu uses native code.

After installing, you'll need to rebuild your custom development client and app.

Vanilla React Native

Run pod install in your ios folder.

Philosophy

Optimized

  1. Use the best API possible
  2. Create the best experience for each platform, without concern for sharing styles
  3. Rely on built-in native menus for iOS and Android
  4. Everything ships unstyled

The API follows that of Radix UI closely.

Usage

import * as DropdownMenu from 'zeego/dropdown-menu'

See radix-ui's dropdown menu. It's really similar.

One difference is that DropdownMenu.Item needs a child DropdownMenu.ItemTitle, since React Native separates Text and View components.

">
<DropdownMenu.Item>
  <DropdownMenu.ItemTitle>Bookmark</DropdownMenu.ItemTitle>
  <DropdownMenu.ItemIcon iosIconName="bookmark">
    <YourIconComponent />
  </DropdownMenu.ItemIcon>
</DropdownMenu.Item>

Custom components

To use a custom component, you'll first need to menuify it.

Here is an example of a custom component using Dripsy:

import * as DropdownMenu from 'zeego/dropdown-menu'
import { styled } from 'dripsy'

const StyledMenuItem = styled(DropdownMenu.Item)({
  height: 32,
})

// this part is important
const DripsyMenuItem = DropdownMenu.menuify(StyledMenuItem, 'Item')

And now, you can use it:

Fernando ">
<DripsyMenuItem key="fernando">
  <DropdownMenu.ItemTitle>Fernando</DropdownMenu.ItemTitle>
<DripsyMenuItem>

Under the hood, menuify applies a displayName to your component. This allows zeego to recognize it when it's mapping children for iOS and Android.

Example

For now, you should reference the example in the repo.

I also added a Moti + Dripsy example.

In the future, I'll make an example app with Solito too.

See more {Platform.OS === 'ios' && ( 12 artists fit your search )} Favorite {bookmarked === 'on' ? 'Bookmarked' : 'Bookmark'} ) }">
const DropdownMenuExample = () => {
  const [bookmarked, setBookmarked] = useState<'on' | 'off' | 'mixed'>('on')
  return (
    <DropdownMenu.Root>
      <DropdownMenu.Trigger>
        <View>
          <Text style={styles.button}>{``}</Text>
        </View>
      </DropdownMenu.Trigger>
      <DropdownMenu.Content style={dropdownStyles.content}>
        <DropdownMenuLabel>Help</DropdownMenuLabel>
        <DropdownMenuItem
          style={dropdownStyles.item}
          onSelect={select(1)}
          key="first"
        >
          <DropdownMenuItemTitle style={dropdownStyles.itemTitle}>
            See more
          </DropdownMenuItemTitle>
          {Platform.OS === 'ios' && (
            <DropdownMenu.ItemSubtitle style={dropdownStyles.itemSubtitle}>
              12 artists fit your search
            </DropdownMenu.ItemSubtitle>
          )}
          <DropdownMenuItemIcon iosIconName="list.star" androidIconName="star_on">
            <Ionicons name="list" size={15} />
          </DropdownMenuItemIcon>
        </DropdownMenuItem>
        <DropdownMenuItem
          style={dropdownStyles.item}
          onSelect={select(2)}
          key="second"
        >
          <DropdownMenuItemTitle>Favorite</DropdownMenuItemTitle>
          <DropdownMenuItemIcon iosIconName="star.fill" androidIconName="star_off">
            <Ionicons name="star" size={15} />
          </DropdownMenuItemIcon>
        </DropdownMenuItem>
        <DropdownMenuCheckboxItem
          style={dropdownStyles.item}
          value={bookmarked}
          onValueChange={setBookmarked}
          key="third"
        >
          <DropdownMenuItemIndicator>
            <Ionicons name="checkmark" size={19} />
          </DropdownMenuItemIndicator>
          <DropdownMenuItemTitle>
            {bookmarked === 'on' ? 'Bookmarked' : 'Bookmark'}
          </DropdownMenuItemTitle>
          <DropdownMenuItemImage
            iosIconName="book"
            source={require('./camera-outline.png')}
            width={20}
            resizeMode="contain"
          />
        </DropdownMenuCheckboxItem>
      </DropdownMenu.Content>
    </DropdownMenu.Root>
  )
}

TODO

  • zeego/dropdown-menu
  • zeego/context-menu (in-progress, missing Web implementation)
  • Android native implementation
  • Docs
  • zeego/tooltip (probably?)
  • zeego/popover (probably)

Thanks

Special thanks to Dominic Go for the awesome iOS context menu. Also, thanks to the Showtime team for testing this and sending PRs.

GitHub

https://github.com/nandorojo/zeego
You might also like...

SVG library for React Native, React Native Web, and plain React web projects.

SVG library for React Native, React Native Web, and plain React web projects.

react-native-svg react-native-svg provides SVG support to React Native on iOS and Android, and a compatibility layer for the web. Check out the demo F

Jun 23, 2022

Cycle.js run() for react-native-navigation on react-native-web

Cycle Native Navigation Web Similar to and largely compatible with cycle-native-navigation but meant for use with react-native-web and Electron. npm i

Apr 8, 2022

Simple, performant & type-safe cross platform navigation in React Native / React Native Web

Simple, performant & type-safe cross platform navigation in React Native / React Native Web

Simple and performant cross platform navigation on iOS, Android and the web with simple and type-safe api for React 18 (alpha)

Mar 9, 2022

TouchBolocker is a React Native and React Native Web component that helps blocking the user from interacting with children components.

TouchBlocker is a React Native and React Native Web component that helps blocking the user from interacting with children components.

May 27, 2022

React Native template for a quick start with React Navigation5 and TypeScript. It's cross-platform runs on Android, iOS, and the web.

对此项目的规划 出于兴趣把自己做 android、ios 开发过程中经验积累沉淀一下,此工程架构会定期更新升级依赖到最新版本,并不断的积累 App 中常用组件和基础页面功能,也会不断优化代码组织架构 此项目对以下情形会有帮助 想用前端技术做 app 开发却无从下手 想在项目中运用 typescrip

May 13, 2022

High performance listview for React Native and web!

High performance listview for React Native and web!

RecyclerListView If this project has helped you out, please support us with a star 🌟 . This is a high performance listview for React Native and Web w

Jun 23, 2022

A cross-platform (iOS / Android), full-featured, highly customizable web browser module for React Native apps.

A cross-platform (iOS / Android), full-featured, highly customizable web browser module for React Native apps.

react-native-webbrowser A cross-platform (iOS / Android), full-featured in-app web browser component for React Native that is highly customizable. Cur

Apr 5, 2022

Import SVG files in your React Native project the same way that you would in a Web application.

Import SVG files in your React Native project the same way that you would in a Web application.

react-native-svg-transformer React Native SVG transformer allows you to import SVG files in your React Native project the same way that you would in a

Jun 16, 2022

A React Native library provides Image blur shadows, highly customizable and mutable component. Supports Android, iOS and Web.

A React Native library provides Image blur shadows, highly customizable and mutable component. Supports Android, iOS and Web.

A React Native library provides Image Blur Shadows, highly customizable and mutable component. Supports Android, iOS and Web.

May 31, 2022
Comments
  • 1. [Android] DropdownMenu not working

    Hello! Thanks for this cool library!

    We just tried a small snippet from the example project and found that it only works on iOS (and maybe web), but on Android, nothing is being shown when I tap on the Trigger. I this a known issue because I see that Android is supported from the documentation? Thank you!

    Repro

     <DropdownMenu.Root key={filter}>
        <DropdownMenu.Trigger>
          <ThemedChip
            key={filter}
            isSelected
            label={filter}
            style={tw('mx-2 my-2')}
            rightComponent={
              <ThemedIcon
                name="x"
                color="white"
                size={16}
                style={tw('ml-1')}
              />
            }
            // onPress={() => removeFilter(filter)}
          />
        </DropdownMenu.Trigger>
        <DropdownMenu.Content
          style={{
            minWidth: 220,
            backgroundColor: 'white',
            borderRadius: 6,
            padding: 5,
            borderWidth: 1,
            borderColor: '#fff8',
          }}
        >
          <DropdownMenuLabel>Help</DropdownMenuLabel>
    
          {[1, 2, 3].map(i => (
            <DropdownMenuItem key={`list-${i}`}>
              <DropdownMenuItemTitle>{`Item ${i}`}</DropdownMenuItemTitle>
            </DropdownMenuItem>
          ))}
        </DropdownMenu.Content>
      </DropdownMenu.Root>
    
    Reviewed by thespacemanatee at 2022-06-12 18:13
  • 2. feat: android menu

    Why?

    Adds native menu on android. The native menu is better for accessibility and has a good default animation.

    How?

    Uses @react-native-menu/menu library as a peer dependency.

    Differences between iOS and Android menu

    Android menu doesn't have a Group support (displayInline prop in iOS menu). So, flattened the group here.

    Discuss

    I think we might need a better name for iOSIconName or add androidIconName prop probably. Maybe just keep it as iconName?

    https://user-images.githubusercontent.com/23293248/173624549-55a3754e-19ce-495b-adc0-d18866917d0a.mov

    Reviewed by intergalacticspacehighway at 2022-06-14 16:00
  • 3. Conditional items mess with keys

    I'm getting a weird error. If, inside of <DropdownMenu.Content>, I have an item that is conditionally rendered, I get an error that my item keys aren't stable. This breaks it:

    <Dropdown.Content>
      <Dropdown.Item key="one" />
      {false}
    </Dropdown.Content>
    

    I think it also breaks if there is an array rendered alongside a single item:

    <Dropdown.Content>
      {items.map(item => <Dropdown.Item key={item} />)}
      <Dropdown.Item key="another-item" />
    </Dropdown.Content>
    

    Getting this issue on ios, will have to debug tomorrow.

    Reviewed by nandorojo at 2022-03-23 00:48
Text inputs with custom label and icon animations for iOS and android. Built with react native and inspired by Codrops.
Text inputs with custom label and icon animations for iOS and android. Built with react native and inspired by Codrops.

React Native Textinput Effects I've come across with those beautiful text inputs created and blogged by Codrops and wanted to port them to react-nativ

Jun 18, 2022
React Native Tip is a simple package inspired in MaterialUI-Tooltip
React Native Tip is a simple package inspired in MaterialUI-Tooltip

React Native Tip is a simple package inspired in MaterialUI-Tooltip that helps you to show a quick tip to the user and highlight some important item in your app. It is useful to explain the user some funcionality.

Jun 6, 2022
A simple search box with animation, inspired from ios search bar. Lightweight, fast, flexible.

React Native Search Box A simple search box with animation, inspired from ios search bar. Lightweight, fast, flexible, customizable. Support both iOS/

Jun 14, 2022
Path-esque circular action menu inspired by CircularFloatingActionMenu.
Path-esque circular action menu inspired by CircularFloatingActionMenu.

react-native-circular-action-menu Path-esque circular action menu inspired by CircularFloatingActionMenu. Installation npm i react-native-circular-act

May 15, 2022
inspired by Airbnb's rheostat, a powerful slider with assorted data visualized charts
inspired by Airbnb's rheostat, a powerful slider with assorted data visualized charts

react-native-rheostat inspired by Airbnb's rheostat, a powerful slider with assorted data visualized charts Features Dependencies Installation Usage E

May 3, 2022
A Beautiful, Customizable React Native Button component for iOS & Android
A Beautiful, Customizable React Native Button component for iOS & Android

React Native Button component React Native Button component for iOS & Android. Provided Components This library provided the following button componen

Jun 15, 2022
:lollipop: A React Native Loader Component which uses Airbnb's Lottie for beautiful loader animations.
:lollipop: A React Native Loader Component which uses Airbnb's Lottie for beautiful loader animations.

React Native Animated Loader Read more about this package here. A React Native Loader Component which uses Airbnb's Lottie for beautiful loader animat

Jun 11, 2022
A high performance, beautiful and fully customizable curved bottom navigation bar for React Native.
A high performance, beautiful and fully customizable curved bottom navigation bar for React Native.

react-native-curved-bottom-bar A high performance, beautiful and fully customizable curved bottom navigation bar for React Native. Getting started

Jun 21, 2022
The Beautiful Image component that supports fadeIn animation and shows placeholderSource if the main source can't be loaded. More will be implemented.
The Beautiful Image component that supports fadeIn animation and shows placeholderSource if the main source can't be loaded. More will be implemented.

react-native-beautiful-image The Image component that supports fadeIn animation and shows placeholderSource if the main source can't be loaded. More w

Feb 26, 2022
😍 A beautiful, fluid, and extensible dialogs API for Kotlin & Android.
😍 A beautiful, fluid, and extensible dialogs API for Kotlin & Android.

Material Dialogs View Releases and Changelogs Modules The core module is the fundamental module that you need in order to use this library. The others

Jun 23, 2022