Skip to content
Bugwise
Menu
UI Components

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.

35 min Content & layout iOS · Android · Web Also called: Swipe to delete, Swipe actions, Swipeable list item

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. 1

    Leading content

    An avatar, thumbnail, icon or checkbox. Helps people scan the list.

  2. 2

    Primary text

    The one thing that identifies the row: a name, a product, a subject. One line, truncated with an ellipsis.

  3. 3

    Secondary text

    Supporting detail: a preview, a status, an address. Usually one or two lines in a lighter color.

  4. 4

    Trailing content

    Metadata (time, price, badge) or a control (switch, checkbox).

  5. 5

    Chevron

    Means "tap opens a detail screen" on iOS. Android and web rows rarely show it.

  6. 6

    Trailing actions

    Revealed by swiping toward the leading edge (left in English). Usually Delete, Archive, More. Destructive goes outermost.

  7. 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:

StyleWhat happensRisk
RevealA short swipe snaps the row open and shows buttons. You tap one.Low: two steps, you see what you’ll get
Full swipeKeep swiping past a point and the outermost action runs on releaseHigher: one movement, easy to do by accident
Swipe to dismissNo 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:

PatternHow it’s triggeredGood for
Swipe actionsSwiping one rowFast, frequent actions on one item
Edit modeAn Edit or Select button, then checkboxesActing on many items at once
Long-press menuTouch and hold a rowDiscoverable list of all actions
Buttons in the detail viewOpen the item, use its toolbarThe 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

FreshCart9:38Your groceries are on the way
Northwind Bank8:47Your statement is ready
SkyTrail Airlines8:02Check-in is open
PulseFitYesterday5-day streak, nice!
StayWell HotelsSunBooking confirmed

Reveal buttons + full swipe

iOS

Swipe 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.

Leading + trailingFull swipeUndo toast
Search in mail

Primary

Swipe to dismiss

Android

Gmail 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.

One actionSnackbar UndoSelection mode
shop.example.com

Saved addresses

  • Home12 Baker Street, London
  • Office5 Canal Road, Leeds
  • Mom88 Elm Avenue, York

Visible actions menu

Web

On 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.

No gesture neededKeyboardConfirmation
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
Rows are recycled in 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…WhenExample
Undo in a toastToastA short, temporary message that appears briefly and disappears on its own, like 'Message sent'.Open in glossary → or snackbarThe action is common and easy to reverseArchive a chat, delete an email to Trash
Confirmation (an action sheet or dialog)The action is permanent or expensive to reverseDelete a saved card, cancel a booking
NeitherOnly when the action is harmlessMark 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.

9:41

Wishlist

Noise-canceling headphonesBack in stock€199
Trail runner 2Size 42 · Blue€89
Pour-over coffee setPrice dropped 15%€34
Linen shirtOnly 2 left€49
Smart watch S3Ships in 3 days€249
Desk lampWarm white€39

Full swipe

Text size

After Remove

Haptic: waiting for a full swipe

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

#BugWhat you seeTypical severity
1Several rows openTwo or more rows show their buttons at the same timeLow–Medium
2Action hits the wrong itemTap Delete on “Mom”, and “Emma” disappearsCritical
3Row stays openButtons still showing after scrolling, opening the item or coming backLow–Medium
4Tap on an open row opens the itemInstead of closing, the row opens the detail screenLow
5Label lies“Archive” deletes; “Mark as read” also mutesHigh
6State jumps to another rowAfter a delete, or after scrolling a long list, a different row appears openMedium–High
7No Undo / no confirmationA permanent delete happens with one swipeHigh
8Layout breaksText runs over the buttons at large text sizes; labels truncate in GermanMedium
9Gesture-onlyNo edit mode, menu or detail button; screen reader users can’t reach the actionHigh (for affected users)
10Not mirrored in RTLIn Arabic, Delete still appears on the rightMedium

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.

Found0/6
9:41

Chats

EEmma Clarke9:41Booked the ramen place for 8pm, see you there!2
MMom9:30Did you get the parcel I sent last week?1
RRunning club9:12Marco: Saturday 9am at the park entrance, bring water
DDaniel Novak8:55Can you review the sprint slides before lunch?
LLandlord (Mia)8:20The plumber comes Tuesday between 10 and 12
FFreshCart supportYesterdayYour refund of €12.40 has been processed
SSofia RossiYesterdayPhotos from the trip are in the shared album
BBook clubMonNext pick: The Pragmatic Programmer. Thoughts?
LLeo (Flatmate)MonWe are out of coffee again…
GGrandpaSunHappy birthday! Call me when you can
TTeam lunchSatAnna: Thai or pizza on Friday?
CCityRideFriYour verification code is 482 913

Device

Drag a chat left or right with your mouse or finger. Scroll with the wheel or by swiping up and down.

  1. 1

    Hint: Open the actions on two different chats, then tap Archive on the second one.

  2. 2

    Hint: Open a row, scroll the list, then tap the open row.

  3. 3

    Hint: Swipe-archive a chat, then open the Archived folder at the top of the list.

  4. 4

    Hint: Turn on Larger text, then swipe a chat to the left.

  5. 5

    Hint: Turn on VoiceOver, tap a chat and listen for the actions.

  6. 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 one

Preconditions

  • Chat list has at least 5 chats

Steps

  1. Swipe the first chat left until its buttons show
  2. 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 Archived

Steps

  1. Swipe "Mom" left
  2. Tap Archive
  3. Wait until the snackbar disappears
  4. 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 position

Steps

  1. Note the position of the third chat
  2. Swipe it left and tap Delete
  3. 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 delete

Steps

  1. Swipe the second chat left
  2. Tap Delete
  3. 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 row

Steps

  1. Swipe a chat left to reveal its buttons
  2. 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 it

Steps

  1. Swipe a chat left to reveal its buttons
  2. Tap the row content (not a button)

Expected result

The row closes. The chat does not open.

TC-SWL-007Swipe actions are available with VoiceOver

Preconditions

  • VoiceOver is on

Steps

  1. Swipe right until a chat is focused
  2. Listen to the announcement
  3. 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 size

Preconditions

  • iOS Settings › Accessibility › Display & Text Size › Larger Text at maximum

Steps

  1. Open Chats
  2. 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 Arabic

Preconditions

  • Device language set to Arabic

Steps

  1. Open Chats
  2. 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:

Mobile vs web

Dev note
Built in: SwiftUI .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
    Compose SwipeToDismissBox, RecyclerView ItemTouchHelper.
  • 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 and touch-action: pan-y so 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. 1.In English, where do trailing swipe actions like Delete usually appear?

  2. 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. 3.Which is the best protection for deleting a saved bank card with a swipe?

  4. 4.VoiceOver is on. How should a user archive a chat from the list?

  5. 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 ⚡
Esc

Type to search the whole site.