Skip to content

Add a subtree blend-mode widget modifier #994

Description

@leoafarias

Use case

Mix supports BoxDecorationMix.backgroundBlendMode, which blends a decoration's own background layers, and ShaderMaskModifier, which blends a shader with its child. It does not currently have the widget-level equivalent of CSS mix-blend-mode: compositing a complete rendered child subtree as one source against content already painted behind it.

This is needed when mapping design systems that use element-level blending. For example, Radix Themes applies mix-blend-mode: multiply to disabled Slider roots in light themes and screen in dark themes. Applying a blend mode independently to the track, range, thumbs, and shadows produces different output because those elements are not grouped before compositing.

Remix currently needs a bespoke render-object wrapper to preserve this behavior.

Visual comparison

The same disabled Fortal Slider is rendered against the same backdrop. Only subtree compositing changes.

Disabled Fortal Slider before and after subtree multiply blending

  • Before: BlendMode.srcOver — standard painting, with no subtree layer.
  • After: BlendMode.multiply — the complete Slider subtree is composited as one layer against the backdrop.

This comparison was rendered by Flutter with the theme, recipe, disabled state, value, dimensions, and backdrop held constant.

Proposal

Add a Mix widget modifier for subtree blending, tentatively BlendModeModifier / BlendModeModifierMix, exposed through WidgetModifierConfig.

Proposed usage:

BoxStyler().wrap(.blendMode(BlendMode.multiply))

Desired behavior:

  • Composite the complete painted child subtree against its backdrop using the selected BlendMode.
  • Treat BlendMode.srcOver as a no-op fast path.
  • Preserve layout, hit testing, and semantics.
  • Participate in normal Mix property resolution and modifier merging.
  • Account for child paint overflow and explicit clips when determining the blend layer bounds.
  • Explicitly support or document the behavior for composited descendants such as RepaintBoundary.

A canvas implementation can group child painting with saveLayer, but retained/composited descendants cannot simply be enclosed by that canvas operation. The API should therefore either support them through a layer-based design or expose the limitation clearly.

This is distinct from both decoration backgroundBlendMode and ShaderMaskModifier because the source and destination operands are different.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions