An expressive way to effortlessly build design systems in Flutter

mix

An expressive way to effortlessly build design systems in Flutter. Mix offers primitive building blocks to help developers and designers create beautiful and consistent UI.

Important

Mix is currently being used internally to build design systems in Flutter.
However, it is still in the experimental development stages.
Major APIs are expected to change until the 1.0 release.

Motivation & Goals

  • Creating consistent custom (non-material) UI in Flutter is difficult
  • Maintaining a design system is much harder than building it.
  • Visual attributes should be defined outside of a widget by a composable API shared across the design system.
  • Style consistently with a global theme
  • Respond to changing requirements quickly
  • Create adaptive layouts with ease
  • Material Theme compatible

Principles

  • Development efficiency is gained by the ease of use, consistency, and reusability, not coding speed.
  • Abstract Flutter API, and not modify its behavior.
  • Composability should be a priority. Mixes, Attributes, Widgets, etc.
  • Designer friendly (use simple standard semantics when possible)

Examples

Simple Mix

final squareMix = Mix(h(150), w(150));

Box(
    squareMix,
    child: Text('Square'),
);

// You can also use the following:
// This way has some downsides. More info soon...
squareMix.box(child:Text('Square'));

Composability

Extend Mixes

final cardMix = squareMix.mix(p(20), rounded(20), bgColor(Colors.white));

Override Mixes

final redCardMix = cardMix.mix(bgColor(Colors.red));

Combine Mixes

final elevationMix = Mix(
    shadowColor(Colors.black12),
    shadowBlur(4),
    shadowOffset(0, 2),
);

Box(
    Mix.combine(cardMix, elevationMix),
    child: Text('Card With Shadow'),
);

Conditional Mixes

// If you wan't to change the Mix depending on a condition
final conditonalMix = Mix.chooser(isSelected, dynamicMix, redCardMix);

Dynamic Mixes

If you want the card to change color when in dark mode you can use a dynamic attribute.

final dynamicMix = cardMix.mix(dark(bgColor(Colors.black)));

/// Now, when the app is on dark mode the card color will change to `black`.
Box(
    dynamicMix,
    child: Text('Dynamic Card'),
);

You can also leverage media query context values

final flexMix = Mix(gap(20), mainAxis.center);

// Adaptive gutter for your flex widgets using media query
final adaptiveFlexMix = flexMix.mix(
  mq.xs(gap(10)),
  mq.sm(gap(15)),
  mq.lg(gap(40)),
);

APIs

Documentation is currently in progress. For now you can find some of the available utilities here

Concepts

Here are some high-level concepts to understand how Mix works and to allow for you to get started.

Attributes

These are the features or characteristics of certain widgets. Most attributes map out to layout, visual widgets, or widget styling itself. Attributes are primitives which get translated into their Flutter API.

Dynamic Attributes

Attributes can be dynamic, which means they only are applied in case a condition is met. This allows for the creation of Atributes that can be used depending on the widget's BuildContext.

Utilities

These are classes whose primary purpose is providing a better API for Attributes.

Not required for building Mixes; however, make a cleaner API possible and overall better development experience.

Mixes

Combination or mix of Attributes. Mixes are passed to Widgets and translated into the widget's properties.

Mixes can be reused across multiple widgets and also combine, extended, and overridden.

Mixer Widgets

These are the building block for your design system. You can easily build new widgets that take advantage of Mixes; however, there are some primitives provided.

Box

Similar to a Container with some slight adjustments for a better development experience.

Flexbox

The equivalent of the Flex widgets (Flex, Row, Column). Allow for the use of flex Attributes, and wrap them in a Box to use box attributes for composability.

ColumnBox

The equivalent of the Column widget. Allows you to use Mix attributes to style and build custom text widgets. It is an abstraction of Flexbox, so it will also accept Box attributes.

RowBox

The equivalent of the Row widget. Allows you to use Mix attributes to style and build custom text widgets. It is an abstraction of Flexbox, so it will also accept Box attributes.

TextMix

The equivalent of the Text widget. Allows you to use Mix attributes to style and build custom text widgets.

IconMix

The equivlent to the Icon widget. Allows to use Mix attributes to style and build custom icon widgets.

GitHub

https://github.com/leoafarias/mix