Skip to Content
Mix 2.0 is in development! You can access the Mix 1.0 docs here.
DocsOverviewIntroduction

Introduction

Mix is a styling system for Flutter that separates style definitions from widget structure. It provides a composable, type-safe way to define and apply styles.

  • Compose, merge, and apply styles across widgets
  • Write maintainable styling definitions separate from widget code
  • Apply styles conditionally based on BuildContext

Why Mix?

Mix provides utility functions for intuitive, composable styling that stays consistent across widgets and files—without being tied to Material Design.

Goals

  • Define styles outside widgets while retaining BuildContext access
  • Reuse style definitions across your app for consistency
  • Adapt styles conditionally using variants (hover, dark mode, breakpoints)
  • Type-safe composability using Dart’s type system

Guiding Principles

  • Simple: Thin layer over Flutter—widgets remain compatible and predictable
  • Consistent: API mirrors Flutter naming conventions
  • Composable: Build complex styles from simple, reusable pieces
  • Extensible: Override and extend utilities to fit your needs

Understanding the Styler Pattern

Mix provides two constructor patterns for Styler classes. Understanding when to use each is key to effective styling:

Fluent API: BoxStyler()

The default constructor provides a fluent API for chaining style properties:

final style = BoxStyler() .color(Colors.blue) .paddingAll(16) .borderRounded(8);

Use this pattern when:

  • Defining styles with direct values
  • Chaining multiple style properties together
  • Building most common styling use cases

Prop-Based API: BoxStyler.create()

The .create() constructor accepts Prop<T> parameters for advanced composition:

final style = BoxStyler.create( color: Prop.token($primaryColor), padding: Prop.value(EdgeInsets.all(16)), );

Use this pattern when:

  • Working with design tokens (Prop.token())
  • Applying number directives like multiply() or clamp()
  • Building custom widget libraries that need deferred resolution

How Prop<T> Works

Prop<T> is a wrapper that enables deferred value resolution. It can hold:

  • Direct values: Prop.value(Colors.blue)
  • Token references: Prop.token($primaryColor)
  • Directives: Prop.value(16.0).multiply(2).clamp(0, 50)

Values are resolved when the style is applied, allowing tokens to be looked up from MixScope and directives to transform values at build time.

Key Features

Powerful Styling API:

Define styles using a fluent, chainable API with Styler classes:

import 'package:flutter/material.dart'; import 'package:mix/mix.dart'; final boxStyle = BoxStyler() .height(100) .width(100) .color(Colors.purple) .borderRounded(10); final textStyle = TextStyler() .fontSize(20) .fontWeight(FontWeight.bold) .color(Colors.black);

Learn more about styling

Dynamic Styling

Styles can adapt to interactions and context (hover, press, dark mode):

final buttonStyle = BoxStyler() .height(50) .borderRounded(25) .color(Colors.blue) .onHovered(BoxStyler().color(Colors.blue.shade700)) .onDark(BoxStyler().color(Colors.blue.shade200));

Learn more about Dynamic Styling

Animation Support:

Mix supports implicit animations, phase animations (multi-step sequences), and keyframe animations. Learn more in the Animations Guide.

Design Tokens and Theming:

Define reusable design tokens for colors, spacing, radii, and more:

final $primaryColor = ColorToken('primary'); final $borderRadius = RadiusToken('borderRadius'); final tokenDefinitions = <MixToken, Object>{ $primaryColor: Colors.blue, $borderRadius: Radius.circular(8), }; final tokenStyle = BoxStyler() .color($primaryColor()) .width(100) .height(100) .borderRadius(BorderRadiusGeometryMix.all($borderRadius())); // Set the tokens in the MixScope MixScope( tokens: tokenDefinitions, child: MyApp(), );

Learn more about Design Tokens and Theming