Skip to main content

Overlay

The Overlay component is a foundational system that renders content at the app root level. It provides a flexible way to display content above the normal view hierarchy with full control over positioning, backdrop, and dismissal behavior.

It provides:

  • Root-level content rendering
  • Flexible positioning (top, left, right, bottom)
  • Backdrop with customizable behavior (interactive, block, dismiss)
  • Auto-hide with configurable duration
  • Imperative API for show, update, and dismiss operations
  • Support for multiple overlay types (popover, modal, etc.)

Usage

The useOverlay hook provides methods to show overlays with custom content and positioning. This example shows a basic overlay with backdrop that can be dismissed by tapping outside.

Show Overlay
function OverlayUsage() {
const {show} = useOverlay()

const overlayContent = useMemo(
() => (
<Surface style={{padding: 16, borderRadius: 8, backgroundColor: 'gray'}}>
<Text>I am Overlay Content</Text>
</Surface>
),
[],
)

return (
<Button
onPress={() => {
show({
type: 'popover',
content: overlayContent,
top: 250,
left: 150,
withBackdrop: true,
backdropBehavior: 'dismiss',
dismissOnBackPress: true,
backdropStyle: {backgroundColor: 'rgba(0,0,0,0.25)'},
})
}}>
Show Overlay
</Button>
)
}

Backdrop Behavior

Control how the backdrop behaves with three options:

  • interactive: Allows interaction with background content while overlay is visible
  • block: Prevents interaction with background but doesn't dismiss on tap
  • dismiss: Dismisses the overlay when backdrop is tapped

interactive
block
dismiss
Show Overlay
function OverlayBackdropBehavior() {
const {show, dismiss} = useOverlay()
const overlayId = useRef('')
const [backdropBehavior, setBackdropBehavior] = useState<
'interactive' | 'block' | 'dismiss'
>('interactive')

const overlayContent = useMemo(
() => (
<Surface style={{padding: 16, borderRadius: 8, backgroundColor: 'gray'}}>
<Text>I am Overlay Content</Text>
<Button onPress={() => dismiss(overlayId.current)}>Close</Button>
</Surface>
),
[dismiss],
)

return (
<>
<SegmentedButton
data={[{title: 'interactive'}, {title: 'block'}, {title: 'dismiss'}]}
onPress={(value, i) => {
setBackdropBehavior(value as 'interactive' | 'block' | 'dismiss')
}}
/>
<Button
onPress={() => {
overlayId.current = show({
type: 'popover',
content: overlayContent,
top: 250,
left: 150,
withBackdrop: true,
backdropBehavior,
})
}}>
Show Overlay
</Button>
</>
)
}

Auto Hide Overlay

Set a duration to automatically dismiss the overlay after a specified time. This is useful for temporary notifications or tooltips.

Show Auto Hide Overlay
function OverlayDuration() {
const {show} = useOverlay()

const overlayContent = useMemo(
() => (
<Surface style={{padding: 16, borderRadius: 8, backgroundColor: 'gray'}}>
<Text>I am Overlay Content</Text>
</Surface>
),
[],
)

return (
<Button
onPress={() => {
show({
type: 'popover',
content: overlayContent,
top: 250,
left: 150,
withBackdrop: true,
backdropBehavior: 'dismiss',
duration: 2000,
})
}}>
Show Auto Hide Overlay
</Button>
)
}

Update

Dynamically update overlay properties after it's shown. This is useful for repositioning overlays or updating their content based on user interactions.

Show Overlay
Update Overlay
Dismiss
function OverlayUpdate() {
const {show, update, dismiss} = useOverlay()
const overlayId = useRef('')

const overlayContent = useMemo(
() => (
<Surface style={{padding: 16, borderRadius: 8, backgroundColor: 'gray'}}>
<Text>I am Overlay Content</Text>
</Surface>
),
[],
)

return (
<View>
<Button
onPress={() => {
overlayId.current = show({
type: 'popover',
content: overlayContent,
top: 300,
left: 100,
withBackdrop: true,
backdropBehavior: 'interactive',
})
}}>
Show Overlay
</Button>
<Button
onPress={() => {
update(overlayId.current, {
top: 100,
left: 50,
})
}}>
Update Overlay
</Button>
<Button onPress={() => dismiss(overlayId.current)}>Dismiss</Button>
</View>
)
}

