Modal
A layer over the whole view that takes its input until it closes.
Modal is a layer over the whole view that takes its input until it
closes. It is not a window: it is drawn in the plugin's one view, so it
works the same in any host, and in the browser.
import { Modal, Pressable, Text, View } from '@soundor/react';
import { useState } from 'react';
function Button({ label, onPress }: { label: string; onPress: () => void }) {
return (
<Pressable
onPress={onPress}
style={({ pressed }) => ({
paddingVertical: 8,
paddingHorizontal: 14,
borderRadius: 6,
backgroundColor: pressed ? '#2a5fd0' : '#3a7bfd',
})}
>
<Text style={{ color: 'white' }}>{label}</Text>
</Pressable>
);
}
// A modal takes the view's input and keyboard focus until it closes:
// Escape and a press on the backdrop ask it to.
export default function ConfirmDiscard() {
const [confirming, setConfirming] = useState(false);
const [discarded, setDiscarded] = useState(0);
return (
<View style={{ alignItems: 'center', gap: 12 }}>
<Button label="Discard changes…" onPress={() => setConfirming(true)} />
<Text style={{ color: '#8b8f98' }}>Discarded {discarded} times</Text>
<Modal
visible={confirming}
onRequestClose={() => setConfirming(false)}
dismissOnBackdropPress
accessibilityLabel="Discard changes"
backdropStyle={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
>
<View
style={{
margin: 'auto',
gap: 12,
padding: 16,
borderRadius: 10,
backgroundColor: '#24262c',
}}
>
<Text style={{ color: '#e6e7ea', fontSize: 16 }}>
Discard changes?
</Text>
<View style={{ flexDirection: 'row', gap: 8 }}>
<Button label="Cancel" onPress={() => setConfirming(false)} />
<Button
label="Discard"
onPress={() => {
setDiscarded((count) => count + 1);
setConfirming(false);
}}
/>
</View>
</View>
</Modal>
</View>
);
}modal.tsxSourceIt is a Portal plus:
- A backdrop over the whole view that blocks the pointer from everything
below, transparent unless
backdropStylesays otherwise. Its children fill the view above it and stay interactive: place a dialog withmargin: 'auto', say. - A trapped
FocusScopewithautoFocusandrestoreFocus: focus goes to its first focusable child on open, Tab stays inside, and focus returns on close. - Close requests: Escape, and with
dismissOnBackdropPressa press on the backdrop itself (not its content), callonRequestClose. The modal stays untilvisibleisfalse: the caller decides.
Modals stack like portals: a modal opened from a modal is above it and owns
focus until it closes, and a <Portal> opened from a modal (a dropdown, a
tooltip) shows above that modal and belongs to its focus trap.
To assistive technology a modal is a modal dialog, named by
accessibilityLabel. While it shows, everything else is hidden from it,
except the portals opened from inside it; a modal opened from it takes
over until it closes. With onRequestClose it offers escape (VoiceOver's
scrub), which asks it to close as Escape does.
Props
Prop
Type