Skip to content

Sheet types (variants) ​

Set variant on present() or NativeSheet to choose the surface. Each variant has its own defaults, and you can override any of them.

tsx
sheet.present({id: 'menu', variant: 'action', content: <ActionList />});

Native status

These placements are all drawn on the web. On iOS and Android every variant is currently presented as a bottom sheet; the variant's behaviour defaults (drag, backdrop, auto-dismiss, back button) still apply. See Platform support.

Bottom sheets ​

bottomSheet
action
share
picker
filter
VariantDragBackdropKeyboardNested scrollUse for
bottomSheet (default)✅✅✅✅Any panel from the bottom
action✅✅✅—Lists of actions
share✅✅✅—Share targets
picker✅✅—✅Date, option or wheel pickers
filter✅✅✅✅Filter and sort panels

All are modal, slide from the bottom and close with the back button.

Modals ​

center
fullScreen
alert
popup
side
top
floating
VariantPlacementDragBackdropBehaviourNotes
centercenter—✅modal
fullScreenfull screen——modal
alertcenter—✅modalNo keyboard or nested scroll. See presentAlert
popupfloating——non-modalScreen beneath stays usable
sideright (or left)—✅modalSet side: 'left'
toptop✅✅modal
floatingfloating——modal16 pt margin by default

NativeModal is a shortcut for these.

Overlays ​

toast
snackbar
inAppNotification
tooltip
popover
contextMenu
dropdown
coachmark
spotlight
loadingOverlay
fullScreenViewer
VariantPlacementBackdropBehaviourAuto-dismissNeeds anchor
toastbottom—non-modal3 s—
snackbarbottom—non-modal4 s—
inAppNotificationtop—non-modal5 s—
tooltipanchored✅non-modal—✅
popoveranchored✅non-modal—✅
contextMenuanchored✅non-modal—✅
dropdownanchored✅non-modal—✅
coachmarkanchored✅non-modal—✅
spotlightanchored✅non-modal—✅
loadingOverlayfull screen✅modal——
fullScreenViewerfull screen✅modal, draggable——

Backdrop on non-modal overlays

For non-modal and persistent behaviour the backdrop defaults to off, even when the table shows ✅. The ✅ applies if you set behavior: 'modal'. You can always pass enableBackdrop yourself.

loadingOverlay ignores the back button by default (hardwareBackDismiss: false).

Anchored overlays ​

Tooltips, popovers, context menus, dropdowns, coachmarks and spotlights need an anchor: the screen rectangle of the view they point at. Without it present() returns missing-anchor.

tsx
import {useRef} from 'react';
import {Pressable, Text, View} from 'react-native';

function MoreButton() {
  const sheet = useNativeSheet();
  const ref = useRef<View>(null);

  const open = () =>
    ref.current?.measureInWindow((x, y, width, height) => {
      sheet.present({
        id: 'more-menu',
        variant: 'popover',
        anchor: {x, y, width, height},
        content: <MoreMenu />,
      });
    });

  return (
    <Pressable ref={ref} onPress={open}>
      <Text>More</Text>
    </Pressable>
  );
}

On the web the surface is placed 8 px below the anchor, aligned to its left edge.

Overriding defaults ​

Any variant default can be changed per sheet:

tsx
sheet.present({
  id: 'new-message',
  variant: 'inAppNotification',
  autoDismissMs: 8000,      // longer than the 5 s default
  enableDrag: true,         // let the user swipe it away
  content: <MessageBanner />,
});

Auto-dismiss applies to every behaviour, including persistent: an auto-dismiss timer closes the sheet by id. Omit autoDismissMs on a variant without a default to keep a sheet open.

The defaults table is exported as VARIANTS if you want to read it in code:

ts
import {VARIANTS} from 'react-native-universal-sheet';
VARIANTS.toast.defaultAutoDismissMs; // 3000

Released under the MIT License.