# UI Design Guidelines - AI Study Assistant ## 🎨 DESIGN SYSTEM OVERVIEW ### Core Design Philosophy - **Clean & Modern**: Minimalist interface with purposeful use of color and space - **Educational Focus**: UI elements designed to support learning, not distract - **Accessibility First**: High contrast ratios, readable fonts, and clear visual hierarchy - **Responsive Design**: Seamless experience across mobile, tablet, and web --- ## 🎨 COLOR PALETTE ### Primary Colors (New EPVC Color Scheme) ```dart class AppColors { // Primary Brand Colors static const Color primaryTeal = Color(0xFF82C9BD); // Main teal color - PRIMARY static const Color primaryOrange = Color(0xFFF68D2D); // Accent orange - SECONDARY // Gradient Colors static const Color gradientStart = Color(0xFF82C9BD); // Teal gradient start static const Color gradientEnd = Color(0xFF6AB8A8); // Darker teal gradient end // Secondary Colors static const Color secondaryTeal = Color(0xFF6AB8A8); // Darker teal static const Color accentTeal = Color(0xFF5AA69A); // Lighter teal accent static const Color lightOrange = Color(0xFFF7A960); // Lighter orange // Neutral Colors static const Color background = Color(0xFFF8F9FA); // Light gray background static const Color surface = Color(0xFFFFFFFF); // White surfaces static const Color cardBackground = Color(0xFFFFFFFF); // White cards // Text Colors static const Color textPrimary = Color(0xFF1A1A1A); // Primary text static const Color textSecondary = Color(0xFF6B7280); // Secondary text static const Color textHint = Color(0xFF9CA3AF); // Hint text // Status Colors static const Color success = Color(0xFF10B981); // Green for success static const Color warning = Color(0xFFF59E0B); // Amber for warnings static const Color error = Color(0xFFEF4444); // Red for errors static const Color info = Color(0xFF3B82F6); // Blue for info // Interactive Colors static const Color buttonPrimary = Color(0xFF82C9BD); // Primary button (teal) static const Color buttonAccent = Color(0xFFF68D2D); // Accent button (orange) static const Color buttonSecondary = Color(0xFFE5E7EB); // Secondary button static const Color iconActive = Color(0xFF82C9BD); // Active icons (teal) static const Color iconInactive = Color(0xFF9CA3AF); // Inactive icons // Chat Specific Colors static const Color chatBubbleStudent = Color(0xFF82C9BD); // Student messages (teal) static const Color chatBubbleAI = Color(0xFFF3F4F6); // AI messages static const Color chatInputBackground = Color(0xFFF8F9FA); // Input background static const Color chatSendButton = Color(0xFF82C9BD); // Send button (teal) } ``` ### Color Usage Guidelines #### Primary Colors (70% usage) - **Primary Teal (#82C9BD)**: Main actions, navigation, important CTAs, backgrounds, frequent UI elements - **Primary Orange (#F68D2D)**: Accent buttons, highlights, achievements, important notifications (used sparingly) - **Secondary Teal**: Hover states, secondary actions, supporting elements #### Neutral Colors (25% usage) - **Background**: Page backgrounds, card backgrounds - **Surface**: Cards, modals, dropdowns - **Text Colors**: Hierarchical text organization #### Status Colors (5% usage) - **Success**: Quiz completion, correct answers - **Warning**: Low mastery, upcoming deadlines - **Error**: Network errors, validation failures - **Info**: System notifications, help text #### Color Distribution Strategy - **Teal (#82C9BD)**: 60% of color usage - Primary brand color for backgrounds, main actions, navigation - **Orange (#F68D2D)**: 10% of color usage - Accent color for CTAs, highlights, special buttons - **Neutral Colors**: 30% of color usage - Backgrounds, surfaces, text hierarchy --- ## 📝 TYPOGRAPHY ### Font Family ```dart class AppTypography { // Primary Font Family (System fonts for consistency) static const String primaryFont = 'SF Pro Display'; // iOS static const String secondaryFont = 'Roboto'; // Android static const String webFont = 'Inter'; // Web // Font Weights static const FontWeight thin = FontWeight.w100; static const FontWeight light = FontWeight.w300; static const FontWeight regular = FontWeight.w400; static const FontWeight medium = FontWeight.w500; static const FontWeight semiBold = FontWeight.w600; static const FontWeight bold = FontWeight.w700; static const FontWeight extraBold = FontWeight.w800; } ``` ### Text Styles ```dart class AppTextStyles { // Headings static const TextStyle h1 = TextStyle( fontSize: 32, fontWeight: FontWeight.bold, color: AppColors.textPrimary, height: 1.2, ); static const TextStyle h2 = TextStyle( fontSize: 24, fontWeight: FontWeight.semiBold, color: AppColors.textPrimary, height: 1.3, ); static const TextStyle h3 = TextStyle( fontSize: 20, fontWeight: FontWeight.semiBold, color: AppColors.textPrimary, height: 1.4, ); // Body Text static const TextStyle bodyLarge = TextStyle( fontSize: 16, fontWeight: FontWeight.regular, color: AppColors.textPrimary, height: 1.5, ); static const TextStyle bodyMedium = TextStyle( fontSize: 14, fontWeight: FontWeight.regular, color: AppColors.textPrimary, height: 1.5, ); static const TextStyle bodySmall = TextStyle( fontSize: 12, fontWeight: FontWeight.regular, color: AppColors.textSecondary, height: 1.4, ); // Button Text static const TextStyle buttonLarge = TextStyle( fontSize: 16, fontWeight: FontWeight.semiBold, color: Colors.white, height: 1.2, ); static const TextStyle buttonMedium = TextStyle( fontSize: 14, fontWeight: FontWeight.medium, color: Colors.white, height: 1.2, ); // Caption and Label static const TextStyle caption = TextStyle( fontSize: 11, fontWeight: FontWeight.regular, color: AppColors.textHint, height: 1.3, ); static const TextStyle label = TextStyle( fontSize: 12, fontWeight: FontWeight.medium, color: AppColors.textSecondary, height: 1.3, ); } ``` --- ## 🎯 ICONOGRAPHY ### Icon Sets - **Primary**: Cupertino Icons (iOS-style consistency) - **Secondary**: Material Icons (for Android compatibility) - **Custom**: Educational icons for specific features ### Icon Guidelines - **Size**: 24px for standard icons, 16px for compact, 32px for large - **Weight**: Medium (consistent across the app) - **Color**: Use `iconActive` for active states, `iconInactive` for inactive - **Meaning**: Clear, universally understood symbols ### Key Icons ```dart class AppIcons { // Navigation static const IconData home = CupertinoIcons.home; static const IconData search = CupertinoIcons.search; static const IconData profile = CupertinoIcons.person_circle; static const IconData settings = CupertinoIcons.settings; static const IconData menu = CupertinoIcons.bars; // Actions static const IconData send = CupertinoIcons.paperplane_fill; static const IconData add = CupertinoIcons.add; static const IconData edit = CupertinoIcons.pencil; static const IconData delete = CupertinoIcons.trash; static const IconData check = CupertinoIcons.check_mark; // Educational static const IconData book = CupertinoIcons.book; static const IconData quiz = CupertinoIcons.question_circle; static const IconData progress = CupertinoIcons.chart_bar; static const IconData lightbulb = CupertinoIcons.lightbulb; static const IconData trophy = CupertinoIcons.trophy; // Status static const IconData success = CupertinoIcons.check_mark_circled; static const IconData warning = CupertinoIcons.exclamationmark_triangle; static const IconData error = CupertinoIcons.xmark_circle; static const IconData info = CupertinoIcons.info_circle; } ``` --- ## 📱 COMPONENTS ### Buttons #### Primary Button ```dart class PrimaryButton extends StatelessWidget { final String text; final VoidCallback onPressed; final bool isLoading; final bool isDisabled; const PrimaryButton({ Key? key, required this.text, required this.onPressed, this.isLoading = false, this.isDisabled = false, }) : super(key: key); @override Widget build(BuildContext context) { return AnimatedContainer( duration: const Duration(milliseconds: 200), height: 48, decoration: BoxDecoration( gradient: LinearGradient( colors: isDisabled ? [AppColors.buttonSecondary, AppColors.buttonSecondary] : [AppColors.gradientStart, AppColors.gradientEnd], ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppColors.primaryBlue.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(12), onTap: isDisabled || isLoading ? null : onPressed, child: Center( child: isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : Text( text, style: AppTextStyles.buttonLarge, ), ), ), ), ); } } ``` #### Secondary Button ```dart class SecondaryButton extends StatelessWidget { final String text; final VoidCallback onPressed; final bool isDisabled; const SecondaryButton({ Key? key, required this.text, required this.onPressed, this.isDisabled = false, }) : super(key: key); @override Widget build(BuildContext context) { return Container( height: 48, decoration: BoxDecoration( color: AppColors.buttonSecondary, borderRadius: BorderRadius.circular(12), border: Border.all( color: AppColors.primaryBlue.withOpacity(0.3), width: 1, ), ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(12), onTap: isDisabled ? null : onPressed, child: Center( child: Text( text, style: AppTextStyles.buttonLarge.copyWith( color: isDisabled ? AppColors.textHint : AppColors.primaryBlue, ), ), ), ), ), ); } } ``` ### Cards #### Standard Card ```dart class StandardCard extends StatelessWidget { final Widget child; final EdgeInsetsGeometry? padding; final EdgeInsetsGeometry? margin; final VoidCallback? onTap; final bool hasShadow; const StandardCard({ required this.child, this.padding, this.onTap, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 8, offset: Offset(0, 2), ), BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 1, offset: Offset(0, 1), ), ], ), child: Material( color: Colors.transparent, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(16), child: Padding( padding: padding ?? EdgeInsets.all(16), child: child, ), ), ), ); } } ``` #### Interactive Card ```dart class InteractiveCard extends StatefulWidget { final Widget child; final EdgeInsetsGeometry? padding; final VoidCallback? onTap; final bool isSelected; const InteractiveCard({ required this.child, this.padding, this.onTap, this.isSelected = false, }); @override State createState() => _InteractiveCardState(); } class _InteractiveCardState extends State { bool isHovered = false; @override Widget build(BuildContext context) { return MouseRegion( onEnter: (_) => setState(() => isHovered = true), onExit: (_) => setState(() => isHovered = false), child: AnimatedContainer( duration: Duration(milliseconds: 200), decoration: BoxDecoration( color: widget.isSelected ? AppColors.primaryBlue.withOpacity(0.1) : AppColors.surface, borderRadius: BorderRadius.circular(16), border: widget.isSelected ? Border.all(color: AppColors.primaryBlue, width: 2) : null, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(isHovered ? 0.12 : 0.08), blurRadius: isHovered ? 12 : 8, offset: Offset(0, isHovered ? 4 : 2), ), BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 1, offset: Offset(0, 1), ), ], ), child: Material( color: Colors.transparent, child: InkWell( onTap: widget.onTap, borderRadius: BorderRadius.circular(16), child: Padding( padding: widget.padding ?? EdgeInsets.all(16), child: widget.child, ), ), ), ), ); } } ``` ### Input Fields #### Text Input ```dart class AppTextInput extends StatelessWidget { final String? label; final String? hint; final String? errorText; final TextEditingController controller; final bool obscureText; final TextInputType keyboardType; final VoidCallback? onTap; final ValueChanged? onChanged; final bool isDisabled; const AppTextInput({ Key? key, this.label, this.hint, this.errorText, required this.controller, this.obscureText = false, this.keyboardType = TextInputType.text, this.onTap, this.onChanged, this.isDisabled = false, }) : super(key: key); @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (label != null) ...[ Text( label!, style: AppTextStyles.label, ), const SizedBox(height: 8), ], Container( decoration: BoxDecoration( color: isDisabled ? AppColors.buttonSecondary : AppColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all( color: errorText != null ? AppColors.error : AppColors.primaryBlue.withOpacity(0.3), width: 1, ), ), child: TextField( controller: controller, obscureText: obscureText, keyboardType: keyboardType, onTap: onTap, onChanged: onChanged, enabled: !isDisabled, decoration: InputDecoration( hintText: hint, hintStyle: AppTextStyles.bodyMedium.copyWith( color: AppColors.textHint, ), border: InputBorder.none, contentPadding: const EdgeInsets.all(16), ), style: AppTextStyles.bodyMedium, ), ), if (errorText != null) ...[ const SizedBox(height: 4), Text( errorText!, style: AppTextStyles.caption.copyWith( color: AppColors.error, ), ), ], ], ); } } ``` --- ## 📱 MODERN LAYOUT PATTERNS ### Dashboard Layout Based on the reference design, implement a modern card-based dashboard with: #### Grid Layout System ```dart class DashboardGrid extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( padding: EdgeInsets.all(16), child: GridView.count( crossAxisCount: 2, crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 1.2, children: [ _buildQuickActionCard( icon: Icons.chat, title: "Ask Tutor", subtitle: "Get help with your questions", color: AppColors.primaryBlue, onTap: () => _navigateToChat(), ), _buildQuickActionCard( icon: Icons.quiz, title: "Take Quiz", subtitle: "Test your knowledge", color: AppColors.primaryTeal, onTap: () => _navigateToQuiz(), ), _buildQuickActionCard( icon: Icons.trending_up, title: "Progress", subtitle: "Track your learning", color: AppColors.primaryOrange, onTap: () => _navigateToProgress(), ), _buildQuickActionCard( icon: Icons.book, title: "Study Materials", subtitle: "Access learning resources", color: AppColors.secondaryBlue, onTap: () => _navigateToMaterials(), ), ], ), ); } Widget _buildQuickActionCard({ required IconData icon, required String title, required String subtitle, required Color color, required VoidCallback onTap, }) { return InteractiveCard( onTap: onTap, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 48, height: 48, decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Icon( icon, color: color, size: 24, ), ), SizedBox(height: 12), Text( title, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.textPrimary, ), ), SizedBox(height: 4), Text( subtitle, style: TextStyle( fontSize: 12, color: AppColors.textSecondary, ), ), ], ), ); } } ``` #### Content Cards ```dart class ContentCard extends StatelessWidget { final String title; final String description; final String progress; final Color accentColor; final VoidCallback onTap; const ContentCard({ required this.title, required this.description, required this.progress, required this.accentColor, required this.onTap, }); @override Widget build(BuildContext context) { return InteractiveCard( onTap: onTap, padding: EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: AppColors.textPrimary, ), ), SizedBox(height: 8), Text( description, style: TextStyle( fontSize: 14, color: AppColors.textSecondary, ), ), ], ), ), Container( width: 40, height: 40, decoration: BoxDecoration( color: accentColor.withOpacity(0.1), borderRadius: BorderRadius.circular(20), ), child: Icon( Icons.arrow_forward, color: accentColor, size: 20, ), ), ], ), SizedBox(height: 16), Container( height: 4, decoration: BoxDecoration( color: AppColors.buttonSecondary, borderRadius: BorderRadius.circular(2), ), child: FractionallySizedBox( alignment: Alignment.centerLeft, widthFactor: double.parse(progress), child: Container( decoration: BoxDecoration( color: accentColor, borderRadius: BorderRadius.circular(2), ), ), ), ), SizedBox(height: 8), Text( '${(double.parse(progress) * 100).toInt()}% Complete', style: TextStyle( fontSize: 12, color: AppColors.textHint, ), ), ], ), ); } } ``` #### Navigation Bar ```dart class ModernBottomNavigation extends StatelessWidget { final int currentIndex; final ValueChanged onTap; const ModernBottomNavigation({ required this.currentIndex, required this.onTap, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: AppColors.surface, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: Offset(0, -2), ), ], ), child: SafeArea( child: Padding( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildNavItem( icon: Icons.home, label: "Home", index: 0, ), _buildNavItem( icon: Icons.chat, label: "Chat", index: 1, ), _buildNavItem( icon: Icons.quiz, label: "Quiz", index: 2, ), _buildNavItem( icon: Icons.person, label: "Profile", index: 3, ), ], ), ), ), ); } Widget _buildNavItem({ required IconData icon, required String label, required int index, }) { final isActive = currentIndex == index; final color = isActive ? AppColors.primaryBlue : AppColors.iconInactive; return GestureDetector( onTap: () => onTap(index), child: Container( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: isActive ? AppColors.primaryBlue.withOpacity(0.1) : Colors.transparent, borderRadius: BorderRadius.circular(12), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon( icon, color: color, size: 24, ), SizedBox(height: 4), Text( label, style: TextStyle( color: color, fontSize: 12, fontWeight: isActive ? FontWeight.w600 : FontWeight.normal, ), ), ], ), ), ); } } ``` ### Chat Interface ```dart class ModernChatInterface extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ // Chat Header Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surface, border: Border( bottom: BorderSide( color: AppColors.buttonSecondary, width: 1, ), ), ), child: Row( children: [ CircleAvatar( backgroundColor: AppColors.primaryBlue.withOpacity(0.1), child: Icon( Icons.smart_toy, color: AppColors.primaryBlue, ), ), SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "AI Tutor", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.textPrimary, ), ), Text( "Always here to help", style: TextStyle( fontSize: 12, color: AppColors.textSecondary, ), ), ], ), ), Icon( Icons.more_vert, color: AppColors.iconInactive, ), ], ), ), // Chat Messages Expanded( child: Container( color: AppColors.background, child: ListView.builder( padding: EdgeInsets.all(16), itemCount: messages.length, itemBuilder: (context, index) { final message = messages[index]; return _buildMessageBubble(message); }, ), ), ), // Chat Input Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surface, border: Border( top: BorderSide( color: AppColors.buttonSecondary, width: 1, ), ), ), child: Row( children: [ Expanded( child: Container( decoration: BoxDecoration( color: AppColors.chatInputBackground, borderRadius: BorderRadius.circular(24), border: Border.all( color: AppColors.primaryBlue.withOpacity(0.3), width: 1, ), ), child: TextField( decoration: InputDecoration( hintText: "Ask your question...", hintStyle: TextStyle( color: AppColors.textHint, ), border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), ), ), ), ), SizedBox(width: 12), Container( width: 48, height: 48, decoration: BoxDecoration( gradient: LinearGradient( colors: [AppColors.primaryBlue, AppColors.primaryTeal], begin: Alignment.centerLeft, end: Alignment.centerRight, ), borderRadius: BorderRadius.circular(24), ), child: Icon( Icons.send, color: Colors.white, size: 20, ), ), ], ), ), ], ); } Widget _buildMessageBubble(Message message) { final isUser = message.isUser; return Container( margin: EdgeInsets.only(bottom: 16), child: Row( mainAxisAlignment: isUser ? MainAxisAlignment.end : MainAxisAlignment.start, children: [ if (!isUser) ...[ CircleAvatar( radius: 16, backgroundColor: AppColors.primaryBlue.withOpacity(0.1), child: Icon( Icons.smart_toy, color: AppColors.primaryBlue, size: 16, ), ), SizedBox(width: 8), ], Flexible( child: Container( constraints: BoxConstraints( maxWidth: MediaQuery.of(context).size.width * 0.7, ), padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: isUser ? AppColors.primaryBlue : AppColors.chatBubbleAI, borderRadius: BorderRadius.circular(16), ), child: Text( message.text, style: TextStyle( color: isUser ? Colors.white : AppColors.textPrimary, fontSize: 14, ), ), ), ), if (isUser) ...[ SizedBox(width: 8), CircleAvatar( radius: 16, backgroundColor: AppColors.primaryOrange.withOpacity(0.1), child: Icon( Icons.person, color: AppColors.primaryOrange, size: 16, ), ), ], ], ), ); } } ``` --- ## 🎭 ANIMATIONS ### Animation Principles - **Purposeful**: Every animation should enhance user understanding - **Smooth**: Use easing functions that feel natural - **Fast**: Respect user time, keep animations under 300ms - **Consistent**: Use similar timing across the app ### Standard Animation Durations ```dart class AppAnimations { static const Duration fast = Duration(milliseconds: 150); static const Duration medium = Duration(milliseconds: 250); static const Duration slow = Duration(milliseconds: 350); static const Duration extraSlow = Duration(milliseconds: 500); } ``` ### Curves ```dart class AppCurves { static const Curve easeIn = Curves.easeIn; static const Curve easeOut = Curves.easeOut; static const Curve easeInOut = Curves.easeInOut; static const Curve bounceIn = Curves.bounceIn; static const Curve elasticOut = Curves.elasticOut; } ``` ### Common Animations #### Fade Transition ```dart class FadeIn extends StatefulWidget { final Widget child; final Duration duration; const FadeIn({ Key? key, required this.child, this.duration = AppAnimations.medium, }) : super(key: key); @override State createState() => _FadeInState(); } class _FadeInState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: widget.duration, vsync: this, ); _animation = Tween( begin: 0.0, end: 1.0, ).animate(CurvedAnimation( parent: _controller, curve: AppCurves.easeIn, )); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return FadeTransition( opacity: _animation, child: widget.child, ); } } ``` #### Slide Transition ```dart class SlideIn extends StatefulWidget { final Widget child; final Duration duration; final Offset begin; final Offset end; const SlideIn({ Key? key, required this.child, this.duration = AppAnimations.medium, this.begin = const Offset(0, 0.3), this.end = Offset.zero, }) : super(key: key); @override State createState() => _SlideInState(); } class _SlideInState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: widget.duration, vsync: this, ); _animation = Tween( begin: widget.begin, end: widget.end, ).animate(CurvedAnimation( parent: _controller, curve: AppCurves.easeOut, )); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SlideTransition( position: _animation, child: widget.child, ); } } ``` #### Scale Animation ```dart class ScaleIn extends StatefulWidget { final Widget child; final Duration duration; const ScaleIn({ Key? key, required this.child, this.duration = AppAnimations.medium, }) : super(key: key); @override State createState() => _ScaleInState(); } class _ScaleInState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: widget.duration, vsync: this, ); _animation = Tween( begin: 0.8, end: 1.0, ).animate(CurvedAnimation( parent: _controller, curve: AppCurves.elasticOut, )); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ScaleTransition( scale: _animation, child: widget.child, ); } } ``` --- ## 📐 LAYOUT GUIDELINES ### Spacing System ```dart class AppSpacing { // Base spacing unit (8px) static const double xs = 4; // 0.5x static const double sm = 8; // 1x static const double md = 16; // 2x static const double lg = 24; // 3x static const double xl = 32; // 4x static const double xxl = 48; // 6x static const double xxxl = 64; // 8x } ``` ### Border Radius ```dart class AppBorderRadius { static const double sm = 8; static const double md = 12; static const double lg = 16; static const double xl = 20; static const double xxl = 24; static const double round = 1000; // For circles } ``` ### Screen Breakpoints ```dart class AppBreakpoints { static const double mobile = 480; static const double tablet = 768; static const double desktop = 1024; static const double largeDesktop = 1440; } ``` --- ## 🎨 SCREEN-SPECIFIC DESIGNS ### Login Screen - **Background**: Gradient from `gradientStart` to `gradientEnd` - **Logo**: Centered with fade-in animation - **Form**: White card with subtle shadow - **Buttons**: Primary gradient button for login, secondary for signup ### Student Dashboard - **Header**: App bar with gradient background - **Cards**: Grid layout with mastery progress bars - **Navigation**: Bottom navigation with active state indicators - **Animations**: Cards slide in from bottom on load ### Chat Interface - **Background**: Light gray (`chatInputBackground`) - **Messages**: Different colors for student vs AI - **Input**: Rounded input field with send button - **Animations**: Messages slide in from sides ### Quiz Screen - **Timer**: Circular progress indicator - **Questions**: Card-based layout - **Options**: Radio buttons with hover states - **Progress**: Linear progress bar at top --- ## 🌙 DARK MODE ### Dark Color Palette ```dart class AppDarkColors { // Background Colors static const Color background = Color(0xFF121212); static const Color surface = Color(0xFF1E1E1E); static const Color cardBackground = Color(0xFF2D2D2D); // Text Colors static const Color textPrimary = Color(0xFFFFFFFF); static const Color textSecondary = Color(0xFFB3B3B3); static const Color textHint = Color(0xFF808080); // Keep primary colors the same static const Color primaryBlue = AppColors.primaryBlue; static const Color primaryTeal = AppColors.primaryTeal; static const Color primaryOrange = AppColors.primaryOrange; } ``` ### Implementation Guidelines - **Automatic**: Follow system dark mode preference - **Manual**: Toggle in app settings - **Consistency**: All screens must support both themes - **Animation**: Smooth transition between themes --- ## 📱 RESPONSIVE DESIGN ### Mobile (< 768px) - **Layout**: Single column, scrollable - **Navigation**: Bottom navigation bar - **Cards**: Full width with horizontal padding - **Typography**: Base sizes as defined ### Tablet (768px - 1024px) - **Layout**: Two-column where appropriate - **Navigation**: Side drawer or top navigation - **Cards**: Grid layout (2-3 columns) - **Typography**: Slightly larger base sizes ### Desktop (> 1024px) - **Layout**: Multi-column, fixed width centered - **Navigation**: Top navigation bar - **Cards**: Grid layout (3-4 columns) - **Typography**: Larger base sizes, better readability --- ## 🎯 ACCESSIBILITY ### Color Contrast - **Normal Text**: Minimum 4.5:1 contrast ratio - **Large Text**: Minimum 3:1 contrast ratio - **Interactive Elements**: Minimum 3:1 contrast ratio ### Typography - **Minimum Size**: 14px for body text - **Line Height**: 1.5 for better readability - **Font Weight**: Regular or medium for body text ### Focus States - **Visible**: All interactive elements have visible focus states - **Consistent**: Same focus style across the app - **Keyboard**: Full keyboard navigation support ### Screen Reader Support - **Labels**: All images and icons have alt text - **Semantic**: Use semantic HTML elements - **Announcements**: Important changes are announced --- ## 🚀 PERFORMANCE ### Animation Performance - **60 FPS**: All animations should maintain 60 FPS - **GPU**: Use GPU-accelerated animations where possible - **Simplify**: Avoid complex animations on low-end devices ### Asset Optimization - **Images**: WebP format with appropriate sizes - **Icons**: SVG icons where possible - **Fonts**: Subset fonts to reduce size ### Bundle Size - **Tree Shaking**: Remove unused code - **Lazy Loading**: Load features on demand - **Compression**: Compress all assets --- ## 📋 DESIGN CHECKLIST ### Before Implementation - [ ] Color palette defined and consistent - [ ] Typography scale established - [ ] Component library created - [ ] Animation system implemented - [ ] Accessibility guidelines reviewed ### During Implementation - [ ] Components follow design system - [ ] Animations are smooth and purposeful - [ ] Responsive design works on all breakpoints - [ ] Dark mode is supported - [ ] Accessibility features are implemented ### Before Release - [ ] All screens reviewed for consistency - [ ] Performance tested on target devices - [ ] Accessibility tested with screen readers - [ ] User testing completed - [ ] Design documentation updated --- ## 🔄 DESIGN SYSTEM MAINTENANCE ### Regular Updates - **Monthly**: Review usage analytics and user feedback - **Quarterly**: Update components and add new ones - **Annually**: Major design system updates ### Version Control - **Semantic Versioning**: Use semantic versioning for releases - **Changelog**: Maintain detailed changelog - **Migration**: Provide migration guides for breaking changes ### Documentation - **Living Document**: Keep documentation up to date - **Examples**: Provide code examples for all components - **Guidelines**: Maintain usage guidelines and best practices --- *Last Updated: 2026-05-06* *Version: 1.0.0* *Design System Owner: UI/UX Team*