Awaitware UI Utilities
Powerful Flutter UI Toolkit — Write beautiful, maintainable Flutter UIs with 1500+ chainable extension methods.
Build stunning UIs faster with intuitive, chainable methods that work perfectly with Flutter's widget system. A utility-first approach to Flutter development.
Table of Contents
- Installation
- Quick Start
- Why Awaitware UI Utilities?
- Features Overview
- v4.0 — Navigation & Advanced
- v3.0 — UI Components
- v2.0 — Advanced Features
- v1.0 — Core Utilities
- Custom Values
- Responsive Design
- Gradients
- Animations
- Dark Mode
- Button, Card & Typography Presets
- Form Inputs
- Images
- Shimmer & Skeleton Loading
- Badges & Chips
- Avatars
- Dialogs & Bottom Sheets
- List Tiles
- Dividers
- Clip Shapes
- Scroll Effects
- Tooltips & Popups
- Accessibility
- Navigation
- Slivers
- Tables
- Stepper & Timeline
- Drag & Drop
- Internationalization (i18n / RTL)
- Platform Adaptive
- The
awHelper Class - Gesture Extensions
- Real-World Examples
- Documentation
- Contributing
- License
Installation
Add to your pubspec.yaml:
dependencies:
awaitware_ui_utilities: ^4.0.0
Then run:
flutter pub get
Quick Start
import 'package:flutter/material.dart';
import 'package:awaitware_ui_utilities/awaitware_ui_utilities.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
// Beautiful card with extensions
Text('Welcome!')
.text4Xl()
.fontBold()
.textCenter()
.p6()
.bgBlue600()
.roundedXl()
.shadowLg()
.m4(),
// Quick button layouts
[
Text('Cancel').textGray700().px4().py2().border().roundedLg(),
Text('Confirm').textWhite().px4().py2().bgGreen600().roundedLg(),
].gap(12).row(),
],
).p4(),
),
);
}
}
Why Awaitware UI Utilities?
Before (Traditional Flutter)
Padding(
padding: const EdgeInsets.all(16),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Color(0x1A000000),
offset: Offset(0, 10),
blurRadius: 15,
),
],
),
child: Text(
'Hello World',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue.shade600,
),
),
),
)
After (With Awaitware UI Utilities)
Text('Hello World')
.text2Xl()
.fontBold()
.textBlue600()
.p6()
.bgWhite()
.roundedXl()
.shadowLg()
.p4()
60-70% less code! More readable, easier to maintain, and faster to write.
Features Overview
| Feature | Count | Description |
|---|---|---|
| Extension Methods | 1500+ | Chainable utilities covering all UI needs |
| Source Files | 41 | Organized by feature category |
| Example Files | 35 | One per category with working code |
| Test Files | 19 | Comprehensive widget tests |
| Helper Classes | 15+ | AwInput, AwAvatar, AwDialog, AwTable, etc. |
Key Highlights
- Chainable API — Combine multiple utilities for clean, readable code
- Custom Values — Use any hex color, custom spacing, or sizing
- Type-Safe — Full Dart type safety with IDE autocomplete
- Zero Dependencies — Only requires Flutter SDK
- Performance Optimized — Lightweight extensions with minimal overhead
- 35 Example Files — Every category has a dedicated example page
- Full Course — Complete learning guide in COURSE.md
What's New in v4.0.0
- Navigation —
asDrawerContent(),withBottomNav(),AwNav.appBar(),.drawer(),.sideNav(),.breadcrumb() - Slivers —
asSliver(),sliverList(),sliverGrid(),customScrollView(),AwSliver.appBar(),.appBarLarge() - Tables —
tableCard(),tableBordered(),AwTable.simple(),.striped(),.bordered(),.compact() - Stepper/Timeline —
withStepIndicator(),stepper(),timeline(),AwTimeline.progress(),.vertical(),.numbered() - Drag & Drop —
asDraggable(),asDragTarget(),reorderableList(),AwDragDrop.dropZone() - Internationalization —
rtl(),ltr(),paddingStart(),alignStart(),AwI18n.isRtl(),.responsive() - Platform Adaptive —
adaptive(),cupertinoOnly(),materialOnly(),AwAdaptive.button(),.indicator(),.scaffold()
What's New in v3.0.0
- Form Inputs — Pre-styled inputs:
inputRounded(),inputBordered(),inputFilled(), validation states,AwInputbuilder - Image Extensions —
imgCircle(),imgRounded(),imgBordered(),imgShadow(),imgOverlay(),imgGrayscale(),AwImagehelpers - Shimmer/Skeleton — Loading states:
skeleton(),AwSkeleton.text(),.circle(),.card(),.listTile(),.grid() - Badges & Chips —
withBadge(),withDotBadge(),badge(),chip(),chipDeletable(),AwBadge.chipGroup() - Avatars —
avatarCircle(),avatarXs()-avatarXl(),AwAvatar.initials(),.icon(),.group(),.withStatus() - Dialogs —
asDialog(),asBottomSheet(),AwDialog.alert(),.confirm(),.confirmDelete(),.snackbar(),.loading() - Dividers —
withDividerBelow(),AwDivider.thin(),.dashed(),.dotted(),.withText(),.gradient(),.space() - List Tiles —
listTileCard(),listTileBordered(),AwListTile.simple(),.settings(),.contact(),.notification() - Clip Shapes —
clipOval(),clipTriangle(),clipDiamond(),clipHexagon(),clipStar(),clipPolygon(),shapeCircle() - Scroll Effects —
scrollWithFade(),scrollBouncing(),scrollSnap(),horizontalScroll(),pageView()with indicators - Tooltips & Popups —
withTooltip(),withStyledTooltip(),withPopupMenu(),withPopover(),AwPopupItemhelpers - Accessibility —
semanticLabel(),semanticButton(),excludeSemantics(),focusable(),AwA11yutilities
What's New in v2.0.0
- Custom Values — Use hex colors like
bgHex('#0f172a'), custom spacing, sizing - Responsive Design — Breakpoint system (xs, sm, md, lg, xl)
- Grid System — CSS Grid-like responsive layouts
- Gradients — Linear, radial, and preset gradients
- Animations — Fade, slide, scale, spin, bounce, pulse, shake
- Dark Mode — Theme-aware styling utilities
- Button & Card Presets — Pre-styled components
- Typography Presets — h1-h6, body, caption, label
Complete Extension Reference
Spacing (90+ methods)
Container().p4() // 16px padding all sides
Container().px4() // 16px horizontal padding
Container().py6() // 24px vertical padding
Container().pt4() // 16px top padding
Container().m4() // 16px margin all sides
Container().mx4() // 16px horizontal margin
Container().mxAuto() // Center horizontally
Container().pCustom(20) // Custom 20px padding
Container().pTRBL(10, 20, 10, 20) // Individual sides
Colors (200+ methods)
Container().bgBlue600()
Container().bgWhite()
Container().bgHex('#0f172a')
Container().bgRgb(15, 23, 42)
Text('Hello').textRed600()
Text('Info').textBlue600()
Text('Custom').textHex('#3b82f6')
Typography (60+ methods)
Text('Title').text4Xl().fontBold()
Text('Body').textBase().fontNormal()
Text('Link').underline().textBlue600()
Text('Hello').fontSize(24)
Text('Hello').fontW(600)
Text('Hello').lineHeight(1.5)
Sizing (50+ methods)
Container().w64() // 256px width
Container().wFull() // 100% width
Container().maxWLg() // Max 512px
Container().square(100) // 100x100px
Container().wPercent(50) // 50% of parent
Icon().size16() // 64x64 square
Decoration (40+ methods)
Container().roundedXl() // 12px radius
Container().roundedFull() // Circle
Container().border() // 1px border
Container().borderBlue() // Blue border
Container().shadowLg() // Large shadow
Container().opacity50() // 50% opacity
Layout (30+ methods)
Container().center()
Container().expanded()
Container().flexible()
Image().aspectVideo() // 16:9
Column().scrollable()
Flex (20+ methods)
[Item1(), Item2()].row()
[Item1(), Item2()].column()
[Item1(), Item2(), Item3()].gap(8).row()
[Item1(), Item2()].spaceBetween()
[Item1(), Item2()].wrap(spacing: 8)
Transform (15+ methods)
Icon().rotate45()
Icon().rotate90()
Container().scale110()
Container().translate(10, 20)
Image().flipH()
Image().flipV()
Custom Values
Use any custom value — hex colors, custom spacing, custom sizing:
// Custom hex colors
Container().bgHex('#0f172a') // Hex string
Container().bgColor(0xFF0f172a) // Hex int
Container().bgRgb(15, 23, 42) // RGB values
Text('Hello').textHex('#3b82f6') // Custom text color
// Custom spacing
Container().pCustom(20) // 20px padding
Container().mCustom(15) // 15px margin
Container().pTRBL(10, 20, 10, 20) // Individual padding
// Custom sizing
Container().wCustom(300) // 300px width
Container().hCustom(200) // 200px height
Container().wPercent(50) // 50% width
Container().square(100) // 100x100px
// Custom decoration
Container().roundedCustom(16) // 16px radius
Container().borderCustom(Colors.blue, 2)
Container().shadowCustom(blurRadius: 10)
// Custom typography
Text('Hello').fontSize(24) // 24px font size
Text('Hello').fontW(600) // Font weight 600
Text('Hello').lineHeight(1.5) // Line height 1.5
Responsive Design
Build responsive layouts with breakpoint utilities:
// Show/hide based on screen size
Container().showOnMobile() // Show only on xs/sm
Container().hideOnMobile() // Hide on xs/sm
Container().lgAndUp() // Show on lg and above
// Responsive grid
[card1, card2, card3, card4].gridResponsive(
xsCols: 1, // 1 column on mobile
smCols: 2, // 2 columns on tablet
lgCols: 4, // 4 columns on desktop
gap: 16,
)
// Responsive builder
ResponsiveBuilder(
xs: MobileLayout(),
md: TabletLayout(),
lg: DesktopLayout(),
)
Gradients
// Custom gradients
Container().gradientToR(colors: [Colors.blue, Colors.purple])
Container().gradientToB(colors: [Colors.red, Colors.orange])
Container().gradientRadial(colors: [Colors.white, Colors.blue])
// Preset gradients
Container().gradientSunset() // Orange to pink
Container().gradientOcean() // Blue to cyan
Container().gradientNeon() // Pink to purple to blue
Container().gradientForest() // Green shades
Animations
// Entry animations
Container().fadeIn()
Container().slideInLeft()
Container().slideInUp()
Container().scaleIn()
// Continuous animations
Icon(Icons.sync).spin() // Spinning loader
Container().pulse() // Pulsing effect
Container().bounce() // Bouncing effect
// Interactive animations
Container().tapScale() // Scale on tap
Container().hoverScale() // Scale on hover
Container().hoverElevate() // Elevate on hover
Dark Mode
// Theme-aware backgrounds
Container().themeBackground() // Adapts to theme
Container().darkBgGray900() // Dark mode: gray900
Container().lightBgWhite() // Light mode: white
// Theme-aware text
Text('Hello').darkTextWhite() // Dark mode: white
Text('Hello').lightTextGray900() // Light mode: gray900
// Theme widgets
ThemeContainer(
lightColor: Colors.white,
darkColor: Colors.grey.shade900,
child: content,
)
Button Presets
// Primary buttons
Text('Submit').btnPrimary(onTap: () {})
Text('Submit').btnPrimaryLg(onTap: () {})
// Variants
Text('Cancel').btnSecondary(onTap: () {})
Text('Learn More').btnOutline(onTap: () {})
Text('Delete').btnDanger(onTap: () {})
Text('Save').btnSuccess(onTap: () {})
// Special buttons
Text('Get Started').btnGradient(onTap: () {})
Text('Subscribe').btnPill(onTap: () {})
Text('Loading...').btnLoading(isLoading: true)
// Icon buttons
Icon(Icons.add).btnIconFilled(onTap: () {})
Icon(Icons.close).btnIconOutline(onTap: () {})
Card Presets
Column(...).card() // Default card with shadow
Column(...).cardBordered() // Card with border
Column(...).cardElevated() // Stronger shadow
Column(...).cardFlat() // No shadow, subtle bg
Column(...).cardHoverable() // Lifts on hover
Column(...).cardClickable(onTap: () {})
Column(...).cardPrimary() // Blue card
Column(...).cardDanger() // Red card
Column(...).cardSuccess() // Green card
Column(...).cardGradient(colors: [Colors.blue, Colors.purple])
Typography Presets
// Headings
Text('Title').h1() // 48px bold
Text('Title').h2() // 36px bold
Text('Title').h3() // 30px semibold
Text('Title').h4() // 24px semibold
// Body text
Text('Content').bodyLarge() // 18px
Text('Content').bodyBase() // 16px
Text('Content').bodySmall() // 14px
// Labels & captions
Text('Label').label() // 14px medium
Text('Caption').caption() // 12px
// Special
Text('Quote').quote() // Italic with left border
Text('code').code() // Monospace font
// Transform
Text('hello').uppercase() // HELLO
Text('HELLO').lowercase() // hello
Text('hello').capitalize() // Hello
Form Inputs
// Pre-styled text fields
TextField().inputRounded()
TextField().inputBordered()
TextField().inputFilled()
// Validation states
TextField().inputError(message: 'Required field')
TextField().inputSuccess()
// AwInput decoration builder
TextField(decoration: AwInput.outlined(label: 'Email', prefixIcon: Icons.email))
TextField(decoration: AwInput.filled(label: 'Password', suffixIcon: Icons.visibility))
TextField(decoration: AwInput.search(hint: 'Search...'))
TextField(decoration: AwInput.rounded(label: 'Name'))
TextField(decoration: AwInput.underline(label: 'Bio'))
// Form group
[field1, field2, field3].formGroup(spacing: 16)
Images
Image.network(url).imgCircle(size: 80)
Image.network(url).imgRounded(radius: 12)
Image.network(url).imgBordered(color: Colors.white, width: 3)
Image.network(url).imgShadow()
Image.network(url).imgOverlay(color: Colors.black54)
Image.network(url).imgGrayscale()
Image.network(url).imgBlur(sigma: 5.0)
AwImage.placeholder(width: 200, height: 150)
AwImage.avatar(url: 'https://...', size: 60)
Shimmer & Skeleton Loading
// Toggle loading state
Text('Hello World').skeleton(isLoading: isLoading)
// Skeleton factory methods
AwSkeleton.text(lines: 3)
AwSkeleton.circle(size: 48)
AwSkeleton.box(width: 200, height: 100)
AwSkeleton.card()
AwSkeleton.listTile(showAvatar: true)
AwSkeleton.list(itemCount: 5)
AwSkeleton.grid(columns: 2, rows: 3)
Badges & Chips
Icon(Icons.notifications).withBadge('3')
Icon(Icons.mail).withDotBadge()
Text('Flutter').chip()
Text('Dart').chip(color: Colors.blue)
Text('Tag').chipDeletable(onDeleted: () {})
AwBadge.chipGroup(
labels: ['Flutter', 'Dart', 'Firebase'],
onSelected: (label) => print(label),
)
Avatars
Image.network(url).avatarCircle(size: 48)
Container().avatarXs() // 24px
Container().avatarMd() // 40px
Container().avatarXl() // 64px
AwAvatar.initials('JD', size: 48, color: Colors.blue)
AwAvatar.icon(Icons.person, size: 48)
AwAvatar.withStatus(child: avatar, isOnline: true, size: 48)
AwAvatar.group(avatars: [a1, a2, a3], maxDisplay: 3, size: 32)
Dialogs & Bottom Sheets
myWidget.asDialog(context)
myWidget.asBottomSheet(context)
AwDialog.alert(context, title: 'Warning', message: 'Cannot be undone.')
final confirmed = await AwDialog.confirm(context, title: 'Delete?', message: 'Are you sure?')
await AwDialog.confirmDelete(context, itemName: 'Document')
AwDialog.loading(context, message: 'Saving...')
AwDialog.snackbar(context, message: 'Saved!')
List Tiles
ListTile(...).listTileCard()
ListTile(...).listTileBordered()
AwListTile.simple(title: 'Profile', leading: Icons.person, onTap: () {})
AwListTile.settings(title: 'Notifications', leading: Icons.notifications, trailing: Switch(...))
AwListTile.contact(name: 'John Doe', phone: '+1 234 567 890', avatarText: 'JD')
AwListTile.notification(title: 'New Message', message: 'You have a new message', time: '2 min ago', isRead: false)
Dividers
Container().withDividerBelow()
Container().withDividerAbove()
AwDivider.thin()
AwDivider.thick()
AwDivider.dashed()
AwDivider.dotted()
AwDivider.withText('OR')
AwDivider.gradient(colors: [Colors.blue, Colors.purple])
AwDivider.space(height: 24)
Clip Shapes
Container().clipOval()
Container().clipTriangle()
Container().clipDiamond()
Container().clipHexagon()
Container().clipOctagon()
Container().clipPentagon()
Container().clipStar()
Container().clipStar(points: 6)
Container().clipPolygon(sides: 7)
Container().shapeCircle(color: Colors.blue)
Scroll Effects
Column(children: [...]).scrollWithFade()
Column(children: [...]).scrollBouncing()
Column(children: [...]).scrollSnap()
[widget1, widget2, widget3].horizontalScroll()
[page1, page2, page3].pageView(showIndicators: true)
Tooltips & Popups
Icon(Icons.info).withTooltip('More information')
Icon(Icons.help).withStyledTooltip(
message: 'Help text',
backgroundColor: Colors.black87,
)
Icon(Icons.more_vert).withPopupMenu(
items: [
AwPopupItem(title: 'Edit', icon: Icons.edit, value: 'edit'),
AwPopupItem(title: 'Delete', icon: Icons.delete, value: 'delete'),
],
onSelected: (value) => print(value),
)
Accessibility
Text('Hello').semanticLabel('Greeting text')
Container().semanticButton(label: 'Submit')
Container().semanticImage('Profile photo')
Container().semanticChecked(true)
Container().semanticHidden()
Container().excludeSemantics()
Container().mergeSemantics()
Container().focusOrder(1.0)
AwA11y.isHighContrast(context)
AwA11y.isBoldText(context)
AwA11y.isReduceMotion(context)
AwA11y.textScale(context)
Navigation
ListView(children: [...]).asDrawerContent()
body.withBottomNav(items: [...], currentIndex: 0, onTap: (i) {})
AwNav.appBar(title: 'My App', actions: [...])
AwNav.drawer(header: widget, items: [...])
AwNav.sideNav(items: [...], selectedIndex: 0, onChanged: (i) {})
AwNav.breadcrumb(items: ['Home', 'Products'], onTap: (i) {})
Slivers
Text('Hello').asSliver()
[item1, item2, item3].sliverList()
[item1, item2, item3].sliverGrid(crossAxisCount: 2)
[sliver1, sliver2].customScrollView()
AwSliver.appBar(title: 'My App', expandedHeight: 200)
AwSliver.appBarLarge(title: 'Discover', expandedHeight: 250)
Tables
AwTable.simple(
headers: ['Name', 'Role', 'Email'],
rows: [
['John Doe', 'Admin', 'john@example.com'],
['Jane Smith', 'User', 'jane@example.com'],
],
)
AwTable.striped(headers: [...], rows: [...])
AwTable.bordered(headers: [...], rows: [...])
AwTable.compact(headers: [...], rows: [...])
Stepper & Timeline
Container().withStepIndicator(step: 1, total: 5)
[step1, step2, step3].stepper(currentStep: 1)
[event1, event2, event3].timeline()
AwTimeline.progress(steps: ['Order', 'Shipped', 'Delivered'], currentStep: 1)
AwTimeline.vertical(items: ['Event 1', 'Event 2', 'Event 3'])
AwTimeline.numbered(items: ['Step 1', 'Step 2', 'Step 3'], currentStep: 1)
Drag & Drop
Container().asDraggable(data: 'item_1')
Container().asDragTarget<String>(onAccept: (data) => print(data))
[item1, item2, item3].reorderableList(onReorder: (old, new_) {})
AwDragDrop.dropZone<String>(onAccept: (data) {}, child: Text('Drop here'))
AwDragDrop.reorderableList(items: widgets, onReorder: (old, new_) {})
Internationalization (i18n / RTL)
Container().rtl() // Force right-to-left
Container().ltr() // Force left-to-right
Container().paddingStart(16) // Left in LTR, Right in RTL
Container().paddingEnd(16) // Right in LTR, Left in RTL
Container().alignStart() // Direction-aware alignment
AwI18n.isRtl(context)
AwI18n.directionOf(context)
AwI18n.responsive(context, ltr: ltrWidget, rtl: rtlWidget)
Platform Adaptive
Container().adaptive() // Auto-adapt to platform
Container().cupertinoOnly() // iOS only
Container().materialOnly() // Android only
AwAdaptive.button(context, child: Text('Submit'), onPressed: () {})
AwAdaptive.switchControl(context, value: true, onChanged: (v) {})
AwAdaptive.slider(context, value: 0.5, onChanged: (v) {})
AwAdaptive.indicator(context)
AwAdaptive.textField(context, placeholder: 'Enter text')
AwAdaptive.alertDialog(context, title: 'Confirm', content: 'Sure?', actions: [...])
AwAdaptive.scaffold(context, appBar: AppBar(...), body: Container())
Gesture Extensions
Container().onTap(() => print('Tapped!'))
Container().onDoubleTap(() => print('Double tap!'))
Container().onLongPress(() => print('Long press!'))
Container().cursorPointer()
Container().cursorGrab()
Container().onHover(
onEnter: (e) => print('Enter'),
onExit: (e) => print('Exit'),
)
The aw Helper Class
// Widget Creators
aw.text('Hello')
aw.container()
aw.icon(Icons.star)
// Layout Builders
aw.row([Widget1(), Widget2()])
aw.column([Widget1(), Widget2()])
aw.stack([Widget1(), Widget2()])
// Spacing Helpers
aw.spaceV(16) // Vertical spacing
aw.spaceH(16) // Horizontal spacing
aw.space4() // 16px space
// Quick Helpers
aw.button('Click', onPressed: () {})
aw.card(child: Widget)
aw.divider()
Real-World Examples
Product Card
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(height: 200, color: Colors.grey.shade200).roundedT(),
Text('Premium Headphones').textXl().fontSemibold().pt4(),
Text('High-quality wireless audio').textSm().textGray600().pt1(),
Text('\$299.99').text2Xl().fontBold().textGreen600().pt2(),
[
Text('In Stock').textXs().textGreen700().px2().py1().bgGreen100().roundedFull(),
Text('Free Shipping').textXs().textBlue700().px2().py1().bgBlue100().roundedFull(),
].gap(8).row().pt2(),
Text('Add to Cart').btnPrimary(onTap: () {}).wFull().pt4(),
],
).p6().bgWhite().roundedXl().shadowLg()
Dashboard Stats
[
_StatCard('Revenue', '\$48,200', Icons.attach_money, Colors.green),
_StatCard('Users', '2,340', Icons.people, Colors.blue),
_StatCard('Orders', '456', Icons.shopping_bag, Colors.orange),
_StatCard('Growth', '+12.5%', Icons.trending_up, Colors.purple),
].gridResponsive(xsCols: 2, lgCols: 4, gap: 16)
Chat Bubble
Text('Hello! How are you?')
.bodyBase()
.textWhite()
.px4()
.py3()
.bgBlue600()
.roundedXl()
Settings Page
Column(
children: [
AwListTile.settings(title: 'Dark Mode', leading: Icons.dark_mode, trailing: Switch(...)),
AwListTile.settings(title: 'Notifications', leading: Icons.notifications, onTap: () {}),
AwListTile.settings(title: 'Language', leading: Icons.language, onTap: () {}),
],
).bgWhite().roundedXl().shadowSm()
See more: 35 complete example files in example/lib/examples/ and the full course in COURSE.md
Documentation
- Full Course with Examples — 34-module learning guide
- 35 Example Files — One per category
- Example App — Working Flutter app with navigation to all examples
- Changelog — Version history
- Contributing Guide — How to contribute
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. See CONTRIBUTING.md for guidelines.
License
This project is licensed under the MIT License — see the LICENSE file for details.
Made with love for Flutter Developers
A modern utility-first toolkit for Flutter development
Libraries
- awaitware_ui_utilities
- Awaitware UI Utilities - Powerful Flutter UI Toolkit