450 lines
8.6 KiB
Markdown
450 lines
8.6 KiB
Markdown
# Quick Reference Guide - New UX Components
|
|
|
|
## 🎯 Quick Start Guide for Developers
|
|
|
|
### 1. Skeleton Loaders
|
|
|
|
**When to use:** Show during data loading to indicate progress
|
|
|
|
```dart
|
|
// Full dashboard skeleton
|
|
if (isLoading) {
|
|
return const SkeletonDashboard();
|
|
}
|
|
|
|
// Individual skeleton cards
|
|
SkeletonCard()
|
|
SkeletonStatsCard()
|
|
SkeletonListItem()
|
|
|
|
// Custom skeleton
|
|
SkeletonLoader(
|
|
width: 200.w,
|
|
height: 40.h,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
### 2. Enhanced Notifications
|
|
|
|
**Import:**
|
|
```dart
|
|
import '../../core/utils/snackbar_util.dart';
|
|
```
|
|
|
|
**Usage:**
|
|
```dart
|
|
// Success (Green)
|
|
SnackbarUtil.showSuccess('Group created successfully!');
|
|
|
|
// Error (Red)
|
|
SnackbarUtil.showError('Failed to save payment');
|
|
|
|
// Warning (Orange)
|
|
SnackbarUtil.showWarning('Payment deadline approaching');
|
|
|
|
// Info (Blue)
|
|
SnackbarUtil.showInfo('Feature coming soon', title: 'Coming Soon');
|
|
|
|
// With custom title
|
|
SnackbarUtil.showError(
|
|
'Please check your internet connection',
|
|
title: 'Connection Error',
|
|
);
|
|
|
|
// Loading (can be dismissed programmatically)
|
|
SnackbarUtil.showLoading('Processing payment...');
|
|
// Later...
|
|
SnackbarUtil.dismiss();
|
|
|
|
// With action button
|
|
SnackbarUtil.showWithAction(
|
|
title: 'Payment Due',
|
|
message: 'You have a pending payment of ₹5,000',
|
|
actionLabel: 'Pay Now',
|
|
onAction: () => navigateToPayment(),
|
|
type: SnackbarType.warning,
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Empty States
|
|
|
|
**Import:**
|
|
```dart
|
|
import '../../shared/widgets/empty_state_widget.dart';
|
|
```
|
|
|
|
**Usage:**
|
|
```dart
|
|
// Pre-configured empty states
|
|
EmptyStateWidget(
|
|
type: EmptyStateType.noGroups,
|
|
actionLabel: 'Create Group',
|
|
onActionPressed: () => showCreateDialog(),
|
|
)
|
|
|
|
// Available types:
|
|
// - EmptyStateType.noGroups
|
|
// - EmptyStateType.noMembers
|
|
// - EmptyStateType.noPayments
|
|
// - EmptyStateType.noActivities
|
|
// - EmptyStateType.noResults
|
|
// - EmptyStateType.error
|
|
// - EmptyStateType.noInternet
|
|
|
|
// Custom empty state
|
|
EmptyStateWidget(
|
|
type: EmptyStateType.noGroups,
|
|
customTitle: 'Your Custom Title',
|
|
customMessage: 'Your custom message here',
|
|
actionLabel: 'Custom Action',
|
|
onActionPressed: () => doSomething(),
|
|
)
|
|
|
|
// Compact version for smaller spaces
|
|
CompactEmptyState(
|
|
icon: Icons.inbox_rounded,
|
|
message: 'No items found',
|
|
color: Colors.grey.shade600,
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
### 4. Interactive Cards
|
|
|
|
**Import:**
|
|
```dart
|
|
import '../../shared/widgets/interactive_card.dart';
|
|
```
|
|
|
|
**Usage:**
|
|
|
|
#### Basic Interactive Card
|
|
```dart
|
|
InteractiveCard(
|
|
onTap: () => navigateToDetails(),
|
|
child: Column(
|
|
children: [
|
|
Text('Card Title'),
|
|
Text('Card Description'),
|
|
],
|
|
),
|
|
)
|
|
```
|
|
|
|
#### Stats Card
|
|
```dart
|
|
InteractiveStatsCard(
|
|
title: 'Active Groups',
|
|
value: '12',
|
|
icon: Icons.group,
|
|
color: Colors.blue.shade600,
|
|
onTap: () => navigateToGroups(),
|
|
subtitle: 'Last updated today', // Optional
|
|
)
|
|
```
|
|
|
|
#### Quick Action Card
|
|
```dart
|
|
QuickActionCard(
|
|
title: 'Create New Group',
|
|
subtitle: 'Start a new chit fund',
|
|
icon: Icons.group_add,
|
|
color: Colors.green.shade600,
|
|
onTap: () => showCreateDialog(),
|
|
)
|
|
```
|
|
|
|
#### Activity Card
|
|
```dart
|
|
ActivityCard(
|
|
title: 'Payment Received',
|
|
description: 'John Doe paid ₹5,000',
|
|
time: '2h ago',
|
|
icon: Icons.payment,
|
|
color: Colors.green.shade600,
|
|
onTap: () => viewPaymentDetails(), // Optional
|
|
)
|
|
```
|
|
|
|
#### Advanced InteractiveCard Options
|
|
```dart
|
|
InteractiveCard(
|
|
onTap: () => doSomething(),
|
|
onLongPress: () => showOptions(),
|
|
padding: EdgeInsets.all(20.w),
|
|
margin: EdgeInsets.all(8.w),
|
|
backgroundColor: Colors.white,
|
|
elevation: 4.0,
|
|
borderRadius: BorderRadius.circular(16.r),
|
|
enableHoverEffect: true,
|
|
enableRipple: true,
|
|
splashColor: Colors.blue.withOpacity(0.2),
|
|
child: YourContent(),
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 Color Guidelines
|
|
|
|
Use these consistent colors across the app:
|
|
|
|
```dart
|
|
// Success / Positive
|
|
Colors.green.shade600 // #43A047
|
|
|
|
// Error / Negative
|
|
Colors.red.shade600 // #E53935
|
|
|
|
// Warning / Caution
|
|
Colors.orange.shade600 // #FB8C00
|
|
|
|
// Info / Neutral
|
|
Colors.blue.shade600 // #1E88E5
|
|
|
|
// Action / Primary
|
|
Colors.purple.shade600 // #8E24AA
|
|
```
|
|
|
|
---
|
|
|
|
## 📐 Spacing Guidelines
|
|
|
|
Use consistent spacing throughout:
|
|
|
|
```dart
|
|
// Small spacing
|
|
SizedBox(height: 8.h) // Between related items
|
|
SizedBox(width: 8.w)
|
|
|
|
// Medium spacing
|
|
SizedBox(height: 16.h) // Between sections
|
|
SizedBox(width: 16.w)
|
|
|
|
// Large spacing
|
|
SizedBox(height: 24.h) // Between major sections
|
|
SizedBox(width: 24.w)
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 Common Patterns
|
|
|
|
### Loading Pattern
|
|
```dart
|
|
Obx(() {
|
|
if (controller.isLoading.value) {
|
|
return const SkeletonDashboard();
|
|
}
|
|
|
|
if (controller.items.isEmpty) {
|
|
return EmptyStateWidget(
|
|
type: EmptyStateType.noGroups,
|
|
onActionPressed: () => controller.createItem(),
|
|
);
|
|
}
|
|
|
|
return YourContentWidget();
|
|
})
|
|
```
|
|
|
|
### Error Handling Pattern
|
|
```dart
|
|
try {
|
|
await someOperation();
|
|
SnackbarUtil.showSuccess('Operation completed!');
|
|
} catch (e) {
|
|
SnackbarUtil.showError(
|
|
'Something went wrong. Please try again.',
|
|
title: 'Error',
|
|
);
|
|
}
|
|
```
|
|
|
|
### Confirmation Pattern
|
|
```dart
|
|
QuickActionCard(
|
|
title: 'Delete Group',
|
|
icon: Icons.delete,
|
|
color: Colors.red.shade600,
|
|
onTap: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Text('Confirm Delete'),
|
|
content: Text('Are you sure?'),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: Text('Cancel'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
Navigator.pop(context);
|
|
deleteGroup();
|
|
SnackbarUtil.showSuccess('Group deleted');
|
|
},
|
|
child: Text('Delete'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## ⚡ Performance Tips
|
|
|
|
1. **Use const constructors** when possible
|
|
```dart
|
|
const SkeletonDashboard() // Good
|
|
SkeletonDashboard() // Less optimal
|
|
```
|
|
|
|
2. **Avoid rebuilding expensive widgets**
|
|
```dart
|
|
Obx(() {
|
|
if (isLoading.value) return const SkeletonDashboard();
|
|
return const YourContent(); // const helps
|
|
})
|
|
```
|
|
|
|
3. **Reuse card instances** when building lists
|
|
```dart
|
|
ListView.builder(
|
|
itemBuilder: (context, index) {
|
|
return ActivityCard(
|
|
key: ValueKey(items[index].id), // Add key for better performance
|
|
title: items[index].title,
|
|
// ...
|
|
);
|
|
},
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### Issue: Snackbar not showing
|
|
**Solution:** Make sure you're using `Get.context` or have a valid `BuildContext`
|
|
|
|
```dart
|
|
// If outside widget tree
|
|
SnackbarUtil.showError('Error message');
|
|
|
|
// Still need GetX initialized
|
|
void main() {
|
|
runApp(GetMaterialApp(home: App()));
|
|
}
|
|
```
|
|
|
|
### Issue: Skeleton loader not animating
|
|
**Solution:** Ensure parent widget has proper size constraints
|
|
|
|
```dart
|
|
// Bad
|
|
Container(child: SkeletonLoader())
|
|
|
|
// Good
|
|
Container(
|
|
width: 200.w,
|
|
height: 40.h,
|
|
child: SkeletonLoader(),
|
|
)
|
|
```
|
|
|
|
### Issue: Interactive card not responding
|
|
**Solution:** Check if there's a conflicting GestureDetector in parent
|
|
|
|
```dart
|
|
// Remove or set behavior
|
|
GestureDetector(
|
|
behavior: HitTestBehavior.translucent, // Add this
|
|
onTap: () {},
|
|
child: InteractiveCard(...),
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 📱 Testing Checklist
|
|
|
|
When adding new features, test:
|
|
|
|
- ✅ Loading state (skeleton loader appears)
|
|
- ✅ Empty state (shows when no data)
|
|
- ✅ Success state (content displays correctly)
|
|
- ✅ Error state (error message shows)
|
|
- ✅ Tap interactions (cards respond to touch)
|
|
- ✅ Pull-to-refresh (works on mobile)
|
|
- ✅ Notifications (appear and dismiss correctly)
|
|
|
|
---
|
|
|
|
## 🎓 Best Practices
|
|
|
|
1. **Always show feedback for user actions**
|
|
```dart
|
|
onPressed: () async {
|
|
SnackbarUtil.showLoading('Saving...');
|
|
await save();
|
|
SnackbarUtil.dismiss();
|
|
SnackbarUtil.showSuccess('Saved!');
|
|
}
|
|
```
|
|
|
|
2. **Provide clear empty states**
|
|
```dart
|
|
// Bad: Just showing nothing
|
|
if (items.isEmpty) return SizedBox();
|
|
|
|
// Good: Show helpful empty state
|
|
if (items.isEmpty) {
|
|
return EmptyStateWidget(
|
|
type: EmptyStateType.noItems,
|
|
onActionPressed: () => createItem(),
|
|
);
|
|
}
|
|
```
|
|
|
|
3. **Use appropriate colors for context**
|
|
```dart
|
|
// Success actions
|
|
SnackbarUtil.showSuccess(...)
|
|
|
|
// Destructive actions
|
|
SnackbarUtil.showWarning('This will delete all data')
|
|
|
|
// Errors
|
|
SnackbarUtil.showError('Failed to connect')
|
|
```
|
|
|
|
4. **Keep interactions consistent**
|
|
```dart
|
|
// All cards should use InteractiveCard
|
|
// All notifications should use SnackbarUtil
|
|
// All empty states should use EmptyStateWidget
|
|
```
|
|
|
|
---
|
|
|
|
## 📚 More Resources
|
|
|
|
- Flutter Documentation: https://flutter.dev/docs
|
|
- GetX Documentation: https://pub.dev/packages/get
|
|
- Material Design: https://material.io/design
|
|
|
|
---
|
|
|
|
**Happy Coding! 🚀**
|
|
|