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

Directives

Directives transform values (text, numbers) when a style is resolved. Unlike modifiers (which wrap widgets), directives transform the underlying data values.

// The text "hello world" is transformed to "HELLO WORLD" at build time StyledText( 'hello world', style: TextStyler().uppercase(), )

Directives can be chained. Number directives operate on Prop<T> values:

// Chain: multiply by 2, then add 5, then clamp between 0-30 final scaled = Prop.value(10.0).multiply(2).add(5).clamp(0, 30); // Result: (10 * 2) + 5 = 25, clamped to [0, 30] = 25

Text Directives

Transform strings in StyledText widgets:

Available Text Directives

MethodDescriptionExample InputResult
.uppercase()Converts all characters to uppercase”hello world""HELLO WORLD”
.lowercase()Converts all characters to lowercase”Hello World""hello world”
.capitalize()Capitalizes the first letter of the string and lowercases the rest”hello World""Hello world”
.titlecase()Capitalizes the first letter of each word”hello world""Hello World”
.sentencecase()Capitalizes the first letter of the first word”hello world""Hello world”
Resolving preview metadata...

Usage Examples

import 'package:flutter/material.dart'; import 'package:mix/mix.dart'; // Uppercase text StyledText( 'welcome back', style: TextStyler().uppercase().fontSize(18), ) // Title case for headings StyledText( 'user profile settings', style: TextStyler().titlecase().fontWeight(.bold), ) // Sentence case for descriptions StyledText( 'click here to continue', style: TextStyler().sentencecase().color(Colors.grey), )

Number Directives

Transform numeric values (width, height, padding, font sizes):

Available Number Directives

MethodDescriptionExample
.multiply(factor)Multiplies by a factorProp.value(10).multiply(2) → 20
.add(addend)Adds a valueProp.value(10).add(5) → 15
.subtract(value)Subtracts a valueProp.value(10).subtract(3) → 7
.divide(divisor)Divides by a valueProp.value(10).divide(2) → 5
.clamp(min, max)Constrains between boundsProp.value(25).clamp(0, 20) → 20
.abs()Returns absolute valueProp.value(-10).abs() → 10
.round()Rounds to nearest integerProp.value(15.7).round() → 16
.floor()Rounds downProp.value(15.7).floor() → 15
.ceil()Rounds upProp.value(15.3).ceil() → 16
.scale(ratio)Alias for multiplyProp.value(10).scale(1.5) → 15

Usage Examples

import 'package:flutter/material.dart'; import 'package:mix/mix.dart'; // Dynamic sizing with tokens final $baseSize = DoubleToken('base.size'); // Use Prop.token() with number directives for token-based calculations final scaledSize = Prop.token($baseSize).multiply(2); final adjustedSize = Prop.token($baseSize).multiply(1.5); // Clamped responsive values final clampedPadding = Prop.value(16.0).clamp(8, 32); // Chaining multiple directives final computed = Prop.value(100.0).multiply(2).add(20).clamp(0, 300); // Result: (100 * 2) + 20 = 220, clamped to [0, 300] = 220

Division always returns a double in Dart. The divisor cannot be zero.

Creating Custom Directives

Extend Directive<T> to create application-specific transformations.

Text Directive Example

import 'package:mix/mix.dart'; /// Directive that reverses a string final class ReverseStringDirective extends Directive<String> { const ReverseStringDirective(); @override String apply(String value) => value.split('').reversed.join(); @override String get key => 'reverse'; @override bool operator ==(Object other) => identical(this, other) || other is ReverseStringDirective; @override int get hashCode => key.hashCode; } // Usage with TextStyler extension ReverseTextDirective on TextStyler { TextStyler reverse() { return merge( TextStyler(textDirectives: [const ReverseStringDirective()]), ); } } // Apply the custom directive StyledText( 'hello', style: TextStyler().reverse(), // Displays "olleh" )

Number Directive Example

import 'package:mix/mix.dart'; /// Directive that negates a number final class NegateNumberDirective extends NumberDirective { const NegateNumberDirective(); @override num apply(num value) => -value; @override String get key => 'number_negate'; @override bool operator ==(Object other) => identical(this, other) || other is NegateNumberDirective; @override int get hashCode => key.hashCode; } // Extension to make it easy to use extension NegateNumberPropExt<T extends num> on Prop<T> { Prop<num> negate() { return directives([const NegateNumberDirective()]); } }

Best Practices

  • Use text directives for consistent case formatting
  • Use number directives for proportional sizing with tokens
  • Color directives (DarkenColorDirective, LightenColorDirective, TintColorDirective, ShadeColorDirective, etc.) are available for programmatic color transformations via Prop.directives([...])
  • Keep directives simple—complex logic belongs elsewhere

Chaining order matters:

Prop.value(10).add(5).multiply(2) // (10 + 5) * 2 = 30 Prop.value(10).multiply(2).add(5) // (10 * 2) + 5 = 25