This is an illustration of Actionsheet component.
function App() {
const [showActionsheet, setShowActionsheet] = React.useState(false)
const handleClose = () => setShowActionsheet(!showActionsheet)
return (
<Box>
<Button onPress={handleClose}>
<ButtonText>Open</ButtonText>
</Button>
<Actionsheet isOpen={showActionsheet} onClose={handleClose} zIndex={999}>
<ActionsheetBackdrop />
<ActionsheetContent h="$72" zIndex={999}>
<ActionsheetDragIndicatorWrapper>
<ActionsheetDragIndicator />
</ActionsheetDragIndicatorWrapper>
<ActionsheetItem onPress={handleClose}>
<ActionsheetItemText>Delete</ActionsheetItemText>
</ActionsheetItem>
<ActionsheetItem onPress={handleClose}>
<ActionsheetItemText>Share</ActionsheetItemText>
</ActionsheetItem>
<ActionsheetItem onPress={handleClose}>
<ActionsheetItemText>Play</ActionsheetItemText>
</ActionsheetItem>
<ActionsheetItem onPress={handleClose}>
<ActionsheetItemText>Favourite</ActionsheetItemText>
</ActionsheetItem>
<ActionsheetItem onPress={handleClose}>
<ActionsheetItemText>Cancel</ActionsheetItemText>
</ActionsheetItem>
</ActionsheetContent>
</Actionsheet>
</Box>
)
}

Installation

Step 1: Install the following dependencies:

npm i @gluestack-ui/actionsheet

Step 2: Copy and paste the following code into your project.

