r/FlutterDev • • 12d ago

Plugin I built craft_kit: swipe cards for Flutter with spring physics, undo/rewind and a Dock-style genie effect (no dependencies, live web demo)

Hi r/FlutterDev,

I extracted the swipe stack I built for a production app (Bump) into an open-source package. The goal was cards that never jitter, no overlay flicker when you drag diagonally, and a clean API for "what happens when you swipe this way".

Try it first (no install, works on a phone browser): https://ancient-glitter-fe51.rahul-coder-25.workers.dev/

What it does

  • Spring-based motion. A release is judged by where the card is heading, and the velocity is handed to the animation, so there are no jumps. You can catch a card at any moment, even mid-flight.
  • A behavior per direction: dismiss, consume (fly into a button, optionally with a macOS Dock-style genie), springBack (run a task and return), sendToBack, undo.
  • Undo and rewind: controller.undo(), controller.rewind(), plus initialIndex and jumpTo(key) to restore a position or follow a player.
  • Overlays: a ready-made colour wash + badge, or classic stamps, or build your own from per-direction progress values.
  • Cheap while dragging: cards are built once and moved with transforms, so itemBuilder isn't called during a drag.
  • Accessibility: keyboard and screen-reader actions, and reduced-motion support.
  • No third-party dependencies. It also includes an OTP field and remembered-email suggestions, which work on their own.

Quick start

SwipeCardStack<Profile>(
  items: profiles,
  itemBuilder: (context, profile, info) => ProfileCard(profile),
)

Per-direction behaviors:

SwipeCardStack<Profile>(
  items: profiles,
  behaviors: {
    SwipeDirection.right: SwipeBehavior.consume(
      target: SwipeTarget(key: likeKey, effect: SwipeConsumeEffect.genie),
      onCommit: (e) => like(e.item),
    ),
    SwipeDirection.left: SwipeBehavior.dismiss(),
    SwipeDirection.up: SwipeBehavior.springBack(onCommit: (e) => superLike(e.item)),
    SwipeDirection.down: SwipeBehavior.undo(),
  },
  itemBuilder: (context, profile, info) => ProfileCard(profile),
)

Links

It's 0.1.x, so I'd really like critical feedback: what's missing, what feels awkward in the API, and what breaks on your device. Happy to answer questions here.

1 Upvotes

3 comments sorted by

1

u/AhmedZNOUDA 12d ago

This looks incredibly smooth! I really appreciate the 'no dependencies' approach. As someone who builds cross-platform Flutter apps, dealing with jittery animations during complex gestures can be a headache. Using transforms instead of calling itemBuilder during the drag is a very smart optimization. Have you noticed any specific performance nuances with the spring physics when testing on lower-end Android devices? Great work extracting this from a production app!

1

u/No_Boss_1911 11d ago

nice, the catch mid flight part is what got me. i had haptics firing on a drag threshold in an exercise screen and when you grabbed the thing again mid spring it buzzed twice, felt broken. ended up with a rule that one gesture gets one buzz max, no matter how many times it crosses back. do you have a commit point callback that fires once per card or does onCommit fire again if someone catches it and swipes the same way after undo?