FocusScope
A boundary for keyboard focus, to trap it, start it and restore it.
FocusScope groups its children for keyboard focus. It adds no node, so
layout is as if it were not there.
import { FocusScope, Pressable, Text, TextInput, View } from '@soundor/react';
import { useState } from 'react';
function Button({ label, onPress }: { label: string; onPress: () => void }) {
return (
<Pressable
onPress={onPress}
style={({ focused }) => ({
padding: 8,
borderRadius: 6,
borderWidth: 2,
borderColor: focused ? '#8fb3ff' : 'transparent',
backgroundColor: '#3a7bfd',
})}
>
<Text style={{ color: 'white' }}>{label}</Text>
</Pressable>
);
}
// Click into the panel, then press Tab: focus cycles inside it while
// trapped, starts in it (autoFocus), and goes back where it was when the
// panel closes (restoreFocus).
export default function TrappedPanel() {
const [open, setOpen] = useState(false);
return (
<View style={{ width: 300, gap: 10 }}>
<Button
label={open ? 'Close panel' : 'Open panel'}
onPress={() => setOpen(!open)}
/>
{open && (
<FocusScope trapped autoFocus restoreFocus>
<View
style={{
gap: 8,
padding: 10,
borderRadius: 8,
backgroundColor: '#24262c',
}}
>
<TextInput
accessibilityLabel="Preset name"
placeholder="Preset name"
style={{
padding: 6,
borderRadius: 6,
backgroundColor: '#17181c',
color: '#e6e7ea',
}}
/>
<View style={{ flexDirection: 'row', gap: 8 }}>
<Button label="Save" onPress={() => setOpen(false)} />
<Button label="Cancel" onPress={() => setOpen(false)} />
</View>
</View>
</FocusScope>
)}
</View>
);
}focus-scope.tsxSourcetrapped: Tab and Shift+Tab cycle through the scope's focusable nodes, wrapping at the ends, and focus moved outside comes back. The innermost trapping scope wins.autoFocus: on mount, focuses the first focusable node, unless focus is already inside.restoreFocus: on unmount, gives focus back to the node that had it on mount, if that node is still there and focusable.
All three are false by default. Membership follows React, not the node
tree: what the scope's children render belongs to it wherever it shows,
through a Portal too. A
Modal is a trapped scope with autoFocus and
restoreFocus.
Props
Prop
Type