import { H4 } from "@expo/html-elements"
import { createActionsheet } from "@gluestack-ui/actionsheet"
import {
Pressable,
View,
Text,
ScrollView,
VirtualizedList,
FlatList,
SectionList,
Platform,
} from "react-native"
import {
tva,
withStyleContext,
withStyleContextAndStates,
} from "@gluestack-ui/nativewind-utils"
import React from "react"
import { cssInterop } from "nativewind"
export const UIActionsheet = createActionsheet({
Root: View,
Content: withStyleContext(View),
// @ts-ignore
Item:
Platform.OS === "web"
? withStyleContext(Pressable)
: withStyleContextAndStates(Pressable),
ItemText: Text,
DragIndicator: View,
IndicatorWrapper: View,
Backdrop: Pressable,
ScrollView: ScrollView,
VirtualizedList: VirtualizedList,
FlatList: FlatList,
SectionList: SectionList,
SectionHeaderText: H4,
Icon: View,
//@ts-ignore
AnimatePresence: null,
})
cssInterop(UIActionsheet, { className: "style" })
// @ts-ignore
cssInterop(UIActionsheet.Content, { className: "style" })
cssInterop(UIActionsheet.Item, { className: "style" })
cssInterop(UIActionsheet.ItemText, { className: "style" })
cssInterop(UIActionsheet.DragIndicator, { className: "style" })
cssInterop(UIActionsheet.DragIndicatorWrapper, { className: "style" })
cssInterop(UIActionsheet.Backdrop, { className: "style" })
cssInterop(UIActionsheet.ScrollView, { className: "style" })
cssInterop(UIActionsheet.VirtualizedList, { className: "style" })
cssInterop(UIActionsheet.FlatList, { className: "style" })
cssInterop(UIActionsheet.SectionList, { className: "style" })
cssInterop(UIActionsheet.SectionHeaderText, { className: "style" })
cssInterop(UIActionsheet.Icon, { className: "style" })
const actionsheetStyle = tva({ base: "w-full h-full web:pointer-events-none" })
const actionsheetContentStyle = tva({
base: "items-center rounded-tl-3xl rounded-tr-3xl p-2 bg-background0 web:pointer-events-auto web:select-none shadow-lg",
})
const actionsheetItemStyle = tva({
base: "w-full flex-row items-center p-3 rounded-sm disabled:opacity-40 disabled:web:pointer-events-auto disabled:web:cursor-not-allowed hover:bg-background-50 active:bg-background-100 focus:bg-background-100 web:focus-visible:bg-background-100",
})
const actionsheetItemTextStyle = tva({
base: "text-typography-700 font-normal font-body tracking-md text-left mx-2",
variants: {
isTruncated: {
true: "",
},
bold: {
true: "font-bold",
},
underline: {
true: "underline",
},
strikeThrough: {
true: "line-through",
},
size: {
"2xs": "text-2xs",
xs: "text-xs",
sm: "text-sm",
md: "text-md",
lg: "text-lg",
xl: "text-xl",
"2xl": "text-2xl",
"3xl": "text-3xl",
"4xl": "text-4xl",
"5xl": "text-5xl",
"6xl": "text-6xl",
},
},
defaultVariants: {
size: "md",
},
})
const actionsheetDragIndicatorStyle = tva({
base: "w-16 h-1 bg-background-400 rounded-full",
})
const actionsheetDragIndicatorWrapperStyle = tva({
base: "w-full py-1 items-center",
})
const actionsheetBackdropStyle = tva({
base: "absolute left-0 top-0 right-0 bottom-0 bg-background950 web:cursor-default web:pointer-events-auto",
})
const actionsheetScrollViewStyle = tva({
base: "w-full h-auto",
})
const actionsheetVirtualizedListStyle = tva({
base: "w-full h-auto",
})
const actionsheetFlatListStyle = tva({
base: "w-full h-auto",
})
const actionsheetSectionListStyle = tva({
base: "w-full h-auto",
})
const actionsheetSectionHeaderTextStyle = tva({
base: "leading-5 font-bold font-heading my-0 text-typography-500 p-3 uppercase",
variants: {
isTruncated: {
true: "",
},
bold: {
true: "font-bold",
},
underline: {
true: "underline",
},
strikeThrough: {
true: "line-through",
},
size: {
"5xl": "text-5xl",
"4xl": "text-4xl",
"3xl": "text-3xl",
"2xl": "text-2xl",
xl: "text-xl",
lg: "text-lg",
md: "text-md",
sm: "text-sm",
xs: "text-xs",
},
sub: {
true: "text-xs",
},
italic: {
true: "italic",
},
highlight: {
true: "bg-yellow500",
},
},
defaultVariants: {
size: "xs",
},
})
const actionsheetIconStyle = tva({
base: "bg-background-500",
variants: {
size: {
"2xs": "h-3 w-3",
xs: "h-3.5 w-3.5",
sm: "h-4 w-4",
md: "w-4 h-4",
lg: "h-5 w-5",
xl: "h-6 w-6",
},
},
defaultVariants: {
size: "sm",
},
})
const Actionsheet = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet
className={actionsheetStyle({
class: className,
})}
ref={ref}
/>
)
}
)
const ActionsheetContent = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.Content
className={actionsheetContentStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetItem = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.Item
className={actionsheetItemStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetItemText = React.forwardRef(
(
{
isTruncated,
bold,
underline,
strikeThrough,
size,
className,
...props
}: any,
ref: any
) => {
return (
<UIActionsheet.ItemText
className={actionsheetItemTextStyle({
class: className,
isTruncated,
bold,
underline,
strikeThrough,
size,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetDragIndicator = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.DragIndicator
className={actionsheetDragIndicatorStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetDragIndicatorWrapper = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.DragIndicatorWrapper
className={actionsheetDragIndicatorWrapperStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetBackdrop = React.forwardRef(
({ className, ...props }: any, ref) => {
return (
<UIActionsheet.Backdrop
{...props}
className={actionsheetBackdropStyle({
class: className,
})}
ref={ref}
/>
)
}
)
const ActionsheetScrollView = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.ScrollView
className={actionsheetScrollViewStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetVirtualizedList = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.VirtualizedList
className={actionsheetVirtualizedListStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetFlatList = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.FlatList
className={actionsheetFlatListStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetSectionList = React.forwardRef(
({ className, ...props }: any, ref: any) => {
return (
<UIActionsheet.SectionList
className={actionsheetSectionListStyle({
class: className,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetSectionHeaderText = React.forwardRef(
(
{
className,
isTruncated,
bold,
underline,
strikeThrough,
size,
sub,
italic,
highlight,
...props
}: any,
ref: any
) => {
return (
<UIActionsheet.SectionHeaderText
className={actionsheetSectionHeaderTextStyle({
class: className,
isTruncated,
bold,
underline,
strikeThrough,
size,
sub,
italic,
highlight,
})}
ref={ref}
{...props}
/>
)
}
)
const ActionsheetIcon = React.forwardRef(
({ className, size, ...props }: any, ref: any) => {
return (
<UIActionsheet.Icon
className={actionsheetIconStyle({
class: className,
size,
})}
ref={ref}
{...props}
/>
)
}
)
export {
Actionsheet,
ActionsheetContent,
ActionsheetItem,
ActionsheetItemText,
ActionsheetDragIndicator,
ActionsheetDragIndicatorWrapper,
ActionsheetBackdrop,
ActionsheetScrollView,
ActionsheetVirtualizedList,
ActionsheetFlatList,
ActionsheetSectionList,
ActionsheetSectionHeaderText,
ActionsheetIcon,
}

Step 3: Update the import paths to match your project setup.

API Reference

To use this component in your project, include the following import statement in your file.
import { Actionsheet } from "@/components/ui/Actionsheet"
export default () => (
<Actionsheet>
<ActionsheetBackdrop />
<ActionsheetContent>
<ActionsheetDragIndicatorWrapper>
<ActionsheetDragIndicator />
</ActionsheetDragIndicatorWrapper>
<ActionsheetItem>
<ActionsheetItemText />
</ActionsheetItem>
</ActionsheetContent>
</Actionsheet>
)

Component Props

This section provides a comprehensive reference list for the component props, detailing descriptions, properties, types, and default behavior for easy project integration.

Actionsheet

It inherits all the properties of React Native's View component.
Prop
Type
Default
Description
isOpen
boolean
-
If true, the Actionsheet will open. Useful for controllable state behavior.
onClose
() => any
-
Callback invoked when the Actionsheet is closed.
onOpen
() => any
-
Callback invoked when the Actionsheet is opened.
useRNModal
boolean
false
If true, renders react-native native modal.
defaultIsOpen
boolean
-
Specifies the default open state of the Actionsheet
initialFocusRef
React.RefObject<any>
-
The ref of element to receive focus when the Actionsheet opens.
finalFocusRef
React.RefObject<any>
-
The ref of element to receive focus when the Actionsheet closes
closeOnOverlayClick
boolean
-
If true, the Actionsheet will close when the overlay is clicked.
isKeyboardDismissable
boolean
-
If true, the keyboard can dismiss the Actionsheet
trapFocus
boolean
true
If true, creates a focus scope containing all elements within the Actionsheet content.
children
any
-
The content to display inside the Actionsheet
snapPoints
Array<number>
[50]
The snap points for the Actionsheet The Actionsheet will snap to the point closest to its current position. The default value is 50% of the screen height. The value should be between 0 and 100. Currently, only one snap point is supported. We plan to support multiple snap points in the future.

ActionsheetBackdrop

It is React Native's Pressable component, created using @legendapp/motion's createMotionAnimatedComponent function to add animation to the component. You can use any declarative animation library you prefer.

ActionsheetContent

It inherits all the properties of @legendapp/motion's Motion.View component. With this Actionsheet component, you have the flexibility to use any declarative animation library that suits your needs.
Descendants Styling Props Props to style child components.
Sx Prop
Description
_sectionHeaderText
Prop to style ActionsheetSectionHeaderText Component

ActionsheetDragIndicatorWrapper

It inherits all the properties of React Native's View component.

ActionsheetDragIndicator

It inherits all the properties of React Native's View component.

ActionsheetItem

It inherits all the properties of React Native's Pressable component.
Descendants Styling Props Props to style child components.
Sx Prop
Description
_text
Prop to style ActionsheetItemText Component
_icon
Prop to style ActionsheetIcon Component

ActionsheetItemText

It inherits all the properties of React Native's Text component.

ActionsheetIcon

It inherits all the properties of React Native's View component.

ActionsheetScrollView

It inherits all the properties of React Native's ScrollView component.

ActionsheetVirtualizedList

It inherits all the properties of React Native's VirtualizedList component.

ActionsheetFlatList

It inherits all the properties of React Native's FlatList component.

ActionsheetSectionList

It inherits all the properties of React Native's SectionList component.

ActionsheetSectionHeaderText

It inherits all the properties of React Native's Text component.
Note: While our Actionsheet component supports both ActionsheetScrollView and ActionsheetVirtualizedList, we recommend using VirtualizedList for better performance on large lists of items. The ScrollView option may cause performance issues on lists with many items.

Features

  • Actionsheet has aria-modal set to true.
  • Actionsheet has role set to dialog.
  • When the Actionsheet opens, focus is trapped within it.
  • Pressing Esc closes the Actionsheet
  • Clicking on the overlay closes the Actionsheet
  • Scrolling is blocked on the elements behind the Actionsheet

Accessibility

We have outlined the various features that ensure the Actionsheet component is accessible to all users, including those with disabilities. These features help ensure that your application is inclusive and meets accessibility standards.

Keyboard

  • Tab + Enter: Triggers the actionsheet action.

Screen Reader

  • VoiceOver: When the actionsheet is focused, the screen reader will announce the button group .

Spec Doc

Explore the comprehensive details of the Actionsheet in this document, including its implementation details, checklist, and potential future additions. Dive into the thought process behind the component and gain insights into its development journey.