List with Swipe Actions
List rows that reveal buttons like Archive or Delete when you swipe them. Learn the anatomy, leading vs trailing actions, full swipe, Undo vs confirmation, the alternatives every swipe needs, and the state bugs testers find in these rows.
Swipe an email to the left in iPhone Mail: red Trash, orange Flag, grey More slide out from behind the row. Swipe a chat in WhatsApp: Archive. Swipe a saved card in a banking app: Remove. These rows look like a plain list until your finger moves, and then they become a little toolbar.
That hidden toolbar is where the bugs live. Which row is open? What happens when you scroll? Does “Archive” really archive? Can someone who can’t swipe still do the same thing? Let’s learn the component properly.
What is a list with swipe actions?
A list with swipe actions is a normal vertical list where each row hides extra actions that appear when you swipe the row sideways. Tapping the row still does the main thing (open the email, open the chat, open the product). Swiping is a shortcut for the secondary things you’d otherwise do from inside the item or from a menu.
You’ll find it in:
- Mail and messaging: Archive, Delete, Mark as read, Pin, Mute.
- Shopping: Remove from cart or wishlist, Move to “Save for later”.
- Banking and finance: Remove a saved payee or card, hide a transaction.
- To-do and notes: Complete, Delete, Flag.
Anatomy
Every row is a normal list item first. Learn its parts, because many bugs are “text overlaps chevron” or “secondary line missing” rather than anything to do with swiping.
iOS list rows: at rest, swiped left, swiped right
- 1
Leading content
An avatar, thumbnail, icon or checkbox. Helps people scan the list.
- 2
Primary text
The one thing that identifies the row: a name, a product, a subject. One line, truncated with an ellipsis.
- 3
Secondary text
Supporting detail: a preview, a status, an address. Usually one or two lines in a lighter color.
- 4
Trailing content
Metadata (time, price, badge) or a control (switch, checkbox).
- 5
Chevron
Means "tap opens a detail screen" on iOS. Android and web rows rarely show it.
- 6
Trailing actions
Revealed by swiping toward the leading edge (left in English). Usually Delete, Archive, More. Destructive goes outermost.
- 7
Leading action
Revealed by swiping the other way. Usually something positive and reversible: Mark as read, Pin, Add to cart.
Leading vs. trailing actions
The two sides have names that work in every language:
- Trailing actions sit at the trailing edge (the right in English) and appear when you swipe toward the leading edge (to the left). This is where destructive actions live: Delete, Archive, Remove.
- Leading actions sit at the leading edge (the left in English) and appear when you swipe to the right. They’re usually positive and reversible: Mark as read, Pin, Add to cart.
In right-to-left languages like Arabic and Hebrew (RTLRight-to-left (RTL)Languages like Arabic and Hebrew that read right to left; layouts and controls must be mirrored.Open in glossary →), everything mirrors: trailing actions appear on the left. A row that still reveals Delete on the right in Arabic is a localization bug.
Reveal buttons vs. full swipe
There are two ways a swipe can end:
| Style | What happens | Risk |
|---|---|---|
| Reveal | A short swipe snaps the row open and shows buttons. You tap one. | Low: two steps, you see what you’ll get |
| Full swipe | Keep swiping past a point and the outermost action runs on release | Higher: one movement, easy to do by accident |
| Swipe to dismiss | No buttons; the row slides away and the action runs (Gmail style) | Highest: must come with Undo |
iOS uses reveal + optional full swipe (iPhone Mail: a full swipe left trashes or archives). Android apps usually use swipe to dismiss with a colored background and an icon (Gmail archives). A good full swipe gives feedback at the point of no return: the outermost button stretches across the row and the phone gives a small hapticHaptic feedbackA short vibration that confirms an action without the user needing to look at the screen.Open in glossary → tick. If you let go before that point, nothing happens.
How it differs from similar patterns
Swipe actions are never the only way to do something. These are the patterns they’re usually paired with:
| Pattern | How it’s triggered | Good for |
|---|---|---|
| Swipe actions | Swiping one row | Fast, frequent actions on one item |
| Edit mode | An Edit or Select button, then checkboxes | Acting on many items at once |
| Long-press menu | Touch and hold a row | Discoverable list of all actions |
| Buttons in the detail view | Open the item, use its toolbar | The always-available, visible path |
Designs & variants
The same idea looks and behaves differently on each platform. Try each one with your finger or by dragging with a mouse.
Inbox
Reveal buttons + full swipe
iOSSwipe a little to reveal buttons, then tap one. Swipe all the way to trigger the outermost action (Trash). Only one row opens at a time; scrolling or tapping the row closes it.
Primary
Swipe to dismiss
AndroidGmail style: no buttons. The color and icon tell you what will happen; past about 40% of the width the email is archived. Tap an avatar to select instead, then use the toolbar.
Saved addresses
- Home12 Baker Street, London
- Office5 Canal Road, Leeds
- Mom88 Elm Avenue, York
Visible actions menu
WebOn the web, swipe is rare. Each row has a visible ⋮ menu that works with mouse, touch and keyboard. Deleting is permanent here, so it asks first.
Dev note
On iOS these are swipe actions (swipeActions in SwiftUI, UISwipeActionsConfiguration in UIKit). On Android you’ll hear swipe to dismiss (SwipeToDismissBox in Jetpack Compose, ItemTouchHelper for RecyclerView). On the web there is no standard; teams build it themselves or use a library.
When to use it
Swipe actions are a good choice when:
- People process many items, one after another: triaging an inbox, clearing notifications, checking off a shopping list.
- The actions are frequent and quick (one tap or one swipe), like Archive or Mark as read.
- The same actions are also available elsewhere: in the item’s detail screen, a long-press menu or an edit mode.
- The result is easy to undo, or the action is protected by Undo or a confirmation.
Good and bad uses
Quick, reversible actions
Archive a chat, mark an email as read, remove an item from a wishlist, with an Undo toast right after.
The only way to do something
Canceling a subscription or deleting a saved card only by swiping. People who don’t know the gesture (or can’t do it) are stuck. Put a visible button in the detail view too.
Two or three actions
Archive and Delete on the trailing side, Read on the leading side. Each button is at least as tall as the row and has a short label.
Five buttons crammed in
Delete, Archive, Flag, Move, Share, Mute all on one side. Labels truncate, buttons get narrower than a fingertip, and the row has to be swiped across the whole screen. Put the extras behind a More button.
Lists of separate items
A list of emails, chats, products, alarms: each row is one thing you can act on.
Rows that already move sideways
A row with a horizontal carousel or a slider inside, or a list inside a screen that itself swipes between tabs. The gestures fight each other. See Gestures.
How good swipe rows behave
These are the rules to test against. Most of them aren’t written in any requirement, but users expect them because the built-in apps behave this way.
Only one row is open at a time
Open the actions on one row, then start swiping another: the first row closes. Two open rows look broken and, worse, can confuse the code about which item an action belongs to.
An open row closes when you do something else
Scrolling the list, tapping the open row, tapping another row, pulling to refresh or leaving the screen should all close the open row. Tapping an open row should only close it, not also open the item.
The action happens to the right item
The button you tap must act on its own row, even after you’ve scrolled, after another row was deleted, or after new items arrived at the top. In long lists, rows are recycled (the same row view is reused for a different item as you scroll). If the “open” state is stored on the recycled view or by position instead of by item, it jumps to the wrong item. That’s a state persistenceState persistenceWhether the app remembers what the user did after navigating away, rotating, or restarting.Open in glossary → bug in disguise.
Dev note
UITableView, RecyclerView, LazyColumn and most web virtual lists.Labels tell the truth
“Archive” must archive (the item can be found in Archived), “Delete” must delete (maybe to a Trash folder), “Mute” must mute. Check the result after the action, not just that the row disappeared.
Destructive actions: Undo or confirmation
| Use… | When | Example |
|---|---|---|
| Undo in a toastToastA short, temporary message that appears briefly and disappears on its own, like 'Message sent'.Open in glossary → or snackbar | The action is common and easy to reverse | Archive a chat, delete an email to Trash |
| Confirmation (an action sheet or dialog) | The action is permanent or expensive to reverse | Delete a saved card, cancel a booking |
| Neither | Only when the action is harmless | Mark as read, Pin |
Don’t confirm everything: a dialog on every archive teaches people to tap Delete without reading. And Undo must really restore the item, in its original position, with its state (unread, pinned) intact.
Haptics and feedback
While swiping, the row should show what will happen: the color, icon and label of the action. On iOS a full swipe gives a light haptic tick when it passes the point of no return. Haptics should follow the system setting and can only be checked on a real deviceReal deviceA physical phone or tablet used for testing, as opposed to an emulator or simulator.Open in glossary →.
Large text, small screens and RTL
With the largest text size (Dynamic TypeDynamic TypeThe phone setting that lets users make text bigger or smaller across apps.Open in glossary → on iOS, Font size on Android), the row grows taller, text wraps or truncates inside its own area, and the action buttons grow with it. Text must never run underneath or on top of the buttons. In RTL languages, the sides swap.
Long lists stay smooth
A list of 2,000 transactions must scroll and swipe without stutter. Rows are usually created only when they come on screen (lazy loadingLazy loadingLoading images or content only when the user scrolls near them.Open in glossary →, infinite scrollInfinite scrollLoading more items automatically when the user reaches the bottom of a list.Open in glossary →). Test swiping right after scrolling fast, and on an older, slower phone.
Try it: swipe lab
This wishlist does everything right. Change the settings, then try to break it: open two rows, scroll with a row open, remove an item and undo it, switch to the largest text, and use Edit to remove items without any gesture. Watch the event log.
Wishlist
Full swipe
Text size
After Remove
Event log
- Drag a row left or right with your finger or mouse…
Try: open one row, then swipe another. Scroll while a row is open. Tab through the list with a keyboard: focusing an action reveals it.
Common bugs
| # | Bug | What you see | Typical severity |
|---|---|---|---|
| 1 | Several rows open | Two or more rows show their buttons at the same time | Low–Medium |
| 2 | Action hits the wrong item | Tap Delete on “Mom”, and “Emma” disappears | Critical |
| 3 | Row stays open | Buttons still showing after scrolling, opening the item or coming back | Low–Medium |
| 4 | Tap on an open row opens the item | Instead of closing, the row opens the detail screen | Low |
| 5 | Label lies | “Archive” deletes; “Mark as read” also mutes | High |
| 6 | State jumps to another row | After a delete, or after scrolling a long list, a different row appears open | Medium–High |
| 7 | No Undo / no confirmation | A permanent delete happens with one swipe | High |
| 8 | Layout breaks | Text runs over the buttons at large text sizes; labels truncate in German | Medium |
| 9 | Gesture-only | No edit mode, menu or detail button; screen reader users can’t reach the action | High (for affected users) |
| 10 | Not mirrored in RTL | In Arabic, Delete still appears on the right | Medium |
Find the bug
This chat app has swipe actions on every row and six bugs in the component. It has the right threshold and a direction lock, so this time the gesture isn’t the problem. Explore it like a tester:
- Open the actions on two chats. Then try the buttons.
- Leave a row open and scroll. Tap an open row.
- Archive a chat, then look for it. Compare with the Archive button inside a chat.
- Delete a chat and look at the row that moves up.
- Use the device panel: Larger text and VoiceOver.
🐞 Bug hunt: Chats
This demo has 6 hidden bugs. Explore it like a tester, then check your findings.
Chats
Device
Drag a chat left or right with your mouse or finger. Scroll with the wheel or by swiping up and down.
- 1
Hint: Open the actions on two different chats, then tap Archive on the second one.
- 2
Hint: Open a row, scroll the list, then tap the open row.
- 3
Hint: Swipe-archive a chat, then open the Archived folder at the top of the list.
- 4
Hint: Turn on Larger text, then swipe a chat to the left.
- 5
Hint: Turn on VoiceOver, tap a chat and listen for the actions.
- 6
Hint: Swipe a chat left, tap Delete, and look at the chat that moves up.
How to test it
Checklist
Swipe actions test checklist
0 of 14 checked
Example test cases
TC-SWL-001Opening a second row closes the first onepositivehigh
Preconditions
- Chat list has at least 5 chats
Steps
- Swipe the first chat left until its buttons show
- Swipe the third chat left
Expected result
The first chat closes as soon as the third one starts moving. Only the third chat shows its buttons.
TC-SWL-002Archive moves the chat to Archivedpositivehigh
Steps
- Swipe "Mom" left
- Tap Archive
- Wait until the snackbar disappears
- Open the Archived folder
Expected result
"Mom" is no longer in Chats, the Archived count increases by 1, and "Mom" is listed in Archived.
TC-SWL-003Undo restores a deleted chat in its original positionpositivehigh
Steps
- Note the position of the third chat
- Swipe it left and tap Delete
- Tap Undo within 4 seconds
Expected result
The chat is back in the third position, with the same unread count. No row is left open.
TC-SWL-004No row inherits the open state after a deleteedgehigh
Steps
- Swipe the second chat left
- Tap Delete
- Look at the chat that moved into the second position
Expected result
The new second chat is closed (no buttons visible).
TC-SWL-005Scrolling closes an open rowpositivemedium
Steps
- Swipe a chat left to reveal its buttons
- Scroll the list down and back up
Expected result
The row closes as soon as scrolling starts.
TC-SWL-006Tapping an open row only closes itnegativelow
Steps
- Swipe a chat left to reveal its buttons
- Tap the row content (not a button)
Expected result
The row closes. The chat does not open.
TC-SWL-007Swipe actions are available with VoiceOverpositivehigh
Preconditions
- VoiceOver is on
Steps
- Swipe right until a chat is focused
- Listen to the announcement
- Swipe down repeatedly
Expected result
VoiceOver says "Actions available"; swiping down offers Archive, Delete and Mark as read. Double tap runs the chosen action.
TC-SWL-008Row layout at the largest text sizeedgemedium
Preconditions
- iOS Settings › Accessibility › Display & Text Size › Larger Text at maximum
Steps
- Open Chats
- Swipe a chat left
Expected result
Name and preview truncate or wrap inside the row. Nothing overlaps the unread badge or the revealed buttons; button labels are readable.
TC-SWL-009Actions are mirrored in Arabicedgelow
Preconditions
- Device language set to Arabic
Steps
- Open Chats
- Swipe a chat to the right
Expected result
Archive and Delete appear on the left side (the trailing edge in RTL). Swiping left reveals the Read action.
Tip: click a test case to expand it.
Tools
- Accessibility Inspector (Xcode › Open Developer Tool) shows a row’s Custom Actions. If the list is empty, VoiceOver users can’t reach the swipe actions.
- Android Studio Layout Inspector and the Accessibility Scanner app show whether a row has accessibility actions; TalkBack’s Actions menu is the real-world check.
- Settings for stress: largest text size, a long language (German), an RTL language (Arabic), and Reduce Motion (the row should still open and close, just without the slide).
- Network log or proxy toolProxy toolA program that sits between the app and the server so you can watch and change network traffic.Open in glossary →: after Archive or Delete, check that one request goes to the server, for the right item ID. Then reopen the app to make sure the change was saved and not only hidden on screen.
Accessibility
Swiping is a path-based gesture, so it’s one of the hardest things to do for people with tremors, limited dexterity, or who can’t see the screen. Check these:
- Screen readers: with VoiceOver or TalkBackScreen readerSoftware that reads the screen aloud for blind and low-vision users, like VoiceOver or TalkBack.Open in glossary → on, a swipe moves focus, it never reaches the row. Every swipe action must be exposed as an accessibility action. On iOS, standard swipe actions do this automatically (“Actions available”, then swipe up or down to choose). TalkBack lists them in its Actions menu.
Dev note
Standard swipe actions are the ones inListandUITableView. Custom-built rows needaccessibilityCustomActions(UIKit) or.accessibilityAction(SwiftUI). On Android, Compose usescustomActionsin semantics; Views useViewCompat.addAccessibilityAction. - A visible alternative: WCAGWCAGThe Web Content Accessibility Guidelines, the main international standard for accessibility.Open in glossary → 2.5.1 Pointer Gestures (Level A) requires a single-pointer way without a path, such as a button in the detail view, a long-press menu or an Edit mode. Voice Control and Switch Control users rely on these.
- Clear labels: icon-only action buttons need text labels for assistive tech (“Archive”, not “button”).
- Announce the result: after Archive or Delete, the screen reader should hear “Chat archived” and focus should move to a sensible place (the next row), not jump to the top.
- Touch targetsTouch targetThe area of the screen that responds to a tap, which should be large enough for a finger.Open in glossary →: revealed buttons are at least 44×44 pt (iOS) / 48×48 dp (Android), and as tall as the row. On the web, WCAG 2.5.8 (AA) asks for at least 24×24 CSS px; 44×44 px (2.5.5, AAA) is the comfortable target.
- Keyboard (web): every action is reachable with Tab and Enter. Hover-only buttons must also show on focus. See Accessibility basics.
Mobile vs web
Dev note
.swipeActions (with allowsFullSwipe) and .onDelete, UIKit UISwipeActionsConfiguration (performsFirstActionWithFullSwipe is on by default). Edit mode: EditButton.- Leading and trailing actions, reveal buttons plus full swipe of the outermost action.
- Edit mode gives red delete circles and multi-select: the standard alternative.
- Standard rows expose swipe actions to VoiceOver for free; custom rows often don’t.
- No standard “reveal buttons” component in Material Design. Most apps use swipe to dismiss with one action per direction and a snackbar Undo.
Dev note
ComposeSwipeToDismissBox, RecyclerViewItemTouchHelper. - The common alternative is selection mode: long press or tap the avatar, then use the top app bar.
- Watch for the system Back gesture from the screen edges colliding with row swipes.
- Test TalkBack’s Actions menu and Switch Access.
- No native component: built by hand or with a library, so quality varies a lot.
- Check that vertical scrolling still works on swipeable rows.
Dev note
Swiping needs Pointer or Touch Events andtouch-action: pan-yso vertical scrolling still works. - Mobile browsers use edge swipes for Back / Forward, which can clash with row swipes.
- Always provide visible buttons or a menu for mouse, keyboard and assistive tech.
Check your understanding
Quick quiz
0/5 answered · 0 correct
1.In English, where do trailing swipe actions like Delete usually appear?
2.You delete the second chat, and the chat that moves into second place shows its buttons already open. What is the most likely cause?
3.Which is the best protection for deleting a saved bank card with a swipe?
4.VoiceOver is on. How should a user archive a chat from the list?
5.Which is NOT expected behavior for a good swipe row?
Key takeaways
- Swipe actions are shortcuts on list rows: trailing (swipe left) for destructive actions, leading (swipe right) for positive ones, mirrored in RTL.
- Know the three styles: reveal buttons, full swipe and swipe to dismiss, and the feedback each needs.
- Test state: only one row open, rows close on scroll and tap, actions hit the right item, nothing inherits an open state after a delete.
- Check that labels tell the truth and that destructive actions have Undo or confirmation.
- Every swipe action needs an alternative: edit mode, long-press menu or detail button, plus accessibility actions for VoiceOver and TalkBack.
Finished this page?Nice work, this page is complete!
Mark it as done to track your progress. It's saved in this browser, no account needed.
Its review cards are now in Bites ⚡