Component

Vue Swipe Actions Component

<DomSwipeActions>

Reveal row actions with a horizontal swipe while preserving vertical scrolling. Includes an Actions button, keyboard access, coordinated open rows, and opt-in full-swipe shortcuts. Applications own mutations and undo.

A shortcut on either side

Task actions

1200px

Install
npm install @getdom/studio
vue
<script setup>
import '@getdom/studio/style.css';
import { ref } from 'vue';
import { DomAppListItem, DomSwipeActions } from '@getdom/studio';

const result = ref('');
const tasks = ref([
	{ id: 1, label: 'Review the project notes', description: 'Mara shared an update this morning.', complete: false },
	{ id: 2, label: 'Book the workshop room', description: 'Tuesday, 10:00 to 11:30.', complete: false },
]);
const endActions = [
	{ value: 'remind', label: 'Remind me' },
	{ value: 'share', label: 'Share', disabled: true },
];

/** Updates local task state or acknowledges a reminder action in this example. */
function act(task, { action }) {
	if (action.value === 'complete') task.complete = !task.complete;
	result.value = action.value === 'complete' ? `${task.label}: ${task.complete ? 'complete' : 'reopened'}.` : `Reminder selected for ${task.label}.`;
}
</script>

<template>
	<div class="mx-auto w-full max-w-xl space-y-4 p-4">
		<div class="divide-y divide-border overflow-hidden rounded-2xl border border-border">
			<DomSwipeActions v-for="task in tasks" :key="task.id" :label="task.label" :start-actions="[{ value: 'complete', label: task.complete ? 'Reopen' : 'Complete', variant: 'success', fullSwipe: true }]" :end-actions="endActions" full-swipe group="task-example" @action="act(task, $event)">
				<DomAppListItem as="div" :label="task.label" :description="task.description" :meta="task.complete ? 'Done' : ''" />
			</DomSwipeActions>
		</div>
		<p class="text-xs leading-6 text-muted-fg">Swipe right to complete. Swipe left for reminders. The Actions button shows both sides, including a disabled sharing action.</p>
		<p v-if="result" role="status" class="text-sm text-canvas-fg">{{ result }}</p>
	</div>
</template>

Gesture contract

Put a row, button, or link in the default slot. startActions and endActions accept records with value, label, optional SVG-path icon, variant (default, success, danger), and disabled. Leading and trailing follow the row’s text direction.

Horizontal intent captures the gesture; vertical scrolling and pinch zoom remain native. Each gesture stays on its initial side: dragging back stops at the closed position, and a new swipe can reveal the opposite actions. Releasing a partial swipe reveals buttons or closes the row. Cancellation never executes an action. Only one row in a group stays open at a time.

Full-swipe execution requires full-swipe on the component and fullSwipe: true on that side’s first action. It uses actual travel distance, so a short fast flick only reveals controls. The action event includes the record, side, and source (button or swipe). The app owns persistence, pending state, and undo; set disabled while a mutation is pending.

The visible Actions button exposes both sides to touch, mouse, and keyboard users. Escape closes them and restores focus. Inputs and elements marked data-no-swipe do not start a row gesture.

See the mobile inbox for archive/restore, read state, deletion with Undo, and expandable message details.

Reference

Props

Control props

NameTypeTSDefaultDescription
labelstringstring'Row'Row name used in the accessible Actions button label.
startActions
ts
type Array<SwipeAction> = unknown;
arrayArray<SwipeAction>[]Leading actions: { value, label, icon, variant, disabled, fullSwipe }. icon is an SVG path.
endActions
ts
type Array<SwipeAction> = unknown;
arrayArray<SwipeAction>[]Trailing actions with the same shape as startActions.
fullSwipebooleanbooleanfalseAllow the first action on each side to run after a full swipe only when that action also has fullSwipe: true.
disabledbooleanbooleanfalseDisable gestures and all action controls.
groupstringstring'default'Opening a row closes other rows in this group in the same document.

Auto-generated from Swipe actions.props and inline _edit hints.

Slots

NameScopeDescription
#(default)Row content, including an ordinary button or link.
#action{ action, side }Optional visual content inside each action button.

Events

NamePayloadDescription
@actionSwipeActionPayloadAn enabled action selected by button or full swipe. source is button or swipe.
@openstringThe revealed side: start, end, or menu.
@closeAll action controls have closed.

Names auto-detected from defineEmits and source emit() calls; payload and description from __doc.events when present.

Keyboard

  • Actions buttonShows every action without requiring a gesture.
  • EscapeCloses revealed actions and returns focus to Actions.