Random Overlay Positions

Demonstrates creating overlays at random positions with automatic updates. Shows the flexibility of the overlay system for dynamic positioning.

Auto Create Overlay Every 2 Seconds
Disable Background Interaction
Show Overlay
Update Overlay
Dismiss All
function OverlayRandom() {
// using scope to automatically dismiss overlays on unmount
const scopeId = useOverlayScope()
const {show, update, dismissAll} = useOverlay()

const [autoCreate, setAutoCreate] = useState(false)
const [disableBackgroundInteraction, setDisableBackgroundInteraction] =
useState(false)

const {width: screenWidth, height: screenHeight} = useWindowDimensions()

const overlayId = useRef('')
const intervalIdRef = useRef<ReturnType<typeof setInterval> | undefined>(
undefined,
)

const topRandom = useCallback(
() => (Math.random() * screenHeight) / 2,
[screenHeight],
)
const leftRandom = useCallback(
() => (Math.random() * screenWidth) / 2,
[screenWidth],
)

const overlayContent = useMemo(
() => (
<Surface style={{padding: 16, borderRadius: 8, backgroundColor: 'gray'}}>
<Text>I am Overlay Content</Text>
</Surface>
),
[],
)

const createOverlay = useCallback(() => {
overlayId.current = show({
type: 'popover',
scope: scopeId,
content: overlayContent,
top: topRandom(),
left: leftRandom(),
withBackdrop: true,
backdropBehavior: disableBackgroundInteraction
? 'dismiss'
: 'interactive',
dismissOnBackPress: true,
})
}, [
show,
scopeId,
overlayContent,
topRandom,
leftRandom,
disableBackgroundInteraction,
])

useEffect(() => {
if (!autoCreate) {
clearInterval(intervalIdRef.current)
return undefined
}
intervalIdRef.current = setInterval(() => {
createOverlay()
}, 2000)

return () => clearInterval(intervalIdRef.current)
}, [autoCreate, createOverlay])

return (
<View>
<Checkbox
label="Auto Create Overlay Every 2 Seconds"
value={autoCreate}
onValueChange={setAutoCreate}
/>
<Checkbox
label="Disable Background Interaction"
value={disableBackgroundInteraction}
onValueChange={setDisableBackgroundInteraction}
/>
<Spacer />
<Button onPress={createOverlay}>Show Overlay</Button>
<Button
onPress={() => {
update(overlayId.current, {
top: topRandom(),
left: leftRandom(),
})
}}>
Update Overlay
</Button>
<Button onPress={dismissAll}>Dismiss All</Button>
</View>
)
}

Imperative API

Use the imperative API to programmatically control overlays. This provides full control over showing, updating, and dismissing overlays from any component.

Show Overlay
function OverlayImperativeAPI() {
const overlayContent = useMemo(
() => (
<Surface style={{padding: 16, borderRadius: 8, backgroundColor: 'teal'}}>
<Text>I am shown from the Overlay Imperative API</Text>
<Button onPress={() => Overlay.dismissLast()}>Close</Button>
</Surface>
),
[],
)

return (
<Button
onPress={() => {
Overlay.show({
type: 'popover',
content: overlayContent,
top: 550,
left: 10,
withBackdrop: true,
backdropBehavior: 'dismiss',
dismissOnBackPress: true,
backdropStyle: {backgroundColor: 'rgba(0,0,0,0.25)'},
})
}}>
Show Overlay
</Button>
)
}

Props

BaseOverlayNode

PropData TypeDefault ValueDescription
Extends------

OverlayContainerProps

PropData TypeDefault ValueDescription
Extends------
nodeOverlayNode--Node properties used to render the overlay content and control its behavior.
stackIndexnumber--The index of the overlay in the stack, used to calculate zIndex