Hussain Arif Hussain is a CS student in Pakistan whose biggest interest is learning and teaching programming to make the world a better place.

Build a custom React Native action sheet

4 min read 1196

Build A Custom React Native Action Sheet

Say you’re building an email client that lets the user manage their drafts. In this situation, it would be sensible to display a custom context menu with a list of options depending on the chosen draft.

Here is a mock-up:

Mockup Of Custom Context Menu

Sure, this solution might work. However, there are is a major problem associated with this context menu: it is not optimized for other screen sizes. This means that while our menu might look great on a laptop, it would appear tiny on a mobile screen. As a result, the user might face accessibility issues while displaying the application on a phone.

So how do we mitigate this issue?

We can solve this problem by using an action sheet.

What is an action sheet?

An action sheet is a UI element that renders a context menu on the bottom of the screen. They are often optimized for various screen sizes and have robust support for icons. Here is a simple example:

Action Sheet For Mobile

In this article, we will build and customize an iOS-like action sheet in React Native using the react-native-action-sheet module. This will be the outcome of the guide:

IOS-Like Action Sheet In React Native

Getting started

In this article, we will initialize our project using Expo. To do so, start by running the following terminal command:

expo init action-sheet-tutorial

Next, choose the option that says “minimal”:

Running Terminal Command With Minimal Option

After that, install the react-native-action-sheet package like so:

cd action-sheet-tutorial #go into project
npm install @expo/react-native-action-sheet

Building a basic action sheet

In this section, you will learn the fundamentals of the react-native-action-sheet library.

As the first step, we need to code our action sheet component. To do so, start by creating a file called ActionButton.js. Here, write the following code:

import * as React from "react";
import { useActionSheet } from "@expo/react-native-action-sheet";
import { View, Button } from "react-native";
export default function ActionButton() {
  return (
    <View>
      <Button title="More actions" onPress={() => alert("Button pressed")} />
    </View>
  );
}

In this code snippet, we have rendered a simple Button component onto the screen.

To display the ActionButton module, replace all the code in App.js to the following:

import ActionButton from "./ActionButton";
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
export default function App() {
  return (
    <ActionSheetProvider>
      <View>
        <Text>Click on 'More actions' to see your options</Text>
        <ActionButton />
      </View>
    </ActionSheetProvider>
  );
}

We have now rendered our custom component to the UI. Moreover, notice that we have wrapped our components within ActionSheetProvider tags. This tells React that our app will consist of an action sheet.

Let’s test it out! Run your program with this Bash command:

expo start

Running Program With Bash Command

Great! Our code works.

Our next step is to connect React Native’s action sheet API with our project. To make this possible, append the following snippet in ActionSheet.js:

import { useActionSheet } from "@expo/react-native-action-sheet";

const { showActionSheetWithOptions } = useActionSheet();

