expo-ui-swipe-to-dismiss-box
v1.0.1
Published
A swipe-to-dismiss component for Expo UI (Jetpack Compose) with reliable threshold control
Downloads
43
Maintainers
Readme
expo-ui-swipe-to-dismiss-box
A swipe-to-dismiss component for Expo UI (Jetpack Compose) with reliable threshold control.
This is a community-built extension that provides a SwipeToDismissBox component matching the Jetpack Compose SwipeToDismissBox API. It uses a custom gesture implementation instead of Material 3's SwipeToDismissBox to work around a bug where positionalThreshold is silently ignored.
Platform Support
Android only. This component uses Jetpack Compose and has no iOS equivalent.
Installation
npx expo install expo-ui-swipe-to-dismiss-box @expo/uiA native rebuild is required after installation:
npx expo run:androidUsage
import { Host, LazyColumn, ListItem, Box, Text } from '@expo/ui/jetpack-compose';
import { fillMaxSize, background, paddingAll } from '@expo/ui/jetpack-compose/modifiers';
import { SwipeToDismissBox } from 'expo-ui-swipe-to-dismiss-box';
function MyList() {
const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);
return (
<Host style={{ flex: 1 }}>
<LazyColumn>
{items.map((item, index) => (
<SwipeToDismissBox
key={item}
positionalThreshold={0.3}
enableDismissFromStartToEnd={false}
onEndToStart={() => setItems((prev) => prev.filter((_, i) => i !== index))}>
<SwipeToDismissBox.BackgroundContent>
<Box
contentAlignment="center"
modifiers={[fillMaxSize(), background('#EF5350'), paddingAll(16)]}>
<Text>Delete</Text>
</Box>
</SwipeToDismissBox.BackgroundContent>
<ListItem headlineContent={item} />
</SwipeToDismissBox>
))}
</LazyColumn>
</Host>
);
}API
SwipeToDismissBox
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| enableDismissFromStartToEnd | boolean | true | Allow swiping from start to end (left-to-right in LTR) |
| enableDismissFromEndToStart | boolean | true | Allow swiping from end to start (right-to-left in LTR) |
| gesturesEnabled | boolean | true | Whether swipe gestures are enabled |
| positionalThreshold | number | 0.5 | Fraction (0.0–1.0) of swipe distance required to trigger dismiss |
| onStartToEnd | () => void | — | Called when item is swiped start-to-end |
| onEndToStart | () => void | — | Called when item is swiped end-to-start |
| modifiers | ModifierConfig[] | — | Compose modifiers |
Sub-components (Slots)
SwipeToDismissBox.BackgroundContent— Fallback background shown in either directionSwipeToDismissBox.BackgroundStartToEnd— Background for start-to-end swipe (overridesBackgroundContent)SwipeToDismissBox.BackgroundEndToStart— Background for end-to-start swipe (overridesBackgroundContent)
Why a custom implementation?
Material 3's SwipeToDismissBox has a known bug where positionalThreshold is silently ignored (never forwarded to the underlying AnchoredDraggableState). This package uses lower-level Compose primitives (detectHorizontalDragGestures + Animatable) for reliable threshold control.
Related
- Original expo PR — Context and design rationale
- Expo UI Extending Guide — How this package is built
- Google Issue Tracker — The Material 3 bug
License
MIT
