Add swipeable to a list so people
can swipe a row sideways on a touch screen to reach its actions. Each row's
actions button does the same for everyone else.
A row with actions holds a <button data-swipe-toggle> as
its trailing action, then a .swipe-actions group of buttons as its
last child. AutoInit() starts every .list.swipeable.
A touch swipe toward the row's inline start slides the row with the finger
and brings the actions in from the other edge. Released past half the
actions' width, or with a flick, the row stays open. A swipe only reveals
the actions; none of them runs until a person presses it. On a touch
screen, swipe a row below to the left; elsewhere, press its actions button.
- Build passed on main
- Invoice 2041 is ready
- Design review moved to Thursday
- New comment on the roadmap
- Your export finished
<ul class="list swipeable" aria-label="Inbox">
<li>
<span class="material-symbols" aria-hidden="true">mail</span>
Weekly report
<button type="button" class="icon-button" data-swipe-toggle aria-label="Actions for Weekly report">
<span class="material-symbols" aria-hidden="true">more_horiz</span>
</button>
<span class="swipe-actions">
<button type="button" class="icon-button" aria-label="Archive Weekly report">
<span class="material-symbols" aria-hidden="true">archive</span>
</button>
<button type="button" class="icon-button" aria-label="Delete Weekly report">
<span class="material-symbols" aria-hidden="true">delete</span>
</button>
</span>
</li>
</ul>
Without a swipe
Swiping needs a touch screen, so every row with actions needs its
<button data-swipe-toggle>. Keyboard, mouse and switch users
open and close the row with it, the script keeps its
aria-expanded in step, and a semantics rule flags a row without
one. Name the toggle and each action for the row they belong to.
The actions stay in the tab order and the accessibility tree while the row is closed, and focus on one opens its row, so tabbing reaches every action. A mouse drag never swipes, and neither does a drag that moves up or down first, which scrolls as usual.
Closing a row
One row in a list is open at a time. A tap or focus outside the open row closes it, as does a swipe the other way, or Escape inside it. Escape on an action, or pressing an action, closes the row and moves focus from the action to the toggle. The page handles what each action does. Under reduced motion the row still follows the finger but opens and closes without sliding. In a right-to-left page the actions sit at the left, and a swipe to the right reveals them.
Events
Opening or closing a row fires expressive:swipetoggle from the
list and runs the onToggle option, both with
{ row, open }.
document.addEventListener('expressive:swipetoggle', (event) => {
const { row, open } = event.detail;
console.log(row, open ? 'opened' : 'closed');
});
Options
| Name | Type | Default | Description |
|---|---|---|---|
onToggle |
Function | null |
Called when a row opens or closes, with { row, open }. |
Methods
const list = Expressive.SwipeActions.getInstance(document.querySelector('.list.swipeable'));
list.open(row); // opens a row of the list, closing the one that was open
list.close(); // closes the open row
list.destroy(); // removes listeners, closes the open row without an event
Tokens
Override these on the .list.swipeable.
| Token | Default |
|---|---|
--md-comp-swipe-actions-gap | 4px |
--md-comp-swipe-actions-motion | default spatial spring |
--md-comp-swipe-actions-motion-duration | the default spatial spring's duration |