mix_winds
mix_winds provides a Tailwind CSS-like utility syntax for styling Flutter widgets using Mix. Write class names such as flex, gap-4, and text-lg instead of composing stylers manually.
Treat this package as a proof of concept. The API is unstable and will change without notice.
This package was published as mix_tailwinds through 0.0.1-alpha.1 and is now mix_winds.
To migrate, rename the dependency and replace package:mix_tailwinds/mix_tailwinds.dart imports
with package:mix_winds/mix_winds.dart. No public API symbol changed.
Interactive Preview
TwScope is optional. The preview uses it to match Tailwind Preflight’s base typography across
the whole card. The utility helpers already fall back to TwConfig.standard() when no scope is
present, so ordinary div, p, and button calls do not require a wrapper.
The card alert above demonstrates gradients, glassmorphism, badges, hover states, and nested flex layouts. The lowercase helpers keep each class string beside its content, while button also provides native interaction and semantics:
import 'package:flutter/material.dart';
import 'package:mix_winds/mix_winds.dart';
class CardAlert extends StatelessWidget {
const CardAlert({super.key});
@override
Widget build(BuildContext context) {
return TwScope(
child: div(
'bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 p-6',
[
div(
'bg-white/10 border border-white/20 rounded-3xl p-6 shadow-2xl',
[
div('flex items-start gap-4', [
div(
'w-14 h-14 rounded-full bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center border-2 border-purple-400',
[span('text-white font-semibold text-lg', 'SM')],
),
div('flex-1 min-w-0', [
div('flex items-center gap-2 mb-1', [
h3(
'text-white font-semibold text-lg truncate',
'Sarah Mitchell',
),
span(
'px-2 py-0.5 bg-purple-500/30 text-purple-200 text-xs rounded-full font-medium',
'Admin',
),
]),
p(
'text-slate-300 text-sm mb-4',
'Your profile changes are ready to publish. Review and confirm to update your public information.',
),
div('bg-white/5 rounded-xl p-3 mb-4 border border-white/10', [
div('flex items-center gap-2 text-amber-300 text-sm', [
span('', '\u26A0'),
span('', 'This action cannot be undone'),
]),
]),
div('flex gap-3', [
button(
'flex flex-1 items-center justify-center rounded-xl border border-white/10 bg-white/10 px-4 py-2.5 font-medium text-white hover:border-white/20 hover:bg-white/20',
[span('', 'Cancel')],
onPressed: () {},
),
button(
'flex flex-1 items-center justify-center rounded-xl bg-gradient-to-r from-purple-500 to-pink-500 px-4 py-2.5 font-medium text-white shadow-lg hover:from-purple-400 hover:to-pink-400',
[span('', 'Save Changes')],
onPressed: () {},
),
]),
]),
]),
],
),
],
),
);
}
}Links
The following resources point to the package registry and source code:
Install
Install the current development version directly from the Mix repository. This follows the repository’s default branch without hardcoding a release number:
flutter pub add "mix_winds:{git:{url: https://github.com/btwld/mix.git, path: packages/mix_winds}}"The mix_winds name on pub.dev currently resolves to a placeholder package. Until a functional
release is published there, do not use the shorter flutter pub add mix_winds command.
The equivalent pubspec.yaml entry is:
dependencies:
mix_winds:
git:
url: https://github.com/btwld/mix.git
path: packages/mix_windsFor a reproducible application build, add a Git ref for a release tag or commit. Keep the unpinned form when the goal is always to follow the latest repository version.
Quick start
Import the package and use the lowercase helpers directly. The standard utility configuration works without any root wrapper:
import 'package:flutter/material.dart';
import 'package:mix_winds/mix_winds.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
body: Center(
child: div(
'flex flex-col gap-4 rounded-xl bg-white p-6 shadow-md',
[
h2('text-2xl font-bold text-gray-900', 'Hello mix_winds'),
p(
'text-sm text-gray-600',
'Utility-first styling powered by Mix.',
),
],
),
),
),
),
);
}This renders a white rounded card with a title and subtitle, using only class name strings.
Functional API
The class-first helpers are the cleanest API for most layouts. Every helper requires a class string; pass '' when an element has no utilities.
Each helper resolves the nearest TwConfig and otherwise uses TwConfig.standard(). Add TwScope only when the subtree needs Tailwind-compatible base typography, a custom configuration, extra Mix tokens, or custom modifier ordering.
| Helper | Purpose |
|---|---|
div(classes, [children]) | Container and layout element. Returns a Div. |
p(classes, text) | Block-level paragraph. Returns a P. |
span(classes, text) | Inline text. Returns a Span. |
h1 – h6(classes, text) | Semantic headings with no default visual styles, matching Tailwind Preflight. |
button(classes, children, onPressed: ...) | Native button interaction, states, and semantics. Returns a Button. |
twIcon(classes, icon) | Icon styled with utility classes. Returns a TwIcon. |
truncatedP(classes, text) | Truncated paragraph that applies flex-1 min-w-0. Returns a TruncatedP. |
Use the uppercase constructors when you need a const widget, key, custom configuration, diagnostics, a single child, or advanced button and focus options:
Div(
classNames: 'flex gap-4 unknown-class',
onDiagnostic: (diagnostic) {
debugPrint('${diagnostic.code}: ${diagnostic.token}');
},
children: [...],
)Supported utility classes
Layout
| Utility | Description |
|---|---|
flex | Enable flex layout |
flex-row, flex-col | Flex direction |
flex-wrap, flex-nowrap, flex-wrap-reverse | Flex wrap behavior |
flex-1, flex-auto, flex-initial, flex-none | Flex shorthand |
grow, grow-0, shrink, shrink-0 | Flex grow/shrink |
items-start, items-center, items-end, items-stretch, items-baseline | Cross-axis alignment |
justify-start, justify-center, justify-end, justify-between, justify-around, justify-evenly | Main-axis alignment |
self-auto, self-start, self-center, self-end, self-stretch | Self alignment |
hidden, block | Display mode |
overflow-hidden, overflow-visible, overflow-clip | Overflow behavior |
Spacing
| Utility | Scale |
|---|---|
p-*, px-*, py-*, pt-*, pr-*, pb-*, pl-* | Padding (0–96) |
m-*, mx-*, my-*, mt-*, mr-*, mb-*, ml-* | Margin (0–96, supports negative: -m-*) |
gap-*, gap-x-*, gap-y-* | Gap between flex children (0–96) |
Sizing
| Utility | Scale |
|---|---|
w-*, h-* | Width/height (0–96, plus full, screen, auto) |
min-w-*, min-h-*, max-w-*, max-h-* | Min/max constraints |
Fractional: w-1/2, h-1/3, w-2/5 | Percentage-based sizing |
Typography
| Utility | Description |
|---|---|
text-xs through text-9xl | Font size (12px–128px) |
font-thin through font-black | Font weight (100–900) |
text-left, text-center, text-right, text-justify, text-start, text-end | Text alignment |
uppercase, lowercase, capitalize | Text transform |
truncate | Text overflow ellipsis |
leading-none through leading-loose | Line height |
tracking-tighter through tracking-widest | Letter spacing |
Colors
| Utility | Description |
|---|---|
bg-* | Background color |
text-* | Text color |
Available color palettes: slate, gray, blue, purple, pink, red, amber, emerald, plus black, white, and transparent. Each palette includes shades from 50 to 950.
Borders
| Utility | Scale |
|---|---|
border-*, border-t-*, border-r-*, border-b-*, border-l-*, border-x-*, border-y-* | Border width (0, 1, 2, 4, 8) |
rounded-*, rounded-t-*, rounded-b-*, rounded-l-*, rounded-r-*, rounded-tl-*, rounded-tr-*, rounded-bl-*, rounded-br-* | Border radius (none–full) |
Effects
| Utility | Description |
|---|---|
shadow-none through shadow-2xl | Box shadow |
text-shadow-none through text-shadow-lg | Text shadow |
blur-none through blur-3xl | Blur filter |
Transforms
| Utility | Scale |
|---|---|
scale-* | Transform scale (0–1.5) |
rotate-* | Rotation (0–180°, supports negative: -rotate-*) |
translate-x-*, translate-y-* | Translation (supports negative) |
Animations
| Utility | Description |
|---|---|
transition, transition-all, transition-colors, transition-opacity, transition-shadow, transition-transform, transition-none | Transition properties |
duration-* | Animation duration (0–1000ms) |
delay-* | Animation delay (0–1000ms) |
ease-linear, ease-in, ease-out, ease-in-out | Easing curves |
Variants
Prefix any utility with a variant to apply it conditionally.
Responsive breakpoints
| Prefix | Min-width |
|---|---|
sm: | 640px |
md: | 768px |
lg: | 1024px |
xl: | 1280px |
2xl: | 1536px |
div('flex flex-col gap-4 md:flex-row', [...])Interaction states
| Prefix | Triggers when |
|---|---|
hover: | Pointer hovers over the widget |
active: | Widget is pressed |
focus: | Widget has focus |
disabled: | Widget is disabled |
group: | Parent group state |
group-hover: | Parent group is hovered |
button(
'rounded-lg bg-blue-600 px-4 py-2 text-white hover:bg-blue-700 active:bg-blue-800',
[span('', 'Click me')],
onPressed: () {},
)Theme variants
| Prefix | Applies when |
|---|---|
dark: | Dark theme is active |
light: | Light theme is active |
Composing variants
Combine multiple variant prefixes on a single token:
div('bg-white md:hover:bg-blue-500 dark:bg-gray-900')Special syntax
Arbitrary values
Use square brackets for values outside the default scale:
div('bg-[#FF0000] p-[24px] w-[100px]')Opacity modifiers
Append /<opacity> (0–100) to any color utility:
div('bg-white/50 text-black/75')Important flag
Prefix with ! to mark a utility as important (overrides other values during merge):
div('!font-bold')Negative values
Prefix with - for margin and transform utilities:
div('-mt-4 -translate-x-8')Defaults and typography configuration
TwScope is configuration, not a prerequisite for utility parsing. Use it when you want
mix_winds to own the subtree’s base typography instead of inheriting Flutter’s surrounding
DefaultTextStyle.
TwScope performs three jobs:
- It provides one
TwConfigto every descendant. Without it, each helper usesTwConfig.standard(). - It installs a
MixScopefor the preflight text token, optional Mix tokens, and modifier ordering. - It applies
TwTextDefaultsthroughTextScope, giving unqualified text a consistent font family, base size, weight, tracking, and line height.
In the card preview, the third job matters: labels such as Cancel intentionally omit a text-* size and inherit Tailwind’s 16px base typography. Without TwScope, the utility classes still work, but those unspecified text properties come from the surrounding Flutter app and the visual result can differ.
Configure typography through TwTextDefaults:
TwScope(
config: TwConfig.standard().copyWith(
textDefaults: TwTextDefaults(
fontFamily: 'Inter',
fontSize: 16,
lineHeight: 1.5,
letterSpacing: 0,
fontWeight: .w400,
),
),
child: MyApp(),
)Two built-in presets are available:
| Preset | Description |
|---|---|
TwTextDefaults.tailwindSans() | System sans-serif stack matching Tailwind’s default (used by TwConfig.standard()) |
TwTextDefaults.platformDefault() | Flutter’s platform-native font with no explicit font family |
Known limitations
The following features are parsed but not applied or have incomplete support:
- Percent-based sizing —
w-[50%]is parsed but not applied. Use fractional syntax (w-1/2) instead. - Fractional translate —
translate-x-1/2is not supported. Use pixel values. - Fractional basis —
basis-1/2is not supported. Use spacing scale values or explicit sizing.
Related docs
- Introduction — what Mix is and why it exists
- Styling — the Styler pattern that
mix_windsbuilds on - Dynamic Styling — variants (hover, dark mode) used by tailwind prefixes
- Design Tokens — token system that powers
TwScopeconfiguration