Docs
Tutorials
Extending Utilities

Extending Mix Utilities

Creating a LinearGradient Utility

In this tutorial, we'll explore how to extend Mix utilities to create custom utilities that align with your design system. We'll focus on creating a utility for vertical gradients as an example.

Understanding the Problem

When working with gradients in Mix, you may find yourself frequently defining vertical gradients using the LinearGradientUtility. For example:

final style = Style(
  $box.linearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
  ),
  
  // Or you can do this
  $box.linearGradient.begin.topCenter(),
  $box.linearGradient.end.bottomCenter(),
);

While this approach works, it can be repetitive and less intuitive if vertical gradients are a common pattern in your styles.

Extending the LinearGradientUtility

Mix allows you to extend its utilities to create custom utilities tailored to your needs. Let's explore two approaches to extending the LinearGradientUtility to create a vertical gradient utility.

Approach 1: Creating a vertical Getter

One way to create a vertical gradient utility is by adding a vertical getter to the LinearGradientUtility. Here's an example:

extension LinearGradientUtilityX<T extends Attribute> on LinearGradientUtility<T> {
  LinearGradientUtility<T> get vertical {
    return LinearGradientUtility(
      (v) => only(begin: Alignment.topCenter, end: Alignment.bottomCenter));
  }
}

With this extension, you can access the vertical gradient utility using $box.linearGradient.vertical or $box.decoration.gradient.linear.vertical.

However, there's a potential issue with this approach. When using linearGradient.vertical.colors(), the begin and end alignments will always be applied, followed by the colors.

But if you use linearGradient.vertical.begin(), it can get complicated, as you can still override the begin alignment.

Approach 2: Creating a vertical Function Method (Recommended)

A cleaner approach is to create a vertical function method that applies the begin and end alignments without allowing further composition. Here's an example:

extension LinearGradientUtilityX<T extends Attribute> on LinearGradientUtility<T> {
  T vertical() {
    return only(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
    );
  }
}

With this approach, when you call linearGradient.vertical(), it will apply the begin and end alignments, but the utility cannot be composed further. You would need to use linearGradient.colors([...]) separately.

This approach is cleaner from a style perspective because it doesn't hide the injection of attributes.

Using the Custom Vertical Gradient Utility

Now that we have extended the LinearGradientUtility with a vertical function method, let's see how we can use it in our styles:

final style = Style(
    /// Approach 1:
    $box.linear.gradient.vertical.colors([Colors.blue, Colors.green]),
    /// Approach 2:
    $box.linearGradient.vertical(),
    $box.linearGradient.colors([Colors.blue, Colors.green]),
);

In this example, we apply the vertical gradient using $box.linearGradient.vertical() and then specify the colors separately using $box.linearGradient.colors([...]).

Conclusion

Extending Mix utilities allows you to create custom utilities that align with your design system and make your styling code more expressive and maintainable. By creating a vertical gradient utility, we've seen how we can simplify the definition of vertical gradients in our styles.

Remember, when extending utilities, it's important to consider the composition and behavior of the utility to ensure a clean and intuitive usage.

Happy styling with Mix!