Status: Ready for Implementation
Version: 1.0
Date: May 1, 2026
This guide provides step-by-step instructions to migrate PetSphere from partial Material Design 3 to a complete, comprehensive Material Design 3 implementation with proper semantic colors, component theming, and accessibility compliance.
- ✅ Complete Material Design 3 theme (
app_theme_v2_material3.dart) - ✅ All semantic colors properly configured
- ✅ Full component theme overrides
- ✅ Typography system (Playfair + DM Sans)
- ✅ Spacing and sizing tokens
- ✅ Accessibility defaults (touch targets, contrast)
- ✅ Dark mode implementation
- Consistency: All components now follow Material Design 3 guidelines
- Maintainability: Centralized theme system reduces hardcoded colors
- Accessibility: Proper contrast ratios, touch targets, focus states
- Scalability: Easy to extend with new colors, sizes, or components
- Performance: Reduced widget rebuilds through proper theming
File: lib/main.dart
Replace the current theme initialization:
// OLD:
home: Consumer(
builder: (context, ref, child) {
final authState = ref.watch(authProvider);
return authState.status == AuthStatus.authenticated
? const MainLayout()
: const LoginScreen();
},
),
theme: AppTheme.darkTheme,
// NEW:
home: Consumer(
builder: (context, ref, child) {
final authState = ref.watch(authProvider);
return authState.status == AuthStatus.authenticated
? const MainLayout()
: const LoginScreen();
},
),
theme: AppThemeV2.darkTheme, // Use new themeFull main.dart template:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:go_router/go_router.dart';
import 'theme/app_theme_v2_material3.dart';
import 'controllers/auth_controller.dart';
import 'views/main_layout.dart';
import 'views/login_screen.dart';
import 'utils/supabase_config.dart';
import 'utils/routes.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Supabase
await Supabase.initialize(
url: supabaseUrl,
anonKey: supabaseAnonKey,
);
runApp(const ProviderScope(child: PetSphereApp()));
}
class PetSphereApp extends ConsumerWidget {
const PetSphereApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(routerProvider);
return MaterialApp.router(
title: 'PetSphere',
routerConfig: router,
theme: AppThemeV2.darkTheme, // NEW: Material Design 3 theme
debugShowCheckedModeBanner: false,
);
}
}After updating main.dart, verify that all Material Design 3 colors are accessible:
// These are now available throughout the app:
Theme.of(context).colorScheme.primary // #D4845A
Theme.of(context).colorScheme.secondary // #4A7C59
Theme.of(context).colorScheme.tertiary // #8B5A7D
Theme.of(context).colorScheme.error // #B3261E
Theme.of(context).colorScheme.background // #0F0E0C
Theme.of(context).colorScheme.surface // #1A1814
Theme.of(context).colorScheme.outline // #6B645B
// Typography:
Theme.of(context).textTheme.displayLarge // 57sp, Playfair
Theme.of(context).textTheme.headlineMedium // 28sp, Playfair
Theme.of(context).textTheme.titleLarge // 22sp, DM Sans Bold
Theme.of(context).textTheme.bodyMedium // 14sp, DM Sans RegularOLD PATTERN (hardcoded colors):
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFFD4845A),
padding: EdgeInsets.all(16),
),
child: Text('Click Me'),
)NEW PATTERN (theme-based):
ElevatedButton(
onPressed: () {},
child: const Text('Click Me'),
)
// Theme handles: color, padding (24h x 12v), height (48dp), radius (8dp)Button Variants:
// Primary (default ElevatedButton)
ElevatedButton(onPressed: () {}, child: const Text('Primary'))
// Secondary (FilledButton)
FilledButton(
onPressed: () {},
child: const Text('Secondary'),
)
// Tertiary (OutlinedButton)
OutlinedButton(
onPressed: () {},
child: const Text('Tertiary'),
)
// Text-only (TextButton)
TextButton(
onPressed: () {},
child: const Text('Text Action'),
)OLD PATTERN:
Card(
color: Color(0xFF211F1B),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(color: Color(0xFF2E2B26)),
),
child: ...
)NEW PATTERN:
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: ...
),
)
// Theme handles: surface color, border, border radius, elevationOLD PATTERN:
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(18),
borderSide: BorderSide(color: Color(0xFF2E2B26)),
),
fillColor: Color(0xFF1A1814),
filled: true,
),
)NEW PATTERN:
TextField(
decoration: InputDecoration(
labelText: 'Enter text',
hintText: 'Placeholder text',
),
)
// Theme handles: border, radius, fill color, focus states, paddingOLD PATTERN:
Chip(
label: Text('Chip'),
backgroundColor: Color(0xFF211F1B),
side: BorderSide(color: Color(0xFF2E2B26)),
)NEW PATTERN:
Chip(
label: const Text('Chip'),
)
// Theme handles: background, border, selected state, label styleOLD PATTERN:
showDialog(
context: context,
builder: (context) => AlertDialog(
backgroundColor: Color(0xFF1A1814),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
title: Text('Confirm'),
content: Text('Are you sure?'),
),
)NEW PATTERN:
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Confirm'),
content: const Text('Are you sure?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text('Confirm'),
),
],
),
)
// Theme handles: background color, border radius, button stylingOLD PATTERN:
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(32)),
),
backgroundColor: Color(0xFF1A1814),
builder: (context) => Container(
child: ...
),
)NEW PATTERN:
showModalBottomSheet(
context: context,
builder: (context) => DraggableScrollableSheet(
expand: false,
builder: (context, scrollController) => Container(
child: ...
),
),
)
// Theme handles: background, shape, drag handleTier 1 - Critical Auth Screens (Week 4):
login_screen.dart- Update form styling, button colors, error statesregistration_screen.dart- Update form styling, multi-step designsplash_screen.dart- Update logo/branding, loading indicator
Tier 2 - Main Navigation (Week 5):
main_layout.dart- Update bottom navigation theme, FAB stylinghome_screen.dart- Update feed cards, story rings, chips, loading statesdiscovery_screen.dart- Update swipe cards, filter panel, buttons
Tier 3 - Pet Management (Week 6):
add_pet_screen.dart- Update form, multi-step stepper stylingpet_profile_screen.dart- Update tabs, cards, action buttonshealth_tab.dart- Update tabs, chart styling, card layouts
Tier 4 - Social Features (Week 7):
create_post_screen.dart- Update form, media picker, previewpost_detail_screen.dart- Update comment form, interaction buttonschat_screen.dart- Update message bubbles, input field, indicatorsnotifications_screen.dart- Update list styling, action buttons
Tier 5 - Marketplace (Week 8):
marketplace_screen.dart- Update product cards, search, filtersproduct_detail_screen.dart- Update gallery, price display, buttonscart_screen.dart- Update item cards, checkout floworder_history_screen.dart- Update order list, status indicators
For each screen, follow this pattern:
// BEFORE: Hardcoded colors
Container(
color: Color(0xFFD4845A),
padding: EdgeInsets.all(16),
child: Text('Title'),
)
// AFTER: Theme-based styling
Container(
color: Theme.of(context).colorScheme.primary,
padding: const EdgeInsets.all(16),
child: Text(
'Title',
style: Theme.of(context).textTheme.titleLarge,
),
)-
Color References:
// Replace all Color(0xFFD4845A) with: Theme.of(context).colorScheme.primary // Replace all Color(0xFF0F0E0C) with: Theme.of(context).colorScheme.background
-
Padding Constants:
// Replace arbitrary padding values with: const EdgeInsets.all(8) // spacingSm const EdgeInsets.all(16) // spacingMd const EdgeInsets.all(24) // spacingLg
-
Border Radius:
// Replace arbitrary radius values with: BorderRadius.circular(8) // radiusMd BorderRadius.circular(12) // radiusLg BorderRadius.circular(16) // radiusXl
-
Typography:
// Replace GoogleFonts.dmSans() with: Theme.of(context).textTheme.bodyMedium // Replace GoogleFonts.playfairDisplay() with: Theme.of(context).textTheme.headlineSmall
These screens need implementation with Material Design 3:
Location: lib/views/onboarding/
- welcome_screen.dart
- signup_screen.dart
- create_first_pet_screen.dart
- pet_details_screen.dart
- enable_notifications_screen.dart
Example: WelcomeScreen
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Hero image/logo
Image.asset('assets/petsphere_logo.png', height: 200),
// Title
Text(
'Welcome to PetSphere',
style: Theme.of(context).textTheme.displaySmall,
textAlign: TextAlign.center,
),
// Subtitle
Text(
'Connect, care, and celebrate your pets',
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Theme.of(context).colorScheme.onBackground,
),
textAlign: TextAlign.center,
),
// CTA Buttons
Column(
children: [
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => context.push('/signup'),
child: const Text('Get Started'),
),
),
SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: () => context.push('/login'),
child: const Text('Sign In'),
),
),
],
),
],
),
),
),
);
}
}Location: lib/views/profile_screen.dart
class ProfileScreen extends ConsumerWidget {
const ProfileScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Profile'),
actions: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () => context.push('/profile/edit'),
),
],
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
// Profile Header Card
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
// Avatar
CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(userImageUrl),
),
const SizedBox(height: 16),
// Name
Text(
'User Name',
style: Theme.of(context).textTheme.headlineSmall,
),
// Bio
Text(
'Pet lover since 2020',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
),
),
const SizedBox(height: 24),
// Pet Collection
Text(
'My Pets',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
spacing: 12,
childAspectRatio: 0.8,
),
itemCount: pets.length,
itemBuilder: (context, index) => PetCard(pet: pets[index]),
),
],
),
);
}
}Location: lib/views/care_goals_screen.dart
Location: lib/views/gamification_screen.dart
Location: lib/views/community/
Location: lib/views/settings_screen.dart (already exists, needs redesign)
Before marking a screen complete, verify:
- Color contrast: 4.5:1 for normal text, 3:1 for large text
- Touch targets: All interactive elements ≥48dp
- Focus indicators: Visible focus rings on all buttons/inputs
- Screen reader labels: All images have semantic labels
- Keyboard navigation: All features accessible via keyboard
Run this in the Flutter inspector to verify theme is properly applied:
void validateTheme(BuildContext context) {
final theme = Theme.of(context);
print('Primary Color: ${theme.colorScheme.primary}');
print('Surface Color: ${theme.colorScheme.surface}');
print('Body Large Font Size: ${theme.textTheme.bodyLarge?.fontSize}');
print('Button Height: 48dp (check in inspector)');
print('Corner Radius: Various (check in components)');
}Test on these devices before completing:
| Device | OS | Version | Status |
|---|---|---|---|
| iPhone 14 | iOS | 16.0+ | [ ] |
| iPhone SE | iOS | 14.0+ | [ ] |
| Pixel 6 | Android | 12 | [ ] |
| Pixel 4a | Android | 11 | [ ] |
| iPad Air | iPadOS | 15.0+ | [ ] |
| Tablet (Android) | Android | 12 | [ ] |
- Update
main.dartto useAppThemeV2 - Copy
app_theme_v2_material3.darttolib/theme/ - Test app launches with new theme
- Verify all colors are correct in inspector
- Migrate button components
- Migrate card styling
- Migrate form styling
- Migrate dialog/bottom sheet styling
- Tier 1: Auth screens (3 screens)
- Tier 2: Main navigation (3 screens)
- Tier 3: Pet management (3 screens)
- Tier 4: Social features (4 screens)
- Tier 5: Marketplace (4 screens)
- Implement onboarding flow
- Implement profile management
- Implement care goals screen
- Implement gamification dashboard
- Implement settings screen
- Run
flutter analyze- 0 errors - Run accessibility audit
- Test on iOS devices
- Test on Android devices
- Test on web (if applicable)
- Verify dark mode on all screens
Problem: New theme colors not showing.
Solution:
// Verify import
import 'theme/app_theme_v2_material3.dart';
// Verify usage in main.dart
theme: AppThemeV2.darkTheme,
// Hard refresh (clear cache)
flutter clean
flutter pub get
flutter runProblem: Text not using correct font/size.
Solution:
// Always use theme text styles
Text(
'Title',
style: Theme.of(context).textTheme.titleLarge,
)
// NOT:
Text(
'Title',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
)Problem: Button heights vary across screens.
Solution:
// The theme sets minimumSize to 48dp
// Don't override with custom padding
ElevatedButton(
onPressed: () {},
child: const Text('Button'),
// Don't add padding here - theme handles it
)-
Performance Optimization (Week 11)
- Profile app performance
- Optimize large list views (marketplace, feed)
- Implement lazy loading where needed
-
Analytics Integration
- Track screen views
- Track button clicks
- Track form submissions
-
User Testing
- Conduct usability testing
- Gather feedback on new design
- Iterate based on user feedback
-
Release Preparation
- Update app store screenshots
- Write release notes
- Plan staged rollout
- Material Design 3 Documentation
- Flutter Material Design 3 Guide
- Google Fonts Documentation
- WCAG 2.1 Guidelines
Questions? Refer to DESIGN_SYSTEM_SPECIFICATION.md or PETSPHERE_UI_UX_REDESIGN_AUDIT.md for detailed design context.