Zeba Academy Empty State
A lightweight, reusable, and highly customizable empty-state widget for Flutter applications.
zeba_academy_empty_state provides a clean and flexible way to display empty screens with support for icons, images, custom widgets, titles, descriptions, action buttons, custom actions, styling, spacing, alignment, and accessibility.
No external runtime dependencies are required.
โจ Features
- ๐ฏ Reusable empty-state layout
- ๐ผ๏ธ Icon support
- ๐จ Custom visual widgets
- ๐ผ๏ธ Image support through
ImageProvider - ๐ Custom title
- ๐ Optional description
- ๐ Built-in action button
- ๐งฉ Custom action widget
- ๐จ Custom title styling
- ๐จ Custom description styling
- ๐ Custom icon color
- ๐ Custom icon size
- โ๏ธ Configurable content width
- ๐ Configurable spacing
- ๐ฆ Configurable padding
- โ๏ธ Main-axis alignment
- โ๏ธ Cross-axis alignment
- ๐ Text alignment
- โฟ Accessibility semantic labels
- ๐ชถ Lightweight implementation
- ๐ซ No external runtime dependencies
- โ Material 3 compatible
- ๐งช Widget-test friendly
- ๐ฑ Works across Flutter platforms
๐ฆ Installation
Add the package to your pubspec.yaml:
dependencies:
zeba_academy_empty_state: ^0.0.1
Then run:
flutter pub get
๐ Quick Start
Import the package:
import 'package:zeba_academy_empty_state/zeba_academy_empty_state.dart';
Use the widget:
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No messages',
description: 'Your inbox is currently empty.',
)
That's all you need for a basic empty state.
๐ฏ Basic Example
import 'package:flutter/material.dart';
import 'package:zeba_academy_empty_state/zeba_academy_empty_state.dart';
class EmptyPage extends StatelessWidget {
const EmptyPage({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No messages',
description: 'Your inbox is currently empty.',
),
),
);
}
}
๐ Empty State With Action
Use actionLabel and onAction to display the built-in Material button.
ZebaEmptyState(
icon: Icons.refresh,
title: 'Nothing here',
description: 'Try refreshing the page.',
actionLabel: 'Refresh',
onAction: () {
// Refresh your data.
},
)
The widget automatically creates a FilledButton.
๐ Example: Empty Cart
ZebaEmptyState(
icon: Icons.shopping_cart_outlined,
title: 'Your cart is empty',
description: 'Add some products to your cart to get started.',
actionLabel: 'Browse Products',
onAction: () {
// Navigate to products.
},
)
โค๏ธ Example: Empty Favorites
ZebaEmptyState(
icon: Icons.favorite_border,
title: 'No favorites yet',
description: 'Items you favorite will appear here.',
)
๐ Example: No Search Results
ZebaEmptyState(
icon: Icons.search_off,
title: 'No results found',
description: 'Try searching with a different keyword.',
actionLabel: 'Clear Search',
onAction: () {
// Clear search query.
},
)
๐ Example: Empty Notifications
ZebaEmptyState(
icon: Icons.notifications_none,
title: 'No notifications',
description: 'You are all caught up!',
)
๐จ Custom Visual Widget
You are not limited to icons.
Use iconWidget when you need a custom illustration, animation, logo, or any other Flutter widget.
ZebaEmptyState(
iconWidget: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.blue.withValues(alpha: 0.1),
shape: BoxShape.circle,
),
child: const Icon(
Icons.shopping_bag_outlined,
size: 48,
),
),
title: 'Your bag is empty',
description: 'Products you add will appear here.',
)
๐ผ๏ธ Image Support
The package supports any Flutter ImageProvider.
For example, with an asset:
ZebaEmptyState(
image: const AssetImage(
'assets/images/empty_state.png',
),
title: 'Nothing found',
description: 'There are no items to display.',
)
You can also use another ImageProvider:
ZebaEmptyState(
image: const NetworkImage(
'https://example.com/empty-state.png',
),
title: 'No results',
)
The package itself does not add a networking dependency.
๐งฉ Custom Action Widget
If the built-in FilledButton is not suitable for your design, provide your own widget through action.
ZebaEmptyState(
icon: Icons.wifi_off,
title: 'No internet connection',
description: 'Check your connection and try again.',
action: OutlinedButton.icon(
onPressed: () {
// Try again.
},
icon: const Icon(Icons.refresh),
label: const Text('Try Again'),
),
)
This allows you to use:
TextButtonOutlinedButtonFilledButtonElevatedButtonIconButton- Custom widgets
- Multiple buttons
- Any Flutter widget
๐จ Custom Styling
Customize the title:
ZebaEmptyState(
icon: Icons.search_off,
title: 'No results',
titleStyle: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
)
Customize the description:
ZebaEmptyState(
icon: Icons.info_outline,
title: 'Nothing available',
description: 'There is currently nothing to show.',
descriptionStyle: const TextStyle(
fontSize: 16,
),
)
Customize the icon:
ZebaEmptyState(
icon: Icons.warning_amber_outlined,
title: 'No data',
iconColor: Colors.orange,
iconSize: 80,
)
๐ Layout Customization
Control the spacing between the title and description:
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'Empty inbox',
description: 'There are no messages.',
spacing: 16,
)
Control the spacing before the action:
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'Empty inbox',
description: 'There are no messages.',
actionLabel: 'Refresh',
onAction: () {},
contentSpacing: 32,
)
Control the maximum text width:
ZebaEmptyState(
icon: Icons.search_off,
title: 'No results found',
description:
'Try changing your search query or using different keywords.',
maxWidth: 500,
)
Control padding:
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No messages',
padding: const EdgeInsets.all(32),
)
โ๏ธ Alignment
You can customize the main-axis alignment:
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No messages',
mainAxisAlignment: MainAxisAlignment.center,
)
Cross-axis alignment:
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No messages',
crossAxisAlignment: CrossAxisAlignment.center,
)
๐ Text Alignment
Customize title and description alignment:
ZebaEmptyState(
icon: Icons.search_off,
title: 'No results',
description: 'Try another search term.',
textAlign: TextAlign.center,
)
Other supported values include:
TextAlign.left
TextAlign.right
TextAlign.center
TextAlign.justify
โฟ Accessibility
The widget supports an optional semantic label:
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No messages',
semanticLabel: 'Empty inbox. There are currently no messages.',
)
This can improve accessibility for users who rely on screen readers.
๐งฑ API Reference
ZebaEmptyState
| Property | Type | Default | Description |
|---|---|---|---|
icon |
IconData? |
null |
Default icon |
iconWidget |
Widget? |
null |
Custom visual widget |
image |
ImageProvider? |
null |
Image or illustration |
title |
String |
Required | Empty-state title |
description |
String? |
null |
Optional description |
actionLabel |
String? |
null |
Built-in action label |
onAction |
VoidCallback? |
null |
Built-in action callback |
action |
Widget? |
null |
Custom action widget |
titleStyle |
TextStyle? |
Theme | Title styling |
descriptionStyle |
TextStyle? |
Theme | Description styling |
iconColor |
Color? |
Theme primary | Icon color |
iconSize |
double? |
64 |
Icon/image size |
spacing |
double? |
12 |
Title-description spacing |
contentSpacing |
double? |
24 |
Content-action spacing |
maxWidth |
double? |
420 |
Maximum text width |
padding |
EdgeInsetsGeometry? |
24 |
Outer padding |
mainAxisAlignment |
MainAxisAlignment |
center |
Main-axis alignment |
crossAxisAlignment |
CrossAxisAlignment |
center |
Cross-axis alignment |
textAlign |
TextAlign |
center |
Text alignment |
semanticLabel |
String? |
null |
Accessibility label |
โ ๏ธ Important API Rules
Icon vs iconWidget
Use either icon or iconWidget.
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'Empty',
)
or:
ZebaEmptyState(
iconWidget: const FlutterLogo(
size: 80,
),
title: 'Empty',
)
Do not provide both.
Icon vs Image
Use either icon or image.
ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'Empty',
)
or:
ZebaEmptyState(
image: const AssetImage(
'assets/images/empty.png',
),
title: 'Empty',
)
action vs actionLabel
Use either the built-in action:
ZebaEmptyState(
title: 'Empty',
actionLabel: 'Refresh',
onAction: refresh,
)
or a custom action:
ZebaEmptyState(
title: 'Empty',
action: OutlinedButton(
onPressed: refresh,
child: const Text('Refresh'),
),
)
Do not provide both.
๐๏ธ Recommended Usage
The widget works especially well inside:
Center(
child: ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No items',
description: 'Items will appear here when available.',
),
)
For a screen that contains other widgets, it can also be placed directly inside layouts such as:
Column(
children: [
const Text('My Items'),
Expanded(
child: ZebaEmptyState(
icon: Icons.inbox_outlined,
title: 'No items',
description: 'Add an item to get started.',
),
),
],
)
๐งช Testing
Run the package tests with:
flutter test
Format the source:
dart format lib test example
Analyze the package:
flutter analyze
Validate the package before publishing:
flutter pub publish --dry-run
๐ฑ Platform Support
The package is built entirely with Flutter widgets and does not use platform-specific APIs.
It can be used in Flutter applications targeting:
- Android
- iOS
- Web
- Windows
- macOS
- Linux
๐ฆ Dependencies
Runtime dependencies:
None
The package only depends on Flutter's built-in framework.
Development dependencies are used for testing and linting.
๐ License
This project is licensed under the GNU General Public License v3.0 (GPL-3.0).
See the LICENSE file for the complete license text.
๐จโ๐ป About Me
โจ I'm Sufyan bin Uzayr, an open-source developer passionate about building and sharing meaningful projects.
You can learn more about me and my work at:
๐ Zeba Academy
Your all-in-one learning hub!
Zeba Academy is focused on helping developers learn, build, and grow through practical development resources and open-source projects.
Explore:
You can also follow the Zeba Academy YouTube content for tutorials and developer-focused learning.
๐ค Contributing
Contributions are welcome!
If you would like to improve this package:
- Fork the repository.
- Create a feature branch.
- Make your changes.
- Add or update tests.
- Run
dart format. - Run
flutter analyze. - Run
flutter test. - Submit a pull request.
Please keep contributions focused, well-tested, and consistent with the existing API.
๐ Issues & Feature Requests
If you find a bug or have an idea for improving the package, please open an issue in the project's issue tracker.
When reporting a bug, include:
- Flutter version
- Dart version
- Package version
- Target platform
- Minimal reproduction
- Expected behavior
- Actual behavior
โญ Support
If this package is useful to you:
- โญ Star the project
- ๐ฆ Like the package on pub.dev
- ๐ Report issues
- ๐ก Suggest improvements
- ๐ค Contribute to the project
- ๐ข Share it with other Flutter developers
Your support helps make open-source Flutter development better for everyone.
๐ Changelog
See CHANGELOG.md for a complete history of changes.
๐ Version
Current version:
0.0.1
Built with โค๏ธ for the Flutter community by Zeba Academy.