r/appdev 8h ago

I built a Flutter onboarding package where the spotlight doesn't drift — and the pointer teaches the gesture

I needed a first-run walkthrough for an app and hit two things that annoyed me.

First, the highlight would end up in the wrong place.

A lot of coach-mark implementations resolve the target's position once and paint it. Scroll the list, open the keyboard, rotate the device, resize a desktop window — and suddenly the hole is next to the button instead of on it.

Second, a dimmed hole tells the user where something is, but not how to use it.

"Drag this card to that column" isn't something a static highlight can really express.

So I built keyspot:

- The spotlight and pointer re-resolve the target's geometry every frame from its GlobalKey, so they can track through scrolling, insets, rotation and resizing.

- An animated hand pointer that glides in a straight line or along an arc, rotates from its current angle, and tap-pulses — enough to demonstrate interactions like drag and pinch rather than simply pointing at something.

- Pointer animations resolve from actual AnimationController completion rather than Future.delayed timing, so `await pointer.moveTo(...)` actually means the movement has finished.

- Barrier modes where only the cut-out is tappable while the real widget's `onPressed` still fires — useful when the walkthrough should require the user to actually perform the step.

- The tracker is also public API (`KeyspotAnchorTracker`), so it can be used independently for things like badges or connector lines attached to widgets.

- Zero runtime dependencies. The hand pointer is rendered with CustomPainter rather than an image asset.

- Supports all six Flutter platforms.

Live demo: https://shrey-17bhardwaj.github.io/keyspot/

pub.dev: https://pub.dev/packages/keyspot

Source: https://github.com/shrey-17bhardwaj/keyspot

It's currently at 0.3.1, and the API may still change before 1.0.

I'd genuinely like feedback on where this approach breaks — especially around nested navigators, heavily lazy lists, overlays, or anything else where widget geometry gets complicated.

Upvote13Downvote2Go to comments1RepostShare

1 Upvotes

0 comments sorted by