Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
import { ActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { View } from '@/components/ui/view';
import React, { useState } from 'react';
export function ActionSheetDemo() {
const [visible, setVisible] = useState(false);
const options = [
{
title: 'Edit',
onPress: () => console.log('Edit pressed'),
},
{
title: 'Share',
onPress: () => console.log('Share pressed'),
},
{
title: 'Delete',
onPress: () => console.log('Delete pressed'),
destructive: true,
},
];
return (
<View>
<Button onPress={() => setVisible(true)}>Show Action Sheet</Button>
<ActionSheet
visible={visible}
onClose={() => setVisible(false)}
title='Choose an action'
message='Select one of the options below'
options={options}
/>
</View>
);
}
Installation
pnpm dlx bna-ui add action-sheet
Usage
import { ActionSheet, useActionSheet } from '@/components/ui/action-sheet';
Basic Usage with Hook
function MyComponent() {
const { show, ActionSheet } = useActionSheet();
const handleShowActionSheet = () => {
show({
title: 'Choose an option',
options: [
{
title: 'Edit',
onPress: () => console.log('Edit pressed'),
},
{
title: 'Delete',
onPress: () => console.log('Delete pressed'),
destructive: true,
},
],
});
};
return (
<>
<Button onPress={handleShowActionSheet}>Show Action Sheet</Button>
{ActionSheet}
</>
);
}
Direct Component Usage
<ActionSheet
visible={isVisible}
onClose={() => setIsVisible(false)}
title='Choose an action'
message='Select one of the options below'
options={[
{
title: 'Share',
onPress: handleShare,
icon: <ShareIcon />,
},
{
title: 'Delete',
onPress: handleDelete,
destructive: true,
},
]}
/>
Examples
Default
import { ActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { View } from '@/components/ui/view';
import React, { useState } from 'react';
export function ActionSheetDemo() {
const [visible, setVisible] = useState(false);
const options = [
{
title: 'Edit',
onPress: () => console.log('Edit pressed'),
},
{
title: 'Share',
onPress: () => console.log('Share pressed'),
},
{
title: 'Delete',
onPress: () => console.log('Delete pressed'),
destructive: true,
},
];
return (
<View>
<Button onPress={() => setVisible(true)}>Show Action Sheet</Button>
<ActionSheet
visible={visible}
onClose={() => setVisible(false)}
title='Choose an action'
message='Select one of the options below'
options={options}
/>
</View>
);
}
With Icons
import { ActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { Download, Edit, Share, Trash2 } from 'lucide-react-native';
import React, { useState } from 'react';
export function ActionSheetIcons() {
const [visible, setVisible] = useState(false);
const options = [
{
title: 'Edit',
onPress: () => console.log('Edit pressed'),
icon: <Icon name={Edit} size={20} />,
},
{
title: 'Share',
onPress: () => console.log('Share pressed'),
icon: <Icon name={Share} size={20} />,
},
{
title: 'Download',
onPress: () => console.log('Download pressed'),
icon: <Icon name={Download} size={20} />,
},
{
title: 'Delete',
onPress: () => console.log('Delete pressed'),
destructive: true,
icon: <Icon name={Trash2} size={20} />,
},
];
return (
<>
<Button onPress={() => setVisible(true)}>
Show Action Sheet with Icons
</Button>
<ActionSheet
visible={visible}
onClose={() => setVisible(false)}
title='File Actions'
options={options}
/>
</>
);
}
Destructive Actions
import { ActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { AlertTriangle, Trash2 } from 'lucide-react-native';
import React, { useState } from 'react';
export function ActionSheetDestructive() {
const [visible, setVisible] = useState(false);
const options = [
{
title: 'Remove from Library',
onPress: () => console.log('Remove from library'),
destructive: true,
},
{
title: 'Delete Permanently',
onPress: () => console.log('Delete permanently'),
destructive: true,
icon: <Icon name={Trash2} size={20} />,
},
{
title: 'Report Content',
onPress: () => console.log('Report content'),
destructive: true,
icon: <Icon name={AlertTriangle} size={20} />,
},
];
return (
<>
<Button variant='destructive' onPress={() => setVisible(true)}>
Destructive Actions
</Button>
<ActionSheet
visible={visible}
onClose={() => setVisible(false)}
title='Are you sure?'
message='These actions cannot be undone'
options={options}
/>
</>
);
}
Disabled Options
import { ActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { Copy, Edit, Share, Trash2 } from 'lucide-react-native';
import React, { useState } from 'react';
export function ActionSheetDisabled() {
const [visible, setVisible] = useState(false);
const options = [
{
title: 'Edit',
onPress: () => console.log('Edit pressed'),
icon: <Icon name={Edit} size={20} />,
},
{
title: 'Copy',
onPress: () => console.log('Copy pressed'),
icon: <Icon name={Copy} size={20} />,
disabled: true,
},
{
title: 'Share',
onPress: () => console.log('Share pressed'),
icon: <Icon name={Share} size={20} />,
disabled: true,
},
{
title: 'Delete',
onPress: () => console.log('Delete pressed'),
destructive: true,
icon: <Icon name={Trash2} size={20} />,
},
];
return (
<>
<Button onPress={() => setVisible(true)}>
Show with Disabled Options
</Button>
<ActionSheet
visible={visible}
onClose={() => setVisible(false)}
title='Document Actions'
message='Some actions are not available'
options={options}
/>
</>
);
}
Custom Styling
import { ActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { Bookmark, Heart, Send, Star } from 'lucide-react-native';
import React, { useState } from 'react';
export function ActionSheetStyled() {
const [visible, setVisible] = useState(false);
const options = [
{
title: 'Add to Favorites',
onPress: () => console.log('Add to favorites'),
icon: <Icon name={Heart} size={20} color='#FF6B6B' />,
},
{
title: 'Rate this Item',
onPress: () => console.log('Rate item'),
icon: <Icon name={Star} size={20} color='#FFD93D' />,
},
{
title: 'Save for Later',
onPress: () => console.log('Save for later'),
icon: <Icon name={Bookmark} size={20} color='#4ECDC4' />,
},
{
title: 'Share with Friends',
onPress: () => console.log('Share with friends'),
icon: <Icon name={Send} size={20} color='#45B7D1' />,
},
];
return (
<>
<Button variant='secondary' onPress={() => setVisible(true)}>
Custom Styled Sheet
</Button>
<ActionSheet
visible={visible}
onClose={() => setVisible(false)}
title='✨ Quick Actions'
message='Choose how you want to interact with this item'
options={options}
cancelButtonTitle='Maybe Later'
style={{
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
}}
/>
</>
);
}
Long Options List
import { ActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import {
Archive,
Bookmark,
Copy,
Download,
Edit,
EyeOff,
Flag,
Heart,
Pin,
Send,
Share,
Star,
Trash2,
} from 'lucide-react-native';
import React, { useState } from 'react';
export function ActionSheetLong() {
const [visible, setVisible] = useState(false);
const options = [
{
title: 'Edit Document',
onPress: () => console.log('Edit'),
icon: <Icon name={Edit} size={20} />,
},
{
title: 'Share',
onPress: () => console.log('Share'),
icon: <Icon name={Share} size={20} />,
},
{
title: 'Download',
onPress: () => console.log('Download'),
icon: <Icon name={Download} size={20} />,
},
{
title: 'Copy Link',
onPress: () => console.log('Copy link'),
icon: <Icon name={Copy} size={20} />,
},
{
title: 'Archive',
onPress: () => console.log('Archive'),
icon: <Icon name={Archive} size={20} />,
},
{
title: 'Pin to Top',
onPress: () => console.log('Pin'),
icon: <Icon name={Pin} size={20} />,
},
{
title: 'Add to Favorites',
onPress: () => console.log('Favorite'),
icon: <Icon name={Heart} size={20} />,
},
{
title: 'Rate & Review',
onPress: () => console.log('Rate'),
icon: <Icon name={Star} size={20} />,
},
{
title: 'Bookmark',
onPress: () => console.log('Bookmark'),
icon: <Icon name={Bookmark} size={20} />,
},
{
title: 'Send Message',
onPress: () => console.log('Send message'),
icon: <Icon name={Send} size={20} />,
},
{
title: 'Hide from Feed',
onPress: () => console.log('Hide'),
icon: <Icon name={EyeOff} size={20} />,
},
{
title: 'Report Issue',
onPress: () => console.log('Report'),
icon: <Icon name={Flag} size={20} />,
},
{
title: 'Delete',
onPress: () => console.log('Delete'),
destructive: true,
icon: <Icon name={Trash2} size={20} />,
},
];
return (
<>
<Button onPress={() => setVisible(true)}>Show Long List</Button>
<ActionSheet
visible={visible}
onClose={() => setVisible(false)}
title='All Actions'
message='Scroll to see all available options'
options={options}
/>
</>
);
}
With Hook
import { useActionSheet } from '@/components/ui/action-sheet';
import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { View } from '@/components/ui/view';
import { Camera, FileText, Image, Mic } from 'lucide-react-native';
import React from 'react';
export function ActionSheetHook() {
const { show, ActionSheet } = useActionSheet();
const showMediaOptions = () => {
show({
title: 'Add Media',
message: 'Choose the type of media to add',
options: [
{
title: 'Take Photo',
onPress: () => console.log('Take photo'),
icon: <Icon name={Camera} size={20} />,
},
{
title: 'Choose from Gallery',
onPress: () => console.log('Choose from gallery'),
icon: <Icon name={Image} size={20} />,
},
{
title: 'Record Audio',
onPress: () => console.log('Record audio'),
icon: <Icon name={Mic} size={20} />,
},
{
title: 'Add Document',
onPress: () => console.log('Add document'),
icon: <Icon name={FileText} size={20} />,
},
],
});
};
const showConfirmation = () => {
show({
title: 'Confirm Action',
message: 'This action cannot be undone',
options: [
{
title: 'Yes, Continue',
onPress: () => console.log('Confirmed'),
destructive: true,
},
],
});
};
return (
<View style={{ gap: 12 }}>
<Button onPress={showMediaOptions}>Add Media</Button>
<Button variant='outline' onPress={showConfirmation}>
Show Confirmation
</Button>
{ActionSheet}
</View>
);
}
API Reference
ActionSheet
The main ActionSheet component.
Prop | Type | Default | Description |
---|---|---|---|
visible | boolean | - | Controls the visibility of the action sheet. |
onClose | () => void | - | Callback fired when the action sheet should close. |
title | string | - | Optional title displayed at the top. |
message | string | - | Optional message displayed below the title. |
options | ActionSheetOption[] | - | Array of options to display in the action sheet. |
cancelButtonTitle | string | 'Cancel' | Text for the cancel button. |
style | ViewStyle | - | Additional styles for the action sheet container. |
ActionSheetOption
Configuration for individual action sheet options.
Prop | Type | Default | Description |
---|---|---|---|
title | string | - | The text to display for this option. |
onPress | () => void | - | Callback fired when this option is pressed. |
destructive | boolean | false | Whether this option should use destructive styling. |
disabled | boolean | false | Whether this option should be disabled. |
icon | React.ReactNode | - | Optional icon to display next to the title. |
useActionSheet Hook
A convenient hook for managing action sheet state.
Returns
Property | Type | Description |
---|---|---|
show | (config: Omit<ActionSheetProps, 'visible' | 'onClose'>) => void | Function to show the action sheet. |
hide | () => void | Function to hide the action sheet. |
ActionSheet | React.ReactElement | The ActionSheet component to render. |
isVisible | boolean | Current visibility state. |
Platform Behavior
iOS
On iOS, the ActionSheet automatically uses the native ActionSheetIOS
API, providing the familiar iOS action sheet experience with proper integration into the system UI.
Android & Other Platforms
On Android and other platforms, a custom implementation is used that mimics the native behavior with smooth animations and proper theming support.
Accessibility
The ActionSheet component follows accessibility best practices:
- Proper focus management when opened/closed
- Screen reader announcements for destructive actions
- Keyboard navigation support where applicable
- Respects system accessibility settings
Animation
The ActionSheet includes smooth animations:
- Slide-up animation from bottom of screen
- Backdrop fade-in/out
- Spring-based animations for natural feel
- Respects reduced motion preferences
Theming
The ActionSheet automatically adapts to your app's theme:
- Uses theme colors for background, text, and borders
- Supports both light and dark modes
- Destructive actions use theme's destructive color
- Disabled states respect theme opacity values
On This Page
InstallationUsageBasic Usage with HookDirect Component UsageExamplesDefaultWith IconsDestructive ActionsDisabled OptionsCustom StylingLong Options ListWith HookAPI ReferenceActionSheetActionSheetOptionuseActionSheet HookReturnsPlatform BehavioriOSAndroid & Other PlatformsAccessibilityAnimationTheming