Docs
Guides
Widget Modifiers

Widget Modifiers

Modifiers in Mix extend functionality by defining the widget composition tree structure, providing support for core widgets, external widgets, and third-party widgets without compromising the simplicity of core Mix.

$with

You can find all available modifiers within the $with utility. This provides a single place to access all modifier functions.

Spec Modifiers

You can also apply modifiers to specific widgets, thanks to the wrap property of each Attribute.

Box(
  style: Style(
    $box.wrap.scale(0.5),
  ),
);

It's a simple example of how to use SpecModifiers. In more complex cases, you may want to apply a modifier to a specific widget in the widget tree.

Box(
  style: Style(
    $icon.wrap.scale(2),
  ),
  child: StyledIcon(
    Icons.abc,
  ),
);

The code above results in a Box without any Transform applied, but as its child a StyledIcon widget with a Transform over it. The reason this is possible is because the $icon.wrap property will only be applied to the StyledIcons.

Understanding the Mechanics

Take the scale attribute, for instance. The Container widget doesn't inherently possess the ability to scale. But, by employing a Transform widget as a modifier, we can introduce this effect.

Transform.scale(
  scale: 0.5,
  child: Container(
    child: const Text("Half sized box"),
  ),
)
⚠️

Important Note: Modifiers are a special kind of attribute that can't be inherited for any child widgets.

Creating a modifier

We can achieve the same effect by creating a custom **WidgetModifier**.

Creating a modifier is like creating a **StatelessWidget**. Extend **WidgetModifier**. Define the properties you want to modify and the widget you want to decorate.

class ScaleModifier extends WidgetModifier<ScaleModifier> {
  final double scale;
  const ScaleModifier(this.scale, {super.key});
 
  @override
  ScaleModifier lerp(ScaleModifier? other, double t) {
    return ScaleModifier(lerpDouble(scale, other?.scale, t) ?? scale);
  }
 
  @override
  get props => [scale];
 
  @override
  Widget build(MixData mix, Widget child) {
    return Transform.scale(
      key: key,
      scale: scale,
      child: child,
    );
  }
}
 

You can then create an extension of the

Crafting a modifier utility

To simplify modifier usage, you can design an utility function that automatically creates the modifier for you.

ScaleModifier scale(double scale, {Key? key}) => ScaleModifier(scale, key: key);

Using a modifier

final style = Style(
  $with.scale(0.5),
  // or $box.wrap.scale(0.5),
);
 
Box(
  style: style,
  child: const Text('Half sized box'),
);

Built-in modifiers

Mix comes with a set of built-in modifiers that can be used out of the box.

Scale Modifier

Decorates a Box with a Transform.scale widget

final modifier = Style(
  $with.scale(0.5),
);
 
final specModifier = Style(
  $box.wrap.scale(0.5),
);
 
// Equivalent to
Transform.scale(
  scale: 0.5,
  child: Box(
    child: const Text('Half sized box'),
  ),
);

Opacity Modifier

Decorates a Box with an Opacity widget

final modifier = Style( $with.opacity(0.5), );

final specModifier = Style( $box.wrap.opacity(0.5), );

// Equivalent to Opacity( opacity: 0.5, child: Box( child: const Text('Half transparent box'), ), );

Rotate Modifier

Decorates a Box with a Transform.rotate widget. The parameter is quarter turns.

final modifier = Style( $with.rotate(1), );

final specModifier = Style( $box.wrap.rotate(1), );

// Equivalent to RotatedBox( quarterTurns: 1, child: Box( child: const Text('Rotated box'), ), );

Helper methods All helpers are also available for SpecModifiers.

  • $with.rotate(1): 90 degrees
  • $with.rotate.d90(): 90 degrees
  • $with.rotate(2): 180 degrees
  • $with.rotate.d180(): 180 degrees
  • $with.rotate(3): 270 degrees
  • $with.rotate.d270(): 270 degrees

Aspect Ratio Modifier

Decorates a Box with an AspectRatio widget

final modifier = Style( $with.aspectRatio(6/9), );

final specModifier = Style( $box.wrap.aspectRatio(6/9), );

// Equivalent to AspectRatio( aspectRatio: 6/9, child: Box( child: const Text('Aspect ratio box'), ), );

Clip Modifier

Decorates a Box with different types of Clip widgets

final modifier = Style( $with.clipOval(), );

final specModifier = Style( $box.wrap.clipOval(), );

