Skip to content

fix(paint): let a self-painting component see its animated background - #415

Merged
LeadcodeDev merged 1 commit into
mainfrom
fix/animated-background-on-self-painting
Sep 29, 2026
Merged

LeadcodeDev merged 1 commit into
mainfrom
fix/animated-background-on-self-painting

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Closes #324.

Reproduced

A badge with a timeline step changing style.background, over a 1.0 s linear
transition:

before after
t = 0.2 s #FF0000 #FF0000
t = 1.0 s #FF0000 #7F007F
t = 1.8 s #FF0000 #0000FF

Cause

Six components paint their own background and read it from their own style:
badge, callout, caption, kbd, stat, tooltip.

resolve_transition_css_overrides writes the interpolated colour onto the node's
css.background. The cascade only carries inheritable properties onto the
clone a component is painted from, and background is not one — so the component
kept painting its declared colour, over the animated one the generic background
step had just painted underneath it.

The fix

with_resolved_background writes the node's resolved background onto a clone of
those six. It returns None when the resolved value already equals the
component's own, so a component whose background is not animated is not cloned
at all
— the serde round-trip is not paid per frame for the common case.

Why not fold it into with_cascaded_style

stat. That function is about inheritance and classifies stat as
non-typographic, so it returns None for it — folding the fix in there would have
missed a sixth of the components it is for. The two concerns are kept apart, and
a_stat_follows_it_too_although_the_cascade_never_clones_it is the test that pins
that specific path.

Tests

Test
a_badge_follows_an_animated_background_instead_of_repainting_its_own the typographic path
a_stat_follows_it_too_although_the_cascade_never_clones_it the path with_cascaded_style does not reach
a_component_with_no_background_animation_is_untouched the clone is not taken when there is nothing to carry

Reverting the dispatch change fails the first two with got (255, 0, 0) — the
declared colour, at the halfway point.

Gate

cargo fmt --all --check clean · cargo clippy --workspace --all-targets --features rustmotion/studio -D warnings clean · cargo test --workspace 1787 passed.

Six components paint their own background and read it from their own
style: badge, callout, caption, kbd, stat, tooltip. The animated value
never reached them. resolve_transition_css_overrides writes the
interpolated colour onto the node's css.background, and the cascade only
carries inheritable properties onto the clone a component is painted
from -- background is not one. So a badge with a timeline step changing
style.background painted its declared colour for the whole scene, and
the generic background step underneath painted the animated one where
the component's own opaque fill covered it.

with_resolved_background writes the node's resolved background onto a
clone of the six. It returns None when the resolved value already equals
the component's own, so a component whose background is not animated is
not cloned at all -- the serde round-trip is not paid per frame for the
common case.

stat is the reason this is not folded into with_cascaded_style: that
function is about inheritance and classifies stat as non-typographic, so
it returns None for it and the fix would have missed a sixth of the
components it is for.

Verified on a badge with a 1.0s linear transition: red at 0.2s,
(127, 0, 127) at 1.0s, blue at 1.8s. Before, all three were red.
@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 29, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 29, 2026
@LeadcodeDev
LeadcodeDev merged commit e02c86b into main Sep 29, 2026
4 checks passed
@LeadcodeDev
LeadcodeDev deleted the fix/animated-background-on-self-painting branch September 29, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A self-painting component may ignore an animated background colour

1 participant