Skip to content

keyframeAnimation styleBuilder loses parent style properties set before .box() #910

Description

@tilucasoli

Description

When using keyframeAnimation inside a .box() call, the animation's styleBuilder does not receive the properties declared earlier in the fluent chain (e.g., color, padding, borderRadius, size). The styleBuilder callback receives a bare BoxStyler() as its style parameter instead of one that carries the previously set properties.

The expectation is that the animation builds on top of the parent style — the animated properties should override specific values while the rest of the parent style is preserved.

Steps to Reproduce

final style = IconBoxStyler()
    .color(Color.purple).        // expects this to carry into animation
    .padding(.all(16))              // expects this to carry into animation
    .borderRadius(.circular(16))    // expects this to carry into animation
    .size(80, 80)                   // expects this to carry into animation
    .box(
      BoxStyler().keyframeAnimation(
        timeline: [
          .new('scale', [
            .spring(3.0, 2000.ms),
            .linear(1.0, 1000.ms),
          ], initial: 1.0),
        ],
        styleBuilder: (values, style) => style.scale(values.get('scale'))),
      ),
    )
    .icon(.color(Colors.white).size(30));

Expected Behavior

The styleBuilder's style parameter should include the properties from the parent chain (color, padding, borderRadius, size). The animation should override only scale while preserving the rest of the parent style (padding, borderRadius, size).

Actual Behavior

The styleBuilder receives a bare BoxStyler() with no parent properties. The animated frames lose padding, borderRadius, size, and any other properties set before .box().

Root Cause

In keyframeAnimation() (animation_style_mixin.dart:12-25), initialStyle is captured from this:

T keyframeAnimation({...}) {
  return animate(
    KeyframeAnimationConfig<S>(
      ...
      initialStyle: this,  // captures current BoxStyler
    ),
  );
}

Since the call is BoxStyler().keyframeAnimation(...), this is an empty BoxStyler(). The parent properties (set via IconBoxStyler.color(), .padding(), etc.) live in a separate BoxStyler that gets merged into the $box prop via Prop.mergeProp(). But the animation's initialStyle never sees those accumulated parent properties.

When _KeyframeAnimatable.transform() runs (style_animation_driver.dart:443-453), it calls:

_config.styleBuilder(KeyframeAnimationResult(result), _config.initialStyle).resolve(_context)

The initialStyle is the bare BoxStyler(), so all parent properties are lost in the animated frames.

Relevant code paths

  • AnimationStyleMixin.keyframeAnimation()packages/mix/lib/src/style/mixins/animation_style_mixin.dart:12-25
  • _KeyframeAnimatable.transform()packages/mix/lib/src/animation/style_animation_driver.dart:443-453
  • Prop.mergeProp()packages/mix/lib/src/core/prop.dart

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions