FORMA Docs

Swipe actions

Reveal row actions with a swipe, or from the same actions in a menu.

import { SwipeActions, SwipeActionsRow } from "@/forma/arc/swipe-actions/swipe-actions";
Base

In FORMA

  • Liegt in kit/arc/swipe-actions und ist über @/forma/arc/swipe-actions/swipe-actions erreichbar.
  • Farbe, Ecken, Höhen, Abstände, Tiefe, Schrift und Tempo kommen aus der Richtung (core/arc-bridge.ts); Arc behält Verhalten, Tastatur und Federn.

When to use

  • Touch-first triage lists such as mail, notifications, or tasks.
  • Rows with one or two quick actions per side, like Archive and Mark unread.
  • Lists where a full swipe should commit the main action and the row should animate away.

When not to use

  • Use context-menu or dropdown-menu for desktop-first tables.
  • Use reorderable-list when rows need to be dragged vertically.
  • Use hold-to-confirm for a single destructive action outside a list.

Usage

import { SwipeActions, SwipeActionsRow } from "@/forma/arc/swipe-actions/swipe-actions";
import { Archive, MailOpen } from "@/forma/icons";

export function Inbox({ messages }: { messages: Message[] }) {
  return (
    <SwipeActions label="Inbox">
      {messages.map(message => (
        <SwipeActionsRow
          key={message.id}
          label={message.subject}
          leading={[{ label: "Unread", icon: <MailOpen size={18} />, tone: "accent", keepRow: true, onSelect: () => markUnread(message.id) }]}
          trailing={[{ label: "Archive", icon: <Archive size={18} />, tone: "danger", onSelect: () => archive(message.id) }]}
        >
          <MessagePreview message={message} />
        </SwipeActionsRow>
      ))}
    </SwipeActions>
  );
}

API reference

SwipeActions

The list. Keeps one row open at a time and closes it on an outside press or Escape.

PropTypeDefaultDescription
label (required)string–Accessible name for the list.
children (required)ReactNode–SwipeActionsRow elements. Removing one animates its height closed.
classNamestring–Extra class on the surface.

SwipeActionsRow

One row whose actions reveal under its left and right edges on a horizontal swipe.

PropTypeDefaultDescription
label (required)string–Names the row's More actions button, for example the message subject.
leadingSwipeAction[][]Actions under the left edge, revealed by swiping right. The first one commits on a full swipe.
trailingSwipeAction[][]Actions under the right edge, revealed by swiping left. The last one commits on a full swipe.
fullSwipebooleantrueLets a long swipe or flick commit the outermost action.
children (required)ReactNode–Row content.
classNamestring–Extra class on the row.

SwipeAction

One action in leading or trailing.

PropTypeDefaultDescription
label (required)string–Shown under the icon and in the menu.
icon (required)ReactNode–Action icon.
onSelect (required)() => void–Runs on full swipe, tap, or menu choice. Remove the item here unless keepRow is set.
tone"neutral" | "accent" | "danger""neutral"Fill of the revealed action.
keepRowboolean–Springs the row home after the action instead of sliding it away.

Keyboard interactions

KeysAction
Enter / SpaceOpens a row's More actions menu from its button.
ArrowDown / ArrowUpMoves between the row's actions in the menu.
EscapeCloses the menu or puts away an open row.

Accessibility

  • The list is a ul with role="list" and aria-label; each row is an li.
  • Every row has a "More actions for <label>" menu with the same actions, so the gesture is never required.
  • Revealed action buttons are aria-hidden and out of the tab order; after a removing action, focus moves to a neighbouring row.

Motion

  • The row tracks the finger, rubber-bands past its last stop, and settles on a spring that carries the release velocity; a flick projects its travel.
  • Past the threshold the outer action stretches across the row, then the row slides out and the list closes the gap.
  • Reduced motion jumps the row to its stops and fades rows in and out instead of animating height.

Responsive behavior

  • Swipes lock to the horizontal axis after the first movement, so vertical page scrolling still works on touch.
  • A full swipe commits past the larger of the open width plus 48px or 56% of the row, measured with a ResizeObserver.
  • Every row also has a More actions menu, so mouse and keyboard users never need the gesture.

Performance

  • Drag updates a motion value directly, so rows do not re-render while following the finger.
  • Rows are not virtualized and each has its own ResizeObserver; paginate long lists.

Notes for AI

  • Use for short, triage-style lists on touch (mail, notifications, tasks). For desktop-first tables use context-menu or a row menu.
  • Remove the item from state inside onSelect; set keepRow for actions that keep the item, such as mark as unread.
  • Rows must be direct children of SwipeActions, keyed by item id, so removal and undo animate.

Also in gestures

  • Reactions: Acknowledge a post in one tap, with counts that roll.

Guidance for AI tools

Swipe actions: Reveal row actions with a swipe, or from the same actions in a menu. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://uiarc.dev/llms.txt

Komponente und Text: Arc UI (MIT, uiarc.dev), angepasst für FORMA.