A collection of Fluent UI widgets for Flutter, designed to work seamlessly with the fluent_ui package. This package provides three main components: toast notifications, a data grid, and tag components.
Note: This package is currently in early development and should be considered experimental. The API may change in future versions.
- Toast Notifications: App-wide toast notifications with queue management, auto-dismiss, and configurable positioning
- Data Grid: A fully-featured data grid with sorting, filtering, pagination, and selection support
- Tags: Flexible tag components with multiple variants (dismissible, interactive, styled)
Add fluent_widgets to your pubspec.yaml:
dependencies:
fluent_ui: ^4.13.0
fluent_widgets: ^0.1.4App-wide toast notifications that work across your entire Flutter app, not just within a specific route.
The Toaster widget must be placed below FluentApp in the widget tree to access the Fluent theme context. Use the builder parameter of FluentApp:
import 'package:fluent_ui/fluent_ui.dart';
import 'package:fluent_widgets/fluent_widgets.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return FluentApp(
title: 'My App',
theme: FluentThemeData(),
darkTheme: FluentThemeData.dark(),
builder: (context, child) {
return Toaster(
child: child!,
);
},
home: const HomePage(),
);
}
}
// Get the toaster controller
final toaster = Toaster.of(context);
// Show a simple toast
toaster.dispatchToast(
Toast(
title: 'Success!',
content: Text('Your changes have been saved'),
intent: ToastIntent.success,
),
);
// Show a persistent toast (no auto-dismiss)
toaster.dispatchToast(
Toast(
title: 'Important',
content: Text('This toast stays until dismissed'),
intent: ToastIntent.warning,
timeout: null, // No auto-dismiss
),
);
// Show a toast with custom icon
toaster.dispatchToast(
Toast(
title: 'Processing',
content: Text('Please wait...'),
icon: const ProgressRing(),
timeout: null,
),
);// Dismiss a specific toast by ID
final toastId = 'my-toast-id';
toaster.dispatchToast(
Toast(
id: toastId,
title: 'Dismissible',
intent: ToastIntent.info,
),
);
// Later, dismiss it
toaster.dismissToast(toastId);
// Dismiss all toasts
toaster.dismissAllToasts();
// Update an existing toast
toaster.updateToast(
Toast(
id: toastId,
title: 'Updated!',
intent: ToastIntent.success,
),
);The Toast class supports:
title(required): Main title textcontent: Optional widget displayed below the titleintent: Visual intent (ToastIntent.info,success,warning,error)timeout: Auto-dismiss duration (default: 3 seconds, set tonullfor persistent)dismissible: Whether the toast can be dismissed (default:true)inverted: Inverted color schemeicon: Custom icon widgettrailing: Custom trailing widget (replaces dismiss button)id: Unique identifier for programmatic control
The Toaster widget supports:
maxToasts: Maximum number of toasts displayed simultaneously (default: 3)position: Toast position (ToastPosition.bottomEnd,bottomStart,topEnd,topStart,bottom,top)offset: Offset from screen edge (default:Offset(5, 5))animationDuration: Animation duration (default: 400ms)
A Fluent UI-style data grid for displaying tabular data with built-in sorting, filtering, pagination, and selection.
DataGrid<Person>(
data: people,
columns: [
DataGridColumn<Person>(
title: 'Name',
valueBuilder: (person) => person.name,
sortBy: (a, b) => a.name.compareTo(b.name),
),
DataGridColumn<Person>(
title: 'Age',
valueBuilder: (person) => person.age.toString(),
sortBy: (a, b) => a.age.compareTo(b.age),
textAlign: TextAlign.right,
),
DataGridColumn<Person>(
title: 'Department',
valueBuilder: (person) => person.department,
filterType: FilterType.dropdown,
filterOptions: ['Sales', 'Engineering', 'Marketing'],
),
],
selectionMode: SelectionMode.multi,
selectedItems: selectedPeople,
onSelectionChanged: (selected) {
setState(() => selectedPeople = selected);
},
itemsPerPage: 50,
showRowNumbers: true,
alternatingRowColors: true,
)Sorting: Click column headers to sort. Supports single-column sorting with visual indicators.
Filtering:
- Text filters: Case-insensitive substring matching
- Dropdown filters: Select from predefined options
- Custom filters: Use
filterBuilderfor custom filter UI - Filter panel: Collapsible filter panel at the top of the grid
Selection:
SelectionMode.none: No selectionSelectionMode.single: Single row selectionSelectionMode.multi: Multiple row selection with checkboxes
Pagination:
- Enable with
itemsPerPage - Automatically resets to first page when filters or sorting change
- Shows item counts and page navigation
Selection Preservation: Use itemIdentifier to preserve selection when data updates:
DataGrid<Person>(
data: people,
itemIdentifier: (person) => person.id, // Preserve selection by ID
// ...
)DataGridColumn<T> supports:
title: Column header textvalueBuilder: Function to extract display value (must return String)width: Fixed width (null for auto-width)sortBy: Optional comparator function for sortingfilterType: Filter type (FilterType.none,text,dropdown,dateRange,numberRange)filterOptions: Options for dropdown filtersfilterPredicate: Custom filter matching logicfilterBuilder: Custom filter widget buildercellBuilder: Custom cell widget buildertextAlign: Text alignment
Show a loading state with shimmer effect:
DataGrid.loading(
columns: ['Name', 'Age', 'Department'],
rowCount: 10,
)Tag components for displaying labeled information, useful for categorization, filtering, or status indication.
Tag(
text: 'Category',
icon: Icon(FluentIcons.tag),
tagStyle: TagStyle.filled,
size: TagSize.medium,
shape: TagShape.rounded,
)DismissibleTag(
text: 'Removable',
onDismiss: () {
// Handle dismissal
},
)InteractiveTag(
text: 'Clickable',
onPressed: () {
// Handle tap
},
)DismissibleInteractiveTag(
text: 'Full Featured',
onPressed: () {
// Handle tap
},
onDismiss: () {
// Handle dismissal
},
)Styles:
TagStyle.filled: Filled background (default)TagStyle.outline: Outlined borderTagStyle.brand: Tinted background with accent color
Sizes:
TagSize.small: Compact sizeTagSize.medium: Default sizeTagSize.large: Larger size for emphasis
Shapes:
TagShape.rounded: Rounded corners (default)TagShape.circular: Fully circular
Customization:
icon: Optional leading icontrailing: Custom trailing widgetbackgroundColor: Custom background colortextColor: Custom text colorborderColor: Custom border color (for outline style)enabled: Enable/disable the tag
Complete working examples can be found in the examples/ directory:
examples/toasts/- Toast notification examplesexamples/data_grid/- Data grid examplesexamples/tags/- Tag component examples
Contributions are welcome! Please feel free to submit a Pull Request.
See LICENSE file for details.