Box( style: modifier, child: const Text('Oval box'), );

// Equivalent to ClipOval( child: Box( child: const Text('Oval box'), ), );

Helper methods All helpers are also available for SpecModifiers.

  • $with.clipOval(): Wraps with a ClipOval widget
  • $with.clipRrect(): Wraps with a ClipRRect widget
  • $with.clipRect(): Wraps with a ClipRect widget
  • $with.clipPath(): Wraps with a ClipPath widget
  • $with.clipTriangle(): Wraps with a ClipPath widget that clips to a triangle

Visibility Modifier

Decorates a Box with a Visibility widget

final modifier = Style( $with.visibility(false), );

final specModifier = Style( $box.wrap.visibility(false), );

// Equivalent to Visibility( visible: false, child: Box( child: const Text('Invisible box'), ), );

IntrinsicHeight and IntrinsicWidth Modifier

Decorates a Box with a IntrinsicHeight or IntrinsicWidth widget

final modifier = Style( $with.intrinsicHeight(), // or intrinsicWidth() );

final specModifier = Style( $box.wrap.intrinsicHeight(), // or intrinsicWidth() );

// Equivalent to IntrinsicHeight( // or IntrinsicWidth child: Box( child: const Text('Invisible box'), ), );

Helper methods All helpers are also available for SpecModifiers.

  • $with.show(): Wraps the Box with a Visibility widget that is visible
  • $with.hide(): Wraps the Box with a Visibility widget that is invisible
  • $with.visibility.on(): Wraps the Box with a Visibility widget that is visible
  • $with.visibility.off(): Wraps the Box with a Visibility widget that is invisible

Flexible Modifier

Decorates a Flex Styled widget like FlexBox, HBox, VBox, with a Flexible widget

final modifier = Style( $with.flexible(flex:1, fit: FlexFit.tight), );

final specModifier = Style( $box.wrap.flexible(flex:1, fit: FlexFit.tight), );

  • $with.flexible(flex:1, fit: FlexFit.tight): Wraps the Flex Styled widget with a Flexible widget

Helper methods All helpers are also available for SpecModifiers.

  • $with.flexible.expanded(): Equivalent to Expanded widget, or flexible(fit: FlexFit.tight)
  • $with.flexible.loose(): Equivalent to Flexible widget, or flexible(fit: FlexFit.loose)
  • $with.flexible.tight(): Equivalent to flexible(fit: FlexFit.tight)
  • $with.expanded(): Equivalent to Expanded widget, or flexible(fit: FlexFit.tight)

This is equivalent to wrapping the Flex Styled widget with a Flexible widget.

Flexible( flex: 1, fit: FlexFit.tight, child: FlexBox( children: [ const Text('Flexible box'), ], ), );

### Mouse Cursor

Decorates the `StyledWidget` with a `MouseRegion` widget but applying only the `cursor` property.

**Helper methods**

- `$with.cursor.defer()`
- `$with.cursor.uncontrolled()`
- `$with.cursor.none()`
- `$with.cursor.basic()`
- `$with.cursor.click()`
- `$with.cursor.forbidden()`
- `$with.cursor.wait()`
- `$with.cursor.progress()`
- `$with.cursor.contextMenu()`
- `$with.cursor.help()`
- `$with.cursor.text()`
- `$with.cursor.verticalText()`
- `$with.cursor.cell()`
- `$with.cursor.precise()`
- `$with.cursor.move()`
- `$with.cursor.grab()`
- `$with.cursor.grabbing()`
- `$with.cursor.noDrop()`
- `$with.cursor.alias()`
- `$with.cursor.copy()`
- `$with.cursor.disappearing()`
- `$with.cursor.allScroll()`
- `$with.cursor.resizeLeftRight()`
- `$with.cursor.resizeUpDown()`
- `$with.cursor.resizeUpLeftDownRight()`
- `$with.cursor.resizeUpRightDownLeft()`
- `$with.cursor.resizeUp()`
- `$with.cursor.resizeDown()`
- `$with.cursor.resizeLeft()`
- `$with.cursor.resizeRight()`
- `$with.cursor.resizeUpLeft()`
- `$with.cursor.resizeUpRight()`
- `$with.cursor.resizeDownLeft()`
- `$with.cursor.resizeDownRight()`
- `$with.cursor.resizeColumn()`
- `$with.cursor.resizeRow()`
- `$with.cursor.zoomIn()`
- `$with.cursor.zoomOut()`