Swipe

Reactive touch-swipe detection on an element using Touch Events API. Tracks single-finger swipe gestures and provides direction and distance signals.

Use PointerSwipe for non-touch input

The swipe function only responds to touch events. If you need to detect swipe gestures from mouse or pen input, use PointerSwipe instead — it works with all pointer types.

Loading demo...

Usage

angular-ts
import { Component, viewChild, ElementRef } from '@angular/core';
import { swipe } from '@signality/core';

@Component({
  template: `
    <div #area style="touch-action: none; width: 300px; height: 300px;">
      <p>Swiping: {{ sw.isSwiping() }}</p>
      <p>Direction: {{ sw.direction() }}</p>
    </div>
  `,
})
export class SwipeDemo {
  readonly area = viewChild<ElementRef>('area');
  readonly sw = swipe(this.area); 
}

Parameters

ParameterTypeDescription
targetMaybeElementSignal<HTMLElement>Element to detect swipe gestures on
optionsSwipeOptionsOptional configuration (see Options below)

Options

The SwipeOptions extends WithInjector:

OptionTypeDefaultDescription
thresholdnumber50Minimum distance in pixels before a swipe is recognized
injectorInjector-Optional injector for DI context

Return Value

Returns a SwipeRef:

PropertyTypeDescription
isSwipingSignal<boolean>Whether a swipe gesture is currently in progress
directionSignal<SwipeDirection>Current swipe direction ('up', 'down', 'left', 'right', or 'none')
distanceXSignal<number>Horizontal distance from start (positive = swiped left)
distanceYSignal<number>Vertical distance from start (positive = swiped up)

Examples

Swipe-to-dismiss

Card follows your finger and disappears when released past 150 px.

angular-ts
import { Component, viewChild, ElementRef, linkedSignal } from '@angular/core';
import { swipe } from '@signality/core';

@Component({
  template: `
    @if (visible()) {
      <div
        #card
        style="touch-action: pan-y"
        [style.transform]="'translateX(' + sw.distanceX() * -1 + 'px)'"
        [style.transition]="sw.isSwiping() ? 'none' : 'all .3s ease'"
      >
        Swipe left or right to dismiss
      </div>
    } @else {
      <button (click)="visible.set(true)">Show again</button>
    }
  `,
})
export class SwipeDismissDemo {
  readonly card = viewChild<ElementRef>('card');
  readonly sw = swipe(this.card);

  readonly visible = linkedSignal({
    source: () => !this.sw.isSwiping() && Math.abs(this.sw.distanceX()) >= 150,
    computation: dismissed => !dismissed,
  });
}

Direction indicator

angular-ts
import { Component, viewChild, ElementRef, computed } from '@angular/core';
import { swipe } from '@signality/core';

@Component({
  template: `
    <div #area style="touch-action: none">
      <p>{{ arrow() }}</p>
      <p>Distance: {{ sw.distanceX() }}px / {{ sw.distanceY() }}px</p>
    </div>
  `,
})
export class DirectionDemo {
  readonly area = viewChild<ElementRef>('area');
  readonly sw = swipe(this.area);

  readonly arrow = computed(() => {
    switch (this.sw.direction()) {
      case 'up': return 'Up';
      case 'down': return 'Down';
      case 'left': return 'Left';
      case 'right': return 'Right';
      default: return 'Swipe in any direction';
    }
  });
}

SSR Compatibility

On the server, signals initialize with safe defaults:

  • isSwipingfalse
  • direction'none'
  • distanceX0
  • distanceY0

Type Definitions

typescript
type SwipeDirection = 'up' | 'down' | 'left' | 'right' | 'none';

interface SwipeOptions extends WithInjector {
  readonly threshold?: number;
}

interface SwipeRef {
  readonly isSwiping: Signal<boolean>;
  readonly direction: Signal<SwipeDirection>;
  readonly distanceX: Signal<number>;
  readonly distanceY: Signal<number>;
}

function swipe(
  target: MaybeElementSignal<HTMLElement>,
  options?: SwipeOptions
): SwipeRef;
Edit this page on GitHub Last updated: Mar 19, 2026, 23:28:23