| name | flutter-widgets |
| description | Principles for maintainable UI components. Use when building, refactoring, or reviewing Flutter widget implementations for maintainability. (triggers: **_page.dart, **_screen.dart, **/widgets/**, StatelessWidget, const, Theme, ListView) |
UI & Widgets
Priority: P1 (OPERATIONAL)
Standards for building reusable, performant Flutter widgets and UI components.
- State: Use
StatelessWidget by default. StatefulWidget only for local state/controllers.
- Composition: Extract UI into small, atomic
const widgets.
- Theming: Use
Theme.of(context). No hardcoded colors.
- Layout: Use
Flex + Gap/SizedBox.
- Widget Keys: All interactive elements must use keys from
widget_keys.dart.
- File Size: If a UI file exceeds ~80 lines, extract sub-widgets into private classes.
- Specialized:
SelectionArea: For multi-widget text selection.
InteractiveViewer: For zoom/pan.
ListWheelScrollView: For pickers.
IntrinsicWidth/Height: Avoid unless strictly required.
- Large Lists: Always use
ListView.builder.
class AppButton extends StatelessWidget {
final String label;
final VoidCallback onPressed;
const AppButton({super.key, required this.label, required this.onPressed});
@override
Widget build(BuildContext context) => ElevatedButton(onPressed: onPressed, child: Text(label));
}
Anti-Patterns
- ❌
setState(() { _orders = await repo.fetch(); }) — server/shared state belongs in a BLoC, not widget state
- ❌ Widget file over 80 lines without extracting private sub-widget classes — helper methods returning
Widget are not a substitute
- ❌
Key('submit-button') inline in widget code — all keys must be constants defined in widget_keys.dart
- ❌
Widget _buildHeader() { … } helper methods — extract to a const StatelessWidget private class for proper rebuilding control
Related Topics
performance | testing