exui 0.0.21
exui: ^0.0.21 copied to clipboard
Build your UI faster. No boilerplate, no dependencies—just powerful widget extensions.
Everything your widgets wish they had.
Want to 10× your Flutter UI development speed?
Useexui
. It’s the fastest way to build clean, maintainable UIs, no wrappers, no boilerplate.
Stop wasting time on widget nesting and boilerplate. exui
is a modern, zero-dependency Flutter extension library that makes your UI code faster, cleaner, and more expressive. It provides expressive, chainable extensions for every single Flutter widget—with no reliance on Material, Cupertino, or external libraries. Just pure Dart and Flutter, designed to work seamlessly in any project.
✅ Features #
- Extensions — for all Flutter widgets.
- Lightweight and efficient — wraps existing widgets without creating new classes.
- Actively maintained — Production-ready and continuously evolving.
- Zero dependencies - Pure Dart. No bloat. Add it to any project safely.
- Exceptional documentation — every extension is well documented with clear examples and fast navigation.
- Gesture extensions —
.onTap
,.onLongPress
,.detectGestures
, and more! - Layout shorthands —
.paddingAll
,.centered
,.expanded
,.sizedBox
, and more! - Styling utilities —
.backgroundColor
,.rounded
,.border
,.blur
, and more!
✨ All exui
Extensions: #
exui
includes a focused set of pure Flutter extensions, no Material or Cupertino dependencies - so you stay in control of your widget tree and design system. This core library contains chainable, declarative enhancements for layout, styling, interaction, and more. Each section below links to detailed documentation for a specific extension group.
- 📝
text()
— Convert Strings toText
Widgets - 🎛️
text.styled()
— Style and EnhanceText
Widgets - 👁️
visible
— Conditional Visibility for Widgets - 🌫️
opacity
— Control Widget Transparency - 🔣
icon
— Quickly Create and Style Icons - 📏
padding
— Add Padding to Any Widget - ➖
margin
— Add Outer Spacing Around Widgets - 🎯
center
— Center Your Widget with Optional Factors - 📐
align
— Position a Widget Precisely - 📍
positioned
— Position Widgets Inside a Stack - ↔️
expanded
— Make Widgets Fill Available Space - 🧬
flex
— Flexible Layouts with Fine-Tuned Control - 🔳
intrinsic
— Size Widgets to Their Natural Dimensions - 🧱
row
/column
— Instantly Wrap Widgets in Flex Layouts - 🧊
stack
— Overlay Widgets with Full Stack Control
More sections coming soon: layout, gestures, containers, spacing, animation, and more.
Additional Sections
📦 exui
Libraries #
exui
is built on pure Flutter (flutter/widgets.dart
) and avoids bundling unnecessary Material or Cupertino designs by default. For convenience, optional libraries are provided for those who want seamless integration with Flutter’s built-in design systems.
Library | Description | Link |
---|---|---|
exui/exui.dart |
Core extensions for pure Flutter. Lightweight and universal. | See details → |
exui/material.dart |
Adds extensions tailored to Material widgets and components. | See details → |
exui/cupertino.dart |
Adds extensions for Cupertino widgets and iOS-style components. | See details → |
exui
Vision #
What if every widget in your Flutter app could instantly do more, with less code?
That’s the bold vision behind exui
: to radically streamline UI development by extending every core Flutter widget with powerful, chainable, and expressive enhancements. No wrappers. No boilerplate. Just pure Flutter.
While most packages offer a handful of helpers or rely on custom widget trees, exui
takes a more ambitious approach:
A zero-dependency extension library with over 200 chainable utilities—designed to accelerate development, reduce clutter, and bring elegance to every line of UI code.
Whether you're prototyping ideas or building production-grade applications, exui
helps you move faster without sacrificing clarity or control.
"Click me"
.text()
.paddingAll(12)
.redBox()
.clipCircular()
.onTap(() => print("Tapped!"));
Each .text()
, .marginAll()
, or .icon()
you use replaces multiple layers of nested widgets with a single, readable chain. Multiply that across an entire app—and the productivity gains are exponential.
Without exui
#
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.pages),
label: 'Page 2',
),
With exui
#
Icons.home.icon().bottomNavigationItem('Page 1'),
Icons.pages.icon().bottomNavigationItem('Page 2'),
⚡ Stop wasting time on verbose nesting and boilerplate. ✨ Start composing clean, maintainable UIs with ease.
This isn’t just a utility library. It’s a declarative layer on top of Flutter—one that feels native, scales cleanly, and fits seamlessly into any project.
Welcome to exui
.
📝 text
— Turn Any String into a Text Widget #
Effortlessly convert a String
into a fully configurable Text
widget. The .text()
and .styledText()
extensions make your UI code clean, readable, and expressive — no more boilerplate, no more clutter.
.text({...})
— Create aText
widget with any nativeText
constructor parameters..styledText({...})
— Configure fullTextStyle
in one place: font, color, spacing, shadows, decoration, and more.
Both methods return a standard Flutter Text
widget — no wrappers, no magic.
🔹 Basic Text
"Hello world".text(); // same as Text("Hello world");
Text("Hello world"); // same as "Hello world".text();
🔹 Styled Text with Alignment
"Hello exui".text(
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
);
Text(
"Hello exui",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
);
🔹 Rich Styling in One Call
"Stylish!".styledText(
fontSize: 24,
fontWeight: FontWeight.w600,
color: Colors.purple,
);
Text(
"Stylish!",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w600,
color: Colors.purple,
),
);
⤴️ Back → All exui
Extensions
🎛️ text.styled()
— Modify and Style Text
Widgets Easily #
Powerfully enhance your Text
widgets with dozens of chainable extensions. Control alignment, overflow, semantics, and apply fine-grained styling—without verbose TextStyle
blocks.
These extensions are non-intrusive, composable, and maintain the immutability of the original widget.
📐 Layout & Metadata Modifiers
textAlign(...)
textDirection(...)
locale(...)
softWrap(...)
overflow(...)
maxLines(...)
semanticsLabel(...)
widthBasis(...)
heightBehavior(...)
selectionColor(...)
strutStyle(...)
textScaler(...)
🎨 Style Extensions
Apply full or partial TextStyle
changes with expressive one-liners:
fontSize(...)
fontWeight(...)
fontStyle(...)
letterSpacing(...)
wordSpacing(...)
height(...)
foreground(...)
/background(...)
shadows(...)
fontFeatures(...)
/fontVariations(...)
decoration(...)
decorationColor(...)
decorationStyle(...)
decorationThickness(...)
fontFamily(...)
/fontFamilyFallback(...)
leadingDistribution(...)
debugLabel(...)
⚡ Expressive Shortcuts
Use simple methods for common typography tasks:
bold()
italic()
underline()
strikethrough()
boldItalic()
boldUnderline()
boldStrikethrough()
🧪 Example
"Hello World"
.text()
.fontSize(20)
.boldItalic()
.textAlign(TextAlign.center)
.maxLines(2)
.overflow(TextOverflow.ellipsis);
Or, apply full styling in one go:
"Sale!"
.text()
.styled(
fontSize: 24,
fontWeight: FontWeight.w900,
decoration: TextDecoration.lineThrough,
color: Colors.red,
);
⤴️ Back → All exui
Extensions
👁️ visible
— Conditional Visibility for Widgets #
Simplify visibility logic in your widget tree with expressive, chainable methods. These extensions replace repetitive ternary conditions and help keep your UI code declarative and clean.
visibleIf(bool)
— Show this widget only if the condition istrue
; otherwise returns an empty box.visibleIfNot(bool)
— Inverse ofvisibleIf
.visibleIfNull(Object?)
— Show this widget only if the given value isnull
.visibleIfNotNull(Object?)
— Show this widget only if the given value is notnull
.hide()
— Always returns an empty widget (SizedBox.shrink()
).invisible()
— Alias ofhide()
for readability.boxShrink()
— ReturnsSizedBox.shrink()
directly.
All methods return valid widgets and are safe to chain inside build methods.
🧪 Examples
"Welcome".text().visibleIf(isLoggedIn); // Show only if condition is true
"Not logged in".text().visibleIfNot(isLoggedIn); // Show only if condition is false
"Missing info".text().visibleIfNull(user); // Show only if value is null
"Edit profile".text().visibleIfNotNull(user); // Show only if value is not null
"Hidden message".text().hide(); // Always hidden
"Not visible".text().invisible(); // Same as hide(), for clarity
final emptyBox = "Unused".text().boxShrink(); // Returns an empty widget directly
💡 Why use this? Instead of writing:
condition ? MyWidget() : const SizedBox.shrink()
Just write:
MyWidget().visibleIf(condition)
🔒 These methods never break layout structure — they return a valid widget in all cases and help you write safer conditional UI.
⤴️ Back → All exui
Extensions
🌫️ opacity
— Control Widget Transparency #
Quickly apply opacity to any widget using clean, expressive methods. These extensions eliminate the need to wrap widgets manually in Opacity
and support percentage-based and common preset values.
opacity(double)
— Set widget transparency using a0.0–1.0
value.opacityPercent(double)
— Use percentage (0–100
) for readability.opacityHalf()
— Set opacity to 50%.opacityQuarter()
— Set opacity to 25%.
All methods return a wrapped Opacity
widget and are safe to chain with other extensions.
🧪 Examples
Set to 70%
visible
"Hello".text().opacity(0.7);
Set to 40%
using percent
"Faded".text().opacityPercent(40);
"50/50".text().opacityHalf(); // Half visible (0.5)
"Subtle".text().opacityQuarter(); // Quarter visible (0.25)
💡 Instead of writing:
Opacity( opacity: value, child: MyWidget(), )
Just write:
MyWidget().opacity(value)
Use
.opacityPercent()
when working with designer specs or to make your code more intuitive at a glance.
⤴️ Back → All exui
Extensions
🔣 icon
— Quickly Create and Style Icons #
Easily create and customize Icon
widgets from an IconData
, or update existing Icon
instances with expressive, chainable methods. These extensions support all styling parameters available on Flutter's Icon
.
🧩 On IconData
icon({...})
— Create anIcon
fromIconData
with full styling options.iconSized(double)
— Shorthand for setting size.iconFilled(double)
— Set the fill level (for Material symbols).iconColored(Color)
— Apply color.
🧩 On Icon
.sized(double)
— Change icon size..filled(double)
— Set fill level..weight(double)
/.grade(double)
/.opticalSize(double)
— Fine-tune variable font icons..colored(Color)
— Change icon color..shadowed(List<Shadow>)
— Add text-style shadows..semanticLabeled(String)
— Set semantic label for accessibility..textDirectioned(TextDirection)
— Set directionality..applyTextScaling(bool)
— Respect or ignore text scaling..blendMode(BlendMode)
— Control blend behavior.
All methods return a new Icon
and preserve other properties unless overwritten.
🧪 Examples
Icons.settings.icon(size: 32, color: Colors.amber,);
// Create a red icon at 24px
Icons.home.iconSized(24).colored(Colors.red);
// Create and fill a Material symbol icon
Icons.favorite.iconFilled(1.0);
// Chain multiple style changes
Icons.star.icon().sized(32).filled(0.8).colored(Colors.amber);
💡 Instead of:
Icon( Icons.star, size: 32, color: Colors.amber, fill: 0.8, )
Just write:
Icons.star.icon(size: 32, color: Colors.amber, fill: 0.8)
⤴️ Back → All exui
Extensions
📏 padding
— Add Padding to Any Widget #
Apply padding effortlessly with readable, chainable methods. These extensions wrap your widget in a Padding
widget using concise, expressive syntax.
padding(EdgeInsets)
— Use anyEdgeInsets
object directly.paddingAll(double)
— Uniform padding on all sides.paddingOnly({left, top, right, bottom})
— Custom padding per side.paddingSymmetric({horizontal, vertical})
— Padding for x/y axes.paddingHorizontal(double)
— Shorthand for horizontal-only padding.paddingVertical(double)
— Shorthand for vertical-only padding.- Per-side utilities:
paddingLeft(double)
paddingRight(double)
paddingTop(double)
paddingBottom(double)
All methods return a wrapped Padding
widget and can be freely chained with other extensions.
🧪 Examples
// 12px padding on all sides
"Hello".text().paddingAll(12);
// 16px left and right, 8px top and bottom
"Box".text().paddingSymmetric(horizontal: 16, vertical: 8);
// 10px padding only on the left
"Back".text().paddingLeft(10);
// Custom per-side padding
"Margin".text().paddingOnly(left: 8, top: 4, bottom: 12);
💡 Why use this? Instead of writing:
Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: MyWidget(), )
Just write:
MyWidget().paddingHorizontal(16)
⤴️ Back → All exui
Extensions
➖ margin
— Add Outer Spacing Around Widgets #
Add clean, configurable margins around any widget with chainable extensions. These methods wrap the widget in a Container
with margin
, avoiding cluttered layout nesting and improving code clarity.
margin(EdgeInsets)
— Use anyEdgeInsets
object directly.marginAll(double)
— Equal margin on all sides.marginOnly({left, top, right, bottom})
— Custom margin per side.marginSymmetric({horizontal, vertical})
— Horizontal & vertical margin.marginHorizontal(double)
— Shorthand for horizontal-only margin.marginVertical(double)
— Shorthand for vertical-only margin.- One-sided margin helpers:
marginLeft(double)
marginRight(double)
marginTop(double)
marginBottom(double)
All methods return a wrapped Container
and can be freely chained with other extensions.
🧪 Examples
// 16px margin on all sides
"Card".text().marginAll(16);
// 24px horizontal, 12px vertical
"Tile".text().marginSymmetric(horizontal: 24, vertical: 12);
// 8px margin only on top
"Header".text().marginTop(8);
// Custom side-by-side margin
"Box".text().marginOnly(left: 6, bottom: 10);
💡 Why use this? Instead of writing:
Container( margin: EdgeInsets.only(left: 8, top: 4), child: MyWidget(), )
Just write:
MyWidget().marginOnly(left: 8, top: 4)
⚖️ Margin vs Padding
Usepadding
to add spacing inside a widget's boundary — like space around text in a button.
Usemargin
to add spacing outside a widget — like separating it from other widgets.🟢 For most layout needs,
padding
is the preferred and safer default. Usemargin
when you need to push the widget away from surrounding elements, but be cautious with nesting to avoid layout issues.
⤴️ Back → All exui
Extensions
🎯 center
— Center Your Widget with Optional Factors #
Effortlessly center any widget with precise control over layout behavior. These extensions wrap your widget in a Center
and offer intuitive access to widthFactor
and heightFactor
when needed.
center({widthFactor, heightFactor})
— Fully customizable centering.centerWidth(double?)
— Center with horizontal shrink-wrapping only.centerHeight(double?)
— Center with vertical shrink-wrapping only.
All methods return a Center
widget and can be seamlessly chained with other extensions.
🧪 Examples
// Center without size constraints
"Centered".text().center();
// Center and shrink-wrap width only
"Shrink X".text().centerWidth(1);
// Center and shrink-wrap height only
"Shrink Y".text().centerHeight(1);
// Fully customized centering
"Shrink both".text().center(widthFactor: 0.8, heightFactor: 0.5);
💡 Instead of writing:
Center( widthFactor: 1, child: MyWidget(), )
Just write:
MyWidget().centerWidth(1)
⤴️ Back → All exui
Extensions
📐 align
— Position a Widget Precisely #
Align your widget anywhere inside its parent with expressive, chainable methods. These extensions wrap your widget in an Align
widget, giving you fine-grained control over its position.
align({ alignment, widthFactor, heightFactor })
— Custom alignment with optional size factors.alignCenter()
— Center of parent (default).- Top alignment:
alignTopLeft()
alignTopCenter()
alignTopRight()
- Center alignment:
alignCenterLeft()
alignCenterRight()
- Bottom alignment:
alignBottomLeft()
alignBottomCenter()
alignBottomRight()
All methods return an Align
widget and are safe to use inside any layout context.
🧪 Examples
// Center the widget (default)
"Centered".text().alignCenter();
// Align to bottom-right
"Download".text().alignBottomRight();
// Top-left aligned with width factor
"Logo".text().alignTopLeft().align(widthFactor: 2);
💡 Instead of writing:
Align( alignment: Alignment.bottomRight, child: MyWidget(), )
Just write:
MyWidget().alignBottomRight()
🧭 When to use
positioned
vsaligned
Use.positioned()
inside aStack
when you need precise pixel placement (top
,left
, etc.).
Use.aligned()
when you want relative alignment (like centering) within any parent.⚠️
.positioned()
only works inside aStack
..aligned()
works almost anywhere.
⤴️ Back → All exui
Extensions
📍 positioned
— Position Widgets Inside a Stack #
Easily wrap widgets with Positioned
using expressive, side-specific methods. These extensions let you declare layout constraints cleanly inside a Stack
without cluttering your build logic.
positioned({left, top, right, bottom, width, height})
— FullPositioned
wrapper with optional constraints.positionedTop(double)
— Position from top.positionedBottom(double)
— Position from bottom.positionedLeft(double)
— Position from left.positionedRight(double)
— Position from right.positionedWidth(double)
— Set width directly.positionedHeight(double)
— Set height directly.
All methods return a Positioned
widget and are designed to be composed fluently.
🧪 Examples
// Position 10px from top and left
"Hello".text().positioned(top: 10, left: 10);
// Set only the width, auto-positioned
"Wide".text().positionedWidth(200);
// Position from bottom with fixed height
"Footer".text().positionedBottom(0).positionedHeight(60);
// Custom full placement
"Box"
.text()
.positioned(top: 12, right: 16, width: 150);
💡 Instead of writing:
Positioned( top: 12, right: 16, width: 150, child: MyWidget(), )
Just write:
MyWidget().positioned(top: 12, right: 16, width: 150)
🧭 When to use
positioned
vsaligned
Use.positioned()
inside aStack
when you need precise pixel placement (top
,left
, etc.).
Use.aligned()
when you want relative alignment (like centering) within any parent.⚠️
.positioned()
only works inside aStack
..aligned()
works almost anywhere.
⤴️ Back → All exui
Extensions
↔️ expanded
— Make Widgets Fill Available Space #
Add layout flexibility with zero boilerplate. These extensions wrap your widget in an Expanded
, allowing you to quickly define how much space it should take relative to its siblings.
expandedFlex([int flex = 1])
— Wraps the widget inExpanded
with an optionalflex
.expanded
— Shorthand forExpanded(flex: 1)
.
- Predefined shorthand getters for fixed flex values:
expanded2
,expanded3
,expanded4
,expanded5
,expanded6
,expanded7
,expanded8
Use them in Row
, Column
, or Flex
to control space distribution without nesting or repetition.
🧪 Examples
// Flex: 1 (default)
"Item".text().expanded;
// Flex: 2
"Item".text().expanded2;
// Flex: 5
"Item".text().expandedFlex(5);
💡 Instead of writing:
Expanded( flex: 3, child: MyWidget(), )
Just write:
MyWidget().expanded3
⤴️ Back → All exui
Extensions
🧬 flex
— Flexible Layouts with Fine-Tuned Control #
Wrap any widget in a Flexible
with full control over flex
and fit
. These extensions reduce verbosity while giving you precise layout behavior in Row
, Column
, or Flex
widgets.
flex({int flex, FlexFit fit})
— Custom flex and fit values (default:flex: 1
,fit: FlexFit.loose
)flexLoose(int)
— Loose-fit shortcutflexTight(int)
— Tight-fit shortcut
- Predefined
flex
shortcuts (default fit:loose
):
flex2()
,flex3()
,flex4()
,flex5()
,flex6()
,flex7()
,flex8()
All methods return a Flexible
widget and are safe to chain with other layout or styling extensions.
🧪 Examples
// Default: flex 1, loose fit
"Flexible".text().flex();
// Predefined: flex 3, loose fit
"Main".text().flex3();
// Custom: flex 4, tight fit
"Filled".text().flex(flex: 4, fit: FlexFit.tight);
// Loose-fit with custom flex
"Side".text().flexLoose(2);
// Tight-fit with custom flex
"Primary".text().flexTight(6);
💡 Instead of writing:
Flexible( flex: 3, fit: FlexFit.tight, child: MyWidget(), )
Just write:
MyWidget().flexTight(3)
⤴️ Back → All exui
Extensions
🔳 intrinsic
— Size Widgets to Their Natural Dimensions #
Wrap widgets with IntrinsicWidth
or IntrinsicHeight
to size them based on their intrinsic (natural) dimensions. These extensions make it easy to apply intrinsic sizing with expressive, chainable syntax.
intrinsicHeight()
— Wraps inIntrinsicHeight
.intrinsicWidth()
— Wraps inIntrinsicWidth
with default options.intrinsicWidthWith({stepWidth, stepHeight})
— Custom step values.intrinsicWidthStepWidth(double)
— SetstepWidth
only.intrinsicWidthStepHeight(double)
— SetstepHeight
only.
All methods return intrinsic wrappers that measure content and size accordingly—ideal for fine-tuned layout control.
🧪 Examples
// Wrap with IntrinsicHeight
MyWidget().intrinsicHeight();
// Wrap with IntrinsicWidth (default)
MyWidget().intrinsicWidth();
// Set stepWidth to 100
MyWidget().intrinsicWidthStepWidth(100);
// Set both stepWidth and stepHeight
MyWidget().intrinsicWidthWith(
stepWidth: 80,
stepHeight: 40,
);
💡 Instead of writing:
IntrinsicWidth( stepHeight: 40, child: MyWidget(), )
Just write:
MyWidget().intrinsicWidthStepHeight(40)
⚠️ Use intrinsic widgets with care — they can be expensive to layout and should only be used when needed for dynamic content sizing.
⤴️ Back → All exui
Extensions
🧱 row
/ column
— Instantly Wrap Widgets in Flex Layouts #
Effortlessly create Row
and Column
layouts with readable, inline extensions. Whether you're working with a single widget or a whole list, these helpers make layout structure fast, chainable, and more expressive.
.row()
/.column()
— Wrap a single widget in aRow
orColumn
.[].row()
/[].column()
— Wrap a list of widgets.
- ✅ Fully supports all
Row
andColumn
parameters, including:
spacing
,mainAxisAlignment
,crossAxisAlignment
, and more.
🧪 Examples
// Single widget inside a Row
"Item".text().row();
// Two widgets in a Row with spacing
[
"A".text(),
"B".text(),
].row(spacing: 12);
// Vertical layout with alignment and spacing
[
Icons.star.icon(),
"Favorite".text(),
].column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 8,
);
// Center a single widget vertically
"Alone".text().column(
mainAxisAlignment: MainAxisAlignment.center,
);
💡 Instead of writing:
Column( spacing: 8, children: [ Text("Hello"), Icon(Icons.star), ], )
Just write:
[ "Hello".text(), Icons.star.icon(), ].column(spacing: 8)
⤴️ Back → All exui
Extensions
🧊 stack
— Overlay Widgets with Full Stack Control #
Build layered UI structures with intuitive, chainable extensions. These methods let you create Stack
layouts directly from a List<Widget>
and configure fit modes easily with named variants.
stack()
— Wrap a list in a standardStack
(StackFit.loose
by default).stackLoose()
— Equivalent toStackFit.loose
(default).stackExpand()
— Children fill the available space (StackFit.expand
).stackPassthrough()
— Children keep their intrinsic size (StackFit.passthrough
).
✅ Fully supports all native Stack
parameters:
alignment
, textDirection
, fit
, and clipBehavior
.
🧪 Examples
// Default stack with loose fit
[
"Base".text(),
"Overlay".text().positionedTop(0),
].stack();
// Stack with expanded fit
[
Image.asset("bg.png"),
"Play".text().positionedBottom(0),
].stackExpand();
// Stack with passthrough sizing
[
Icons.circle.icon(), // same as Icon(Icons.circle)
Icon(Icons.star),
].stackPassthrough();
// Stack with custom alignment and clip behavior
[
...someWidgets,
].stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
);
// A single widget wrapped in a Stack
"Overlay".text().stack();
💡 Instead of writing:
Stack( fit: StackFit.expand, alignment: Alignment.center, children: [ ... ], )
Just write:
[...].stackExpand(alignment: Alignment.center)
⤴️ Back → All exui
Extensions