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.
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
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.
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.
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.
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.
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
| Prop | Data Type | Default Value | Description |
|---|---|---|---|
| Extends | -- | -- | -- |
OverlayContainerProps
| Prop | Data Type | Default Value | Description |
|---|---|---|---|
| Extends | -- | -- | -- |
| node | OverlayNode | -- | Node properties used to render the overlay content and control its behavior. |
| stackIndex | number | -- | The index of the overlay in the stack, used to calculate zIndex |