Decorators
Decorators 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.
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 decorator, we can introduce this effect.
Transform.scale(
  scale: 0.5,
  child: Container(
    child: const Text("Half sized box"),
  ),
)Important Note: Decorators are a special kind of attribute that can't be inherited for any child widgets.
Creating a decorator
We can achieve the same effect by creating a custom **WidgetDecorator**.
Creating a decorator is like creating a **StatelessWidget**. Extend **WidgetDecorator**. Define the properties you want to modify and the widget you want to decorate.
class ScaleDecorator extends WidgetDecorator<ScaleDecorator> {
  final double scale;
  const ScaleDecorator(this.scale, {super.key});
 
  @override
  ScaleDecorator lerp(ScaleDecorator? other, double t) {
    return ScaleDecorator(lerpDouble(scale, other?.scale, t) ?? scale);
  }
 
  @override
  get props => [scale];
 
  @override
  Widget build(mix, child) {
    return Transform.scale(
      key: key,
      scale: scale,
      child: child,
    );
  }
}Crafting a decorator utility
To simplify decorator usage, you can design a utility function that automatically creates the decorator for you.
ScaleDecorator scale(double scale, {Key? key}) => ScaleDecorator(scale, key: key);Using a decorator
final style = Style(
  scale(0.5),
);
 
Box(
  style: style,
  child: const Text('Half sized box'),
);Built-in decorators
Mix comes with a set of built-in decorators that can be used out of the box.
Scale Decorator
Decorates a Box with a Transform.scale widget
final style = Style(
  scale(0.5),
);
 
// Equivalent to
Transform.scale(
  scale: 0.5,
  child: Box(
    child: const Text('Half sized box'),
  ),
);Opacity
Decorates a Box with an Opacity widget
final style = Style(
  opacity(0.5),
);
 
// Equivalent to
Opacity(
  opacity: 0.5,
  child: Box(
    child: const Text('Half transparent box'),
  ),
);Rotate
Decorates a Box with a Transform.rotate widget. The parameter is quarter turns.
final style = Style(
  rotate(1),
);
 
// Equivalent to
RotatedBox(
  quarterTurns: 1,
  child: Box(
    child: const Text('Rotated box'),
  ),
);Helper methods
- rotate(1): 90 degrees
- rotate.d90(): 90 degrees
- rotate(2): 180 degrees
- rotate.d180(): 180 degrees
- rotate(3): 270 degrees
- rotate.d270(): 270 degrees
Aspect Ratio
Decorates a Box with an AspectRatio widget
final style = Style(
  aspectRatio(6/9),
);
 
// Equivalent to
AspectRatio(
  aspectRatio: 6/9,
  child: Box(
    child: const Text('Aspect ratio box'),
  ),
);Clip
Decorates a Box with different types of Clip widgets
final style = Style(
  clip.oval(),
);
 
Box(
  style: style,
  child: const Text('Oval box'),
);
 
// Equivalent to
ClipOval(
  child: Box(
    child: const Text('Oval box'),
  ),
);Helper methods
- clip.oval(): Wraps with a ClipOval widget
- clip.rrect(): Wraps with a ClipRRect widget
- clip.rect(): Wraps with a ClipRect widget
- clip.path(): Wraps with a ClipPath widget
- clip.triangle(): Wraps with a ClipPath widget that clips to a triangle
Visibility
Decorates a Box with a Visibility widget
final style = Style(
  visibility(false),
);
 
// Equivalent to
Visibility(
  visible: false,
  child: Box(
    child: const Text('Invisible box'),
  ),
);Helper methods
- visibility.on(): Wraps the Box with an Visibility widget that is visible
- visibility.off(): Wraps the- **Box**with an- **Visibility**widget that is invisible
Flexible
Decorates a Flex Styled widget like FlexBox, HBox, VBox, with a Flexible widget
final style = Style(
  flexible(flex:1, fit: FlexFit.tight),
);- flexible(flex:1, fit: FlexFit.tight): Wraps the- FlexStyled widget with a- Flexiblewidget
Helper methods
- flexible.expanded(): Equivalent to Expanded widget, or- flexible(fit: FlexFit.tight)
- flexible.loose(): Equivalent to Flexible widget, or- flexible(fit: FlexFit.loose)
- flexible.tight(): Equivalent to- 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'),
    ],
  ),
);