const openSheet = () => {
  const options = ["Delete", "Save", "Cancel"];
  const destructiveButtonIndex = 0; //the first element in 'options' will denote the Delete option
  const cancelButtonIndex = 2; //Element number 2 in the array will be the 'Cancel' button

  showActionSheetWithOptions(
    {
      options,
      cancelButtonIndex, //the third button will be the 'Cancel' button
      destructiveButtonIndex, //the first button will be the 'Delete' option
    },
    (buttonIndex) => {
      // Do something here depending on the button index selected
      alert("Index pressed: " + buttonIndex);
    }
  );

return (
  <View>
    {/*Edit your Button code here:*/}
    {/*When the button is clicked, execute the openSheet method*/}
    <Button title="More options" onPress={() => openSheet()} />
  </View>
);

This code might seem daunting at first, but it is straightforward to understand. Here is the breakdown:

  • First, we imported the useActionSheet Hook. This will let us render an action sheet according to our config
  • Later on, declare an options array that holds the user’s available choices
  • Afterwards, we passed our config into the showSheetButtonWithOptions function. As a result, React will display our custom-built action sheet
  • The second argument of this function is a callback function that will run when the client clicks on an option. In this case, we are using an alert function to inform the current index of the user’s selected choice

 Alert Function To Inform Current Index Of User’s Selected Choice

Customizing your action sheets

In this portion of the guide, you will learn how to alter the look and feel of your action sheet.

Displaying icons

The icons property will draw icons to go along with each option. This might be handy for cases where the designer wants a better looking context menu.

Here is an example of icons in action:

import Icon from "react-native-vector-icons/FontAwesome";
//create an icon array
//each item in the 'icons' array corresponds to its respective index in the 'options' array.
//each item in the array in an Icon component.
const icons = [
  <Icon name="trash" size={20} />,
  <Icon name="save" size={20} />,
  <Icon name="remove" size={20} />,
];

showActionSheetWithOptions(
  {
    options,
    cancelButtonIndex,
    destructiveButtonIndex,
    icons, //pass in our icons array
  },
  (buttonIndex) => {}
);

Adding Icons In Context Menu

You can even use images instead of icons like so:

//create an icon array
//this array comprises of `Image` components with source images
const icons = [
  <Image
    source={{
      uri: "https://www.chevychasesection3.org/sites/g/files/vyhlif406/f/styles/news_image/public/pages/trash-278x300.jpg?itok=fK7hIbG-",
    }}
    style={{ width: "200%", height: "200%" }}
  />,
  <Image
    source={{
      uri: "https://img-new.cgtrader.com/items/73665/floppy_disk_3_5_3d_model_3ds_fbx_blend_dae_fc20cd23-1906-47a6-b94e-643026bac619.jpg",
    }}
    style={{ width: "200%", height: "200%" }}
  />,
  <Image
    source={{
      uri: "https://about.twitter.com/content/dam/about-twitter/en/brand-toolkit/brand-download-img-1.jpg.twimg.1920.jpg",
    }}
    style={{ width: "200%", height: "200%" }}
  />,
];

showActionSheetWithOptions(
  {
    options,
    icons,
//further code..

Adding Images In Context Menu

Messages and titles for your action sheets

To display a title or a message within your menu, use the title and message argument. One use-case might be for displaying confirmation prompts. An example for this can be to show an alert when the user chooses to delete an item from a list:

showActionSheetWithOptions(
  {
    message: "Do you want to delete this draft?",
    title: "Are you sure?",
    //further options...
  }
  //further code..
);

Adding Messages To Items In Context Menu

Applying CSS styles

If you want to apply custom CSS to your action sheet, React Native provides the following arguments:

  • textStyle: Apply any text style props to the options
  • titleTextStyle: As the name suggests, this will apply text styles to the title
  • containerStyle: This will apply CSS to the container of the action sheet
  • seperatorStyle: Alter the look of the separators

Using custom CSS is crucial for situations where the developer wants to write a custom theme for their app.

Here is a code sample which uses CSS code to modify the menu:

showActionSheetWithOptions(
  {
    showSeparators: true, //display a seperator component after each item.
   //apply custom styles to the action sheet.
    containerStyle: styles.container, 
    textStyle: styles.text,
    messageTextStyle: styles.message,
    titleTextStyle: styles.title,
    //further options..
  }
  //further code..
);

//create our styles
const styles = StyleSheet.create({
  container: {
    borderRadius: 20, //our container's borders will be rounded
    backgroundColor: "#cb7856", 
  },
  message: {
    backgroundColor: "purple", 
    color: "white",
  },
  title: {
    backgroundColor: "yellow",
  },
  text: {
    paddingLeft: "40%", //our options will have a certain amount of padding
  },
});

Modify Context Menu Using CSS

Conclusion

Here is the associated Expo Snack for this project.

In this guide, you learned how to use and customize action sheets using the react-native-action-sheet module. Its documentation is clear and concise, which means working with action sheets takes up little to no effort.



Thank you so much for reading!

LogRocket: Instantly recreate issues in your React Native apps.

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — .

Hussain Arif Hussain is a CS student in Pakistan whose biggest interest is learning and teaching programming to make the world a better place.

Leave a Reply