svelte-swipeout
Version:
iOS-style swipeable list component for Svelte 5 with delete animations and mobile-optimized touch handling
303 lines (233 loc) • 8.42 kB
Markdown
# svelte-swipeout
A powerful and flexible swipeable list component for Svelte 5 applications with iOS-style swipe actions, delete animations, and mobile-optimized touch handling.
## Installation
```bash
npm install svelte-swipeout
```
or
```bash
pnpm add svelte-swipeout
```
or
```bash
yarn add svelte-swipeout
```
## Features
- 🎯 **iOS-style swipe actions** - Smooth, native-feeling swipe gestures
- 📱 **Mobile-optimized** - Touch-friendly with proper scroll handling
- 🎨 **Customizable actions** - Left and right swipe actions with custom styling
- 💥 **Overswipe support** - Trigger actions by swiping past threshold
- 🗑️ **Delete animations** - Multiple delete animation styles (fade, collapse, slide, scale)
- ⚡ **Performant** - Hardware-accelerated animations using CSS transforms
- 🎭 **Svelte 5 ready** - Built with Svelte 5 runes and modern features
## Usage
Here is a simple example of how to use the `svelte-swipeout` components:
```svelte
<script>
import {
Swipeout,
SwipeoutItem,
SwipeoutContent,
SwipeoutActionsLeft,
SwipeoutActionsRight,
SwipeoutAction,
} from 'svelte-swipeout';
</script>
<Swipeout>
<SwipeoutItem>
<SwipeoutContent>
<div class="item">Swipe me</div>
</SwipeoutContent>
<SwipeoutActionsRight>
<SwipeoutAction onclick={() => console.log('Delete clicked')}>
Delete
</SwipeoutAction>
</SwipeoutActionsRight>
</SwipeoutItem>
</Swipeout>
```
## Examples
### Simple Swipe
This example shows a simple swipe with left and right actions.
```svelte
<Swipeout>
<SwipeoutItem>
<SwipeoutContent>
<div class="item">Swipe me</div>
</SwipeoutContent>
<SwipeoutActionsLeft>
<SwipeoutAction on:click={() => console.log('Archive clicked')}>
Archive
</SwipeoutAction>
</SwipeoutActionsLeft>
<SwipeoutActionsRight>
<SwipeoutAction onclick={() => console.log('Delete clicked')}>
Delete
</SwipeoutAction>
</SwipeoutActionsRight>
</SwipeoutItem>
</Swipeout>
```
### Delete with Animation
This example shows how to use the delete functionality with animations. The component supports multiple delete animation styles.
```svelte
<script>
let items = $state([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' }
]);
function handleDelete(id) {
items = items.filter(item => item.id !== id);
}
</script>
<!-- Default fade animation -->
<Swipeout>
{#each items as item (item.id)}
<SwipeoutItem delete onDelete={() => handleDelete(item.id)}>
<SwipeoutContent>
<div class="item">{item.name}</div>
</SwipeoutContent>
<SwipeoutActionsRight>
<SwipeoutAction
overSwipe
class="bg-red-500"
data-delete="true"
>
Delete
</SwipeoutAction>
</SwipeoutActionsRight>
</SwipeoutItem>
{/each}
</Swipeout>
<!-- With collapse animation -->
<Swipeout class="swipeout-delete-collapse">
<!-- items here -->
</Swipeout>
<!-- With slide animation -->
<Swipeout class="swipeout-delete-slide">
<!-- items here -->
</Swipeout>
<!-- With scale animation -->
<Swipeout class="swipeout-delete-scale">
<!-- items here -->
</Swipeout>
```
### Overswipe Actions
Overswipe actions are triggered when the user swipes past a certain threshold. Perfect for destructive actions like delete.
```svelte
<Swipeout>
<SwipeoutItem>
<SwipeoutContent>
<div class="item">Swipe me far to trigger overswipe</div>
</SwipeoutContent>
<SwipeoutActionsLeft>
<SwipeoutAction overSwipe class="bg-green-500">
Reply
</SwipeoutAction>
</SwipeoutActionsLeft>
<SwipeoutActionsRight>
<SwipeoutAction overSwipe class="bg-red-500">
Delete
</SwipeoutAction>
</SwipeoutActionsRight>
</SwipeoutItem>
</Swipeout>
```
### Programmatic Control
You can programmatically close swipeouts using the exported functions:
```svelte
<script>
import { closeSwipeout, closeAll } from 'svelte-swipeout';
// Close a specific swipeout element
function handleClose(element) {
closeSwipeout(element);
}
// Close all open swipeouts
function handleCloseAll() {
closeAll();
}
</script>
```
### Custom Styling
You can customize the colors and styles of the components using CSS variables.
```css
:root {
--swipeout-delete-button-bg-color: #ff3b30;
--swipeout-button-text-color: #fff;
--swipeout-button-padding-vertical: 0;
--swipeout-button-padding-horizontal: 30px;
--swipeout-button-font-size: inherit;
--swipeout-button-font-weight: inherit;
}
```
You can also use the `class` prop to add custom classes to the components.
```svelte
<SwipeoutAction class="my-custom-class">
Delete
</SwipeoutAction>
```
## API
### Swipeout
The root component for the swipeout list.
| Prop | Type | Default | Description |
| -------- | -------- | ------- | --------------------- |
| `class` | `string` | `''` | Custom class for the component. |
### SwipeoutItem
A single item in the swipeout list. Handles all swipe interactions and animations.
| Prop | Type | Default | Description |
| -------- | -------- | ------- | --------------------- |
| `class` | `string` | `''` | Custom class for the component. |
| `delete` | `boolean` | `false` | Enable delete functionality with animations. |
| `onDelete` | `function` | `undefined` | Callback function when item is deleted (only used when `delete` is true). |
**Events:**
- `swipeout:open` - Fired when swipeout starts opening
- `swipeout:opened` - Fired when swipeout is fully opened
- `swipeout:close` - Fired when swipeout starts closing
- `swipeout:closed` - Fired when swipeout is fully closed
- `swipeout:delete` - Fired when delete is triggered
- `swipeout:deleted` - Fired after delete animation completes
### SwipeoutContent
The content of the swipeout item.
| Prop | Type | Default | Description |
| -------- | -------- | ------- | --------------------- |
| `class` | `string` | `''` | Custom class for the component. |
### SwipeoutActionsLeft
A container for the left swipeout actions.
| Prop | Type | Default | Description |
| -------- | -------- | ------- | --------------------- |
| `class` | `string` | `''` | Custom class for the component. |
### SwipeoutActionsRight
A container for the right swipeout actions.
| Prop | Type | Default | Description |
| -------- | -------- | ------- | --------------------- |
| `class` | `string` | `''` | Custom class for the component. |
### SwipeoutAction
A single action button in the swipeout actions.
| Prop | Type | Default | Description |
| ----------- | ---------- | ------- | --------------------------------------------------------------------------- |
| `class` | `string` | `''` | Custom class for the component. |
| `overSwipe` | `boolean` | `false` | If `true`, the action will be triggered when the user swipes past a certain threshold. |
| `onclick` | `function` | `() => {}` | A function to be called when the action is clicked. |
| `data-delete` | `string` | `undefined` | Set to `"true"` to mark this as a delete action (used with SwipeoutItem's delete prop). |
## Mobile Support
The component is fully optimized for mobile devices with:
- **Touch-action CSS** - Prevents scroll interference during swipes
- **Intelligent scroll detection** - Differentiates between vertical scrolling and horizontal swiping
- **Proper event handling** - Uses pointer events for unified touch/mouse support
- **Momentum scrolling** - Maintains smooth iOS-style scrolling when not swiping
- **One-at-a-time** - Only one swipeout can be open at a time for better UX
## Delete Animations
The component supports multiple delete animation styles that can be applied by adding a class to the `Swipeout` container:
- **Default** - Simple fade out
- **`swipeout-delete-collapse`** - Fade out with height collapse
- **`swipeout-delete-slide`** - Slide left and collapse
- **`swipeout-delete-scale`** - Scale down and collapse
## Browser Support
- Modern browsers with ES6+ support
- iOS Safari 12+
- Chrome 80+
- Firefox 75+
- Edge 80+
## License
MIT