78 lines
1.8 KiB
Markdown
78 lines
1.8 KiB
Markdown
---
|
|
title: Use Native Modals Over JS-Based Bottom Sheets
|
|
impact: HIGH
|
|
impactDescription: native performance, gestures, accessibility
|
|
tags: modals, bottom-sheet, native, react-navigation
|
|
---
|
|
|
|
## Use Native Modals Over JS-Based Bottom Sheets
|
|
|
|
Use native `<Modal>` with `presentationStyle="formSheet"` or React Navigation
|
|
v7's native form sheet instead of JS-based bottom sheet libraries. Native modals
|
|
have built-in gestures, accessibility, and better performance. Rely on native UI
|
|
for low-level primitives.
|
|
|
|
**Incorrect (JS-based bottom sheet):**
|
|
|
|
```tsx
|
|
import BottomSheet from "custom-js-bottom-sheet";
|
|
|
|
function MyScreen() {
|
|
const sheetRef = useRef<BottomSheet>(null);
|
|
|
|
return (
|
|
<View style={{ flex: 1 }}>
|
|
<Button onPress={() => sheetRef.current?.expand()} title="Open" />
|
|
<BottomSheet ref={sheetRef} snapPoints={["50%", "90%"]}>
|
|
<View>
|
|
<Text>Sheet content</Text>
|
|
</View>
|
|
</BottomSheet>
|
|
</View>
|
|
);
|
|
}
|
|
```
|
|
|
|
**Correct (native Modal with formSheet):**
|
|
|
|
```tsx
|
|
import { Modal, View, Text, Button } from "react-native";
|
|
|
|
function MyScreen() {
|
|
const [visible, setVisible] = useState(false);
|
|
|
|
return (
|
|
<View style={{ flex: 1 }}>
|
|
<Button onPress={() => setVisible(true)} title="Open" />
|
|
<Modal
|
|
visible={visible}
|
|
presentationStyle="formSheet"
|
|
animationType="slide"
|
|
onRequestClose={() => setVisible(false)}
|
|
>
|
|
<View>
|
|
<Text>Sheet content</Text>
|
|
</View>
|
|
</Modal>
|
|
</View>
|
|
);
|
|
}
|
|
```
|
|
|
|
**Correct (React Navigation v7 native form sheet):**
|
|
|
|
```tsx
|
|
// In your navigator
|
|
<Stack.Screen
|
|
name="Details"
|
|
component={DetailsScreen}
|
|
options={{
|
|
presentation: "formSheet",
|
|
sheetAllowedDetents: "fitToContents",
|
|
}}
|
|
/>
|
|
```
|
|
|
|
Native modals provide swipe-to-dismiss, proper keyboard avoidance, and
|
|
accessibility out of the box.
|