Member-only story

This package will change your Flutter code forever

5 min read6 days ago

Full article

If you are a member, please continue, otherwise, read the full story here.

Contents

The problem
The solution
Mix widgets
Design systems
Extracting styles vs extracting components
Limited number of styled widgets
Conclusion

The problem

Here is how we normally write Flutter code:

         Container(
height: 100,
width: 100,
margin: EdgeInsets.symmetric(
vertical: 10,
horizontal: 20,
),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: Colors.black,
width: 1,
style: BorderStyle.solid,
),
),
child: Text('Hello World'),
),

The code is absolutely legit, we do it every time, and don’t know better.

The problem is: the widget (Container) definition is mixed with styling attributes without a clear way to separate them.

It is like writing HTML with inline CSS:

<div style="
height: 100px;
width: 100px;
margin: 10px 20px;
background-color: #2196F3;
border-radius: 10px;
border: 1px solid #000000;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
"
>
Hello World
</div>

However, the above CSS can be easily extracted from the HTML, but the attributes of Flutter’s Container cannot be extracted.

The solution

This is exactly what the Mix package is for. It allows rewriting Flutter widgets in a way that makes them easily separable from their styling attributes.

Here is the above Container rewritten with Mix:

         Box(
style: Style(
$box.height(100),
$box.width(100),
$box.margin(10, 20),
$box.color.blue(),
$box.borderRadius(10),
$box.border(
color: Colors.black,
width: 1,
style: BorderStyle.solid,
)),
child: Text('Hello Mix'),
),

The Box widget is the Mix’s analog of Flutter’s Container.

We can see that the Style object can be easily extracted from the view code and put in a separate style library where it belongs.

 Style blue100 = Style(
$box.height(100),
$box.width(100),
$box.margin(10, 20),
$box.color.blue(),
$box.borderRadius(10),
$box.border(
color: Colors.black,
width: 1,
style: BorderStyle.solid,
),
);

And now our view looks amazing:

         Box(
style: blue100,
child: Text('Hello Mix'),
)

This package is extremely underrated.

Yes, it is the whole new API on top of Flutter with some learning curve, but look at the above code snippet again. It was:

        Container(
height: 100,
width: 100,
margin: EdgeInsets.symmetric(
vertical: 10,
horizontal: 20,
),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: Colors.black,
width: 1,
style: BorderStyle.solid,
),
),
child: Text('Hello World'),
),

It became:

         Box(
style: blue100,
child: Text('Hello Mix'),
)

It is worth any learning curve! 😎

What is this alien-looking $box variable?

It reminds me of the love of my youth — jQuery

Nothing complicated here. It is the global variable of type BoxSpecUtility , that “knows” all attributes that can be applied to the Box widget.

Mix widgets

Mix has a set of widgets that are styled replacements of the corresponding Flutter widgets. Each has a related SpecUtility object with a global variable starting with $.

We are already familiar with Box, which is the styled Container.

The rest are listed below.

StyledText is a replacement for Text.

Instead of:

         Text(
'text',
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),

We should write:

  Style green20 = Style(
$text.color.green(),
$text.fontSize(20),
);
         StyledText(
'text',
style: green20,
)

HBoxVBox, and FlexBox are equivalents of RowColumn, and Flex

Instead of:

           SizedBox(
height: 100,
child: Row(
spacing: 20,
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
Container(color: Colors.green, width: 100, ),
Container(color: Colors.red, width: 100,),
],),
),

we can do:

   Style row20EndMax = Style(
$box.height(100),
$flex.gap(20),
$flex.mainAxisAlignment.end(),
$flex.mainAxisSize.max(),
);

Style boxW100green = Style(
$box.color.green(),
$box.width(100),
);

Style boxW100red = Style(
$box.color.red(),
$box.width(100),
);
           HBox(
style: row20EndMax,
children: [
Box(
style: boxW100green,
),
Box(
style: boxW100red,
),
],
),

Note, that HBoxVBox, and FlexBox are also boxes and BoxSpecUtility $box properties can also be applied to them. Very convenient.

PressableBox is a mix of the Container , MouseRegion and GestureDetector. Ideal for creating custom buttons.

StyledIcon and StyledImage are self-explanatory.

And, finally, ZBox is a mix of Container and Stack.

I planned to provide examples for every Mix widget, but now I think we already got an idea, and more examples will not change the perception.

For me, the package is gold. I am going to use it as much as possible.

Design systems

The package documentation and every article about Mix I have checked are talking about design systems and how Mix makes them easier to create.

We can get the impression that we only need it when we want to create our own design system.

First, no. The Mix coding style is more convenient and readable, even if we don’t separate widgets from styles.

Second, when we code the whole app with Mix, we end up with a styling library that can be reused. Like this:


Style blue100 = Style(
$box.height(100),
$box.width(100),
$box.margin(10, 20),
$box.color.blue(),
$box.borderRadius(10),
$box.border(
color: Colors.black,
width: 1,
style: BorderStyle.solid,
),
);

Style green20 = Style(
$text.color.green(),
$text.fontSize(20),
);

Style row20EndMax = Style(
$box.height(100),
$flex.gap(20),
$flex.mainAxisAlignment.end(),
$flex.mainAxisSize.max(),
);

Style boxW100green = Style(
$box.color.green(),
$box.width(100),
);

Style boxW100red = Style(
$box.color.red(),
$box.width(100),
);

Those are styles from the three above small examples. Imagine what we will have after coding the whole app with this approach. We will have a design system. 😀

Extracting styles vs extracting components

By not providing a way to separate styles from widgets, Flutter forces us to create a lot of custom components. It is fine. And sometimes, it makes more sense to extract a whole component.

But sometimes it doesn’t. Mix doesn’t prevent us from creating custom components. Opposite, it makes it easier. However, in separating the style from the widget, Mix has no alternatives.

Limited number of styled widgets

Since Mix provides a limited (7) number of styled widgets, developers who use it (just my guess) tend to use them a lot to the detriment of others. It can be seen as a flaw, but my perception is that it is an advantage. Flutter has way too many widgets.

Conclusion

As I said, I see the Mix as a God sent package and plan to use it every time, everywhere. But it is the kind of thing that I cannot even recommend. You should try and decide for yourself.

Thank you for reading!

Yuri Novicow

Written by Yuri Novicow

Writes about everything. Differently.

Comments