Framer Motion. For Flutter.

Animate anything.Write almost nothing.

Spring physics, exit animations, viewport triggers, gesture states, and variants — all in a declarative API that replaces hundreds of lines of AnimationController boilerplate.

flutter pub add nib_motion
The status quo

Flutter animations shouldn't be this hard.

The Flutter way
// 67 lines just to fade in a widget
late AnimationController _controller;
late Animation<double> _animation;

@override
void initState() {
  super.initState();
  _controller = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 400),
  );
  _animation = Tween(begin: 0.0, end: 1.0)
      .animate(CurvedAnimation(
        parent: _controller,
        curve: Curves.easeOut,
      ));
  _controller.forward();
}

@override
void dispose() {
  _controller.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return FadeTransition(
    opacity: _animation,
    child: MyWidget(),
  );
}
// ...and you still can't animate it out.
The NibMotion way
NibMotion(
  initial: NibAnim(opacity: 0),
  animate: NibAnim(opacity: 1),
  exit:    NibAnim(opacity: 0),
  child: MyWidget(),
)

That exit animation on the right? That required NibPresence. No other Flutter package does this.

Flutter's most-requested missing feature

Exit animations.Finally.

Every Flutter animation package ignores widget removal. When a widget leaves the tree, Flutter unmounts it instantly — no chance to animate it out. NibPresence changes that. It intercepts the unmount, holds the widget alive, plays the exit animation to completion, then removes it cleanly.

dart
NibPresence(
  children: isVisible
    ? [
        NibMotion(
          key: const ValueKey('card'),
          initial: NibAnim(opacity: 0, y: 20),
          animate: NibAnim(opacity: 1, y: 0),
          exit:    NibAnim(opacity: 0, y: -20),
          transition: NibTransition.springSnappy,
          child: MyCard(),
        ),
      ]
    : [],
)
Physics-based

Real spring physics.Not CSS easing curves.

Curves.elasticOut is not a spring. It's a curve that approximates one. NibMotion uses Flutter's SpringSimulation — real mass, stiffness, and damping — so gesture-release animations carry actual velocity. Flick a widget. It keeps moving.

dart
NibMotion(
  whileTap: NibAnim(scale: 0.94),
  transition: NibTransition.springWobbly, // mass:1 stiffness:180 damping:12
  child: MyButton(),
)
Scroll-triggered

Animate when it entersthe viewport.

Flutter has no Intersection Observer equivalent. NibMotion's viewport system detects when a widget enters the visible area and triggers its enter animation. Build scroll-reveal layouts, staggered content sections, and parallax effects without any package dependencies beyond NibMotion itself.

dart
NibMotionList(
  initial: NibAnim(opacity: 0, y: 32),
  animate: NibAnim(opacity: 1, y: 0),
  staggerDelay: Duration(milliseconds: 60),
  children: items.map((item) => ItemCard(item)).toList(),
)
Zero GestureDetector boilerplate

Declare gesture states.NibMotion handles the rest.

whileTap. whileHover. whileDrag. whileFocus. Each is a NibAnim — the state the widget animates to while the gesture is active, and springs back from the moment it ends. No GestureDetector. No setState. No AnimationController.

dart
NibMotion(
  whileTap:   NibAnim(scale: 0.92, opacity: 0.85),
  whileHover: NibAnim(scale: 1.04),
  transition: NibTransition.springSnappy,
  child: MyCard(),
)
Parent-controlled

One state change.Every child responds.

Variants let a parent widget control the animation state of all its descendants by name. Toggle 'hidden' to 'visible' at the top level and every child widget that knows about those variants animates in sequence — with stagger built in.

dart
const containerVariants = {
  'hidden': NibAnim(opacity: 0),
  'visible': NibAnim(opacity: 1),
};
const itemVariants = {
  'hidden': NibAnim(opacity: 0, y: 24),
  'visible': NibAnim(opacity: 1, y: 0),
};

NibMotion(
  animate: isVisible ? 'visible' : 'hidden',
  variants: containerVariants,
  child: Column(
    children: items.map((item) =>
      NibMotion(variants: itemVariants, child: ItemWidget(item))
    ).toList(),
  ),
)

See what's possible

Every primitive, live in Flutter. Click any demo to see the code.

Also included

A component library built on motion.

NibMotion ships with a growing set of production-ready Flutter components — each animated out of the box, built on the same design tokens.

Start animating in 60 seconds.

Add NibMotion to any Flutter project. No setup. No boilerplate. The first animation you write will be the last AnimationController you ever think about.

flutter pub add nib_motion