# UI Design Specification for FocusBuddy **Version**: 1.0 **Target Platforms**: iOS & Android (responsive) **Framework**: Flutter **Design Philosophy**: Calm • Gentle • Accessible • Neurodivergent-Friendly **Implementation Status**: MVP 已完成 --- ## 1. Core Principles - **Low Stimulation**: Avoid bright colors, sharp edges, fast animations - **Emotional Safety**: No red error messages, no countdown pressure - **Clarity Over Cleverness**: One primary action per screen - **Offline-First UX**: Assume no internet; no loading spinners --- ## 2. Color Palette | Role | Hex | Usage | |------|-----|-------| | Primary (Calm Green) | `#A7C4BC` | Main buttons, active states | | Background | `#F8F6F2` | App background (warm off-white) | | Text Primary | `#5B6D6D` | Headings, large numbers | | Text Secondary | `#8A9B9B` | Descriptions, helper text | | Distraction Button | `#E0E0E0` | “I got distracted” button | | Success | `#88C9A1` | Achievement unlocked | > 🎨 All colors pass WCAG AA contrast ratio for accessibility. --- ## 3. Typography | Element | Font | Size | Weight | |--------|------|------|--------| | App Title | Nunito | 24px | Bold | | Timer Display | Nunito | 64px | ExtraBold | | Buttons | Nunito | 18px | SemiBold | | Body Text | Nunito | 16px | Regular | | Helper Text | Nunito | 14px | Light | > 💡 **Font Source**: [Google Fonts – Nunito](https://fonts.google.com/specimen/Nunito) (free, supports Latin + basic Unicode) --- ## 4. Core Screens ### 4.1 Home Screen **Layout:** ``` ┌─────────────────────────────────┐ │ ┌───────────────────────────┐ │ │ │ Points Card │ │ │ │ ┌──────┬──────┬────────┐ │ │ │ │ │⚡ 120│🎖️ Lv2│📅 Check │ │ │ │ │ └──────┴──────┴────────┘ │ │ │ └───────────────────────────┘ │ │ │ │ FocusBuddy │ ← App title (24px, centered) │ │ │ │ │ [ 25 minutes ] │ ← Duration display (28px) │ │ │ │ │ ┌───────────────────────┐ │ │ │ Start Focusing ▶ │ │ ← Primary button (#A7C4BC) │ └───────────────────────┘ │ │ │ │ "Tap 'I got distracted' │ ← Helper text (#8A9B9B) │ anytime — no guilt." │ ← 14px, centered │ │ │ │ │ 📊 History ⚙️ Settings │ ← Bottom navigation (text + icons) └─────────────────────────────────┘ ``` **Interactions:** - "Start Focusing" button: Scale animation (0.95 → 1.0) on press - Transitions to "During Focus" screen with fade-in (300ms) - Points card is tappable, navigates to Profile screen --- ### 4.2 During Focus Screen **Layout:** ``` ┌─────────────────────────────────┐ │ │ │ 24:37 │ ← Timer (64px, #5B6D6D) │ │ │ │ │ ┌───────────────────────┐ │ │ │ I got distracted │ │ ← Secondary button (#E0E0E0) │ └───────────────────────┘ │ │ │ │ ┌───────────────────────┐ │ │ │ ⏸ Pause │ │ ← Tertiary button (outlined) │ └───────────────────────┘ │ ← Border: 1px #A7C4BC │ │ └─────────────────────────────────┘ ``` **Interactions:** - **Timer**: Count-down display, updates every second - **"I got distracted"** → Opens bottom sheet with 4 options - **Pause** → Shows "Resume" button + elapsed time badge **Bottom Sheet: Distraction Types** ``` ┌─────────────────────────────────┐ │ What pulled you away? │ ← Title (16px, #5B6D6D) │ │ │ 📱 Scrolling social media │ ← Option 1 (tap to select) │ 👥 Got interrupted │ ← Option 2 │ 😰 Felt overwhelmed │ ← Option 3 │ 💭 Just zoned out │ ← Option 4 │ │ └─────────────────────────────────┘ ``` **Feedback after selection:** - Toast message: "It happens. Let's gently come back." (3s) - Auto-dismiss bottom sheet - Timer continues running --- ### 4.3 Focus Complete Screen **Layout:** ``` ┌─────────────────────────────────┐ │ │ │ ✨ │ ← Success icon │ │ │ You focused for │ ← Headline (20px, #5B6D6D) │ 24 minutes │ ← Large number (32px, bold) │ │ │ ┌─────────────────────────┐ │ │ │ Total Today: 47 mins │ │ ← Stats card (#F8F6F2 bg) │ │ Distractions: 2 times │ │ ← Body text (16px) │ │ │ │ │ │ "Showing up is half │ │ ← Random encouragement │ │ the battle." │ │ ← Italic, #8A9B9B │ └─────────────────────────┘ │ │ │ │ ┌───────────────────────┐ │ │ │ Start Another │ │ ← Primary button │ └───────────────────────┘ │ │ │ └─────────────────────────────────┘ ``` **Interactions:** - "Start Another" → Navigates to Home screen - Shows random encouragement message from `assets/encouragements.json` --- ### 4.4 History Screen **Layout:** ``` ┌─────────────────────────────────┐ │ 📊 Your Focus Journey │ ← Header (24px) │ │ │ ┌──────────────────────────┐ │ │ │ Today's Summary │ │ │ │ Total: 47 mins │ │ │ │ Sessions: 2 │ │ │ │ Distractions: 3 │ │ │ └──────────────────────────┘ │ │ │ │ ┌──────────────────────────┐ │ │ │ Session 1: 25 mins │ │ │ │ • 2 distractions │ │ │ │ • 10:00 AM - 10:25 AM │ │ │ └──────────────────────────┘ │ │ │ │ ┌──────────────────────────┐ │ │ │ Session 2: 22 mins │ │ │ │ • 1 distraction │ │ │ │ • 11:00 AM - 11:22 AM │ │ │ └──────────────────────────┘ │ │ │ └─────────────────────────────────┘ ``` **Interactions:** - Tap session card → Navigates to Session Detail screen - Empty state: Shows message "No sessions yet. Start your first focus session!" --- ### 4.5 Settings Screen **Layout:** ``` ┌─────────────────────────────────┐ │ ⚙️ Settings │ │ │ │ ┌─ Focus Settings ──────────┐ │ │ │ Default Duration: │ │ │ │ • 25 minutes (selected) │ │ │ │ • 15 minutes │ │ │ │ • 5 minutes │ │ │ └───────────────────────────┘ │ │ │ │ ┌─ Language ────────────────┐ │ │ │ English (selected) │ │ │ │ 中文 │ │ │ │ 日本語 │ │ │ │ 한국어 │ │ │ │ Español │ │ │ │ Deutsch │ │ │ │ Français │ │ │ │ Português │ │ │ │ Русский │ │ │ │ हिन्दी │ │ │ │ Bahasa Indonesia │ │ │ │ Italiano │ │ │ │ العربية │ │ │ └───────────────────────────┘ │ │ │ │ ┌─ About ───────────────────┐ │ │ │ Privacy Policy │ │ │ │ Terms of Service │ │ │ │ Version 1.0.0 │ │ │ └───────────────────────────┘ │ │ │ └─────────────────────────────────┘ ``` **Interactions:** - Tap duration option → Updates default duration - Tap language option → Updates app language - Tap links → Opens respective pages ### 4.6 Profile Screen **Layout:** ``` ┌─────────────────────────────────┐ │ 🧑 Profile │ │ │ │ ┌───────────────────────────┐ │ │ │ Points: 120 │ │ │ │ Level: 2 │ │ │ │ Consecutive Check-ins: 5 │ │ │ └───────────────────────────┘ │ │ │ │ ┌───────────────────────────┐ │ │ │ Achievements │ │ │ │ • First Focus Session │ │ │ │ • 5 Sessions Completed │ │ │ │ • 100 Points Earned │ │ │ └───────────────────────────┘ │ │ │ └─────────────────────────────────┘ ``` **Interactions:** - Shows user's points, level, and achievements - Shows consecutive check-in streak ### 4.7 Onboarding Screen **Layout:** ``` ┌─────────────────────────────────┐ │ │ │ FocusBuddy │ ← App title │ │ │ ┌───────────────────────────┐ │ │ │ │ │ │ │ No guilt. │ │ │ │ No shame. │ │ │ │ Just gentle focus. │ │ │ │ │ │ │ └───────────────────────────┘ │ │ │ │ Learn to focus without the │ │ pressure of perfection. │ │ │ │ ┌───────────────────────┐ │ │ │ Get Started │ │ ← Primary button │ └───────────────────────┘ │ │ │ └─────────────────────────────────┘ ``` **Interactions:** - "Get Started" → Navigates to Home screen - Only shown once (first launch) --- ## 5. Component Specifications ### 5.1 Primary Button **Visual:** - Background: `#A7C4BC` - Text: `#FFFFFF`, 18px, SemiBold - Height: 56px - Border radius: 16px - Shadow: 0px 4px 12px rgba(167, 196, 188, 0.3) **States:** ``` Normal: opacity 1.0, scale 1.0 Pressed: opacity 0.9, scale 0.95 (150ms ease-out) Disabled: opacity 0.5, grayscale 100% ``` **Flutter Implementation:** ```dart ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, minimumSize: Size(double.infinity, 56), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), elevation: 4, ), child: Text('Start Focusing', style: AppTextStyles.buttonText), onPressed: () {}, ) ``` --- ### 5.2 Secondary Button (Distraction Button) **Visual:** - Background: `#E0E0E0` - Text: `#5B6D6D`, 18px, SemiBold - Height: 48px - Border radius: 12px - No shadow (flat design) **States:** ``` Normal: background #E0E0E0 Pressed: background #D5D5D5 ``` --- ### 5.3 Timer Display **Visual:** - Font: Nunito ExtraBold - Size: 64px - Color: `#5B6D6D` - Letter spacing: 2px (monospace feel) **Flutter Implementation:** ```dart Text( '24:37', style: AppTextStyles.timerDisplay, ), ``` --- ### 5.4 Bottom Sheet (Distraction Selector) **Visual:** - Background: `#FFFFFF` - Border radius: 24px 24px 0 0 - Height: 60% of screen (max 400px) - Drag handle: 4px × 32px rounded bar, `#E0E0E0` **Options:** - Each row: 56px height - Icon: 24px, `#8A9B9B` - Text: 16px Regular, `#5B6D6D` - Divider: 1px, `#F0F0F0` **Animation:** - Slide up: 300ms ease-out - Backdrop: Fade to 0.5 opacity black ### 5.5 Points Card **Visual:** - Background: Gradient from `#A7C4BC1A` to `#A7C4BC0D` - Border: 1px solid `#A7C4BC33` - Border radius: 16px - Padding: 16px - Contains points, level, and check-in status **Flutter Implementation:** ```dart Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.primary.withOpacity(0.1), AppColors.primary.withOpacity(0.05), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), border: Border.all( color: AppColors.primary.withOpacity(0.2), width: 1, ), ), child: Row( // Points, level, check-in status ), ) ``` --- ## 6. Animations & Micro-interactions ### 6.1 Screen Transitions - **Cross-fade**: 300ms ease-in-out for all screen transitions - **No slide transitions** to avoid motion sickness ### 6.2 Button Interactions - **Primary Button**: Scale animation (0.95 → 1.0) on press - **Secondary Button**: Background color change on press - **Text Button**: Underline appears on hover ### 6.3 Loading States - **App Launch**: Simple circular progress indicator - **Data Loading**: Skeleton screens for list items --- ## 7. Responsive Design ### 7.1 Screen Sizes **Small (< 5.5"):** - Timer: 56px (reduce from 64px) - Button height: 48px (reduce from 56px) - Padding: 16px (reduce from 24px) **Large (> 6.5"):** - Keep default sizes - Max content width: 400px (centered) **Tablet (7"+):** - Use 2-column layout for History screen - Timer centered with max 500px container --- ### 7.2 Safe Areas **iOS:** - Respect notch: Use `SafeArea` widget - Bottom nav: 20px padding above home indicator **Android:** - Edge-to-edge: Use `WindowInsets` - Navigation bar: Semi-transparent overlay --- ## 8. Accessibility ### 8.1 Screen Reader Support **Labels:** - Timer: "24 minutes and 37 seconds remaining" - Distraction button: "Record a distraction, no penalty" - Slider: "Focus duration, 25 minutes, adjustable from 5 to 60" **Announcements:** - Focus start: "Focus session started" - Distraction logged: "Distraction recorded. It happens." - Focus complete: "Session complete. You focused for 24 minutes." --- ### 8.2 High Contrast Mode **When system high contrast enabled:** - Increase all borders to 2px - Button text: Pure black `#000000` - Background: Pure white `#FFFFFF` - Disable shadows and gradients --- ### 8.3 Font Scaling **Support dynamic type:** - Small: 0.85× base sizes - Large: 1.2× base sizes - Max: 1.5× (prevent overflow) **Test at:** - iOS: Settings → Accessibility → Display → Text Size - Android: Settings → Accessibility → Font size --- ## 9. Dark Mode (Future Enhancement) **Not in MVP**, but color mappings ready: | Light Mode | Dark Mode | |-----------|-----------| | `#F8F6F2` (bg) | `#1A1A1A` | | `#A7C4BC` (primary) | `#88A89F` (dimmer) | | `#5B6D6D` (text) | `#E0E0E0` | | `#FFFFFF` (cards) | `#2A2A2A` | --- ## 10. Design Assets Checklist ### 10.1 Required Lottie Files - [ ] `calm-particles.json` (background animation) - [ ] `success-sparkle.json` (focus complete) - [ ] `achievement-shimmer.json` (badge unlock) **Source:** [LottieFiles](https://lottiefiles.com) (search "calm", "gentle", "success") --- ### 10.2 App Icons **Sizes needed:** - **iOS:** 1024×1024 (App Store), 180×180, 120×120, 87×87, 80×80, 60×60 - **Android:** 512×512 (Play Store), 192×192, 144×144, 96×96, 72×72, 48×48 **Design:** - Main symbol: Gentle wave or breathing circle - Background: `#A7C4BC` gradient to `#88C9A1` - Style: Minimal, rounded, approachable --- ### 10.3 Screenshots (for stores) **Required shots (6.5" iPhone):** 1. Home screen with "Start Focusing" button 2. During focus with timer + distraction button 3. Focus complete with achievement badge 4. History screen with weekly chart 5. Settings with theme preview 6. (Optional) User testimonial overlay **Text overlays:** - "Focus without guilt" - "Track gently, improve naturally" - "Made for neurodivergent minds" --- ## 11. Implementation Details ### 11.1 Flutter Packages **Core Dependencies:** ```yaml dependencies: flutter: ^3.10.0-290.4.beta flutter_localizations: ^0.1.0 cupertino_icons: ^1.0.8 hive: ^2.2.3 # 本地存储 hive_flutter: ^1.1.0 flutter_local_notifications: ^17.0.0 # 通知 permission_handler: ^11.0.0 # 权限管理 path_provider: ^2.1.0 # 文件路径 shared_preferences: ^2.2.0 # 简单键值存储 intl: ^0.20.2 # 日期格式化和国际化 google_fonts: ^6.1.0 # Google Fonts (Nunito) get_it: ^7.7.0 # 依赖注入框架 ``` ### 11.2 Folder Structure ``` lib/ ├── main.dart ├── components/ │ ├── control_buttons.dart │ ├── distraction_button.dart │ └── timer_display.dart ├── l10n/ │ ├── app_en.arb │ ├── app_zh.arb │ └── ... (12 more languages) ├── models/ │ ├── achievement_config.dart │ ├── distraction_type.dart │ ├── focus_session.dart │ ├── user_progress.dart │ └── *.g.dart (generated files) ├── screens/ │ ├── complete_screen.dart │ ├── focus_screen.dart │ ├── history_screen.dart │ ├── home_screen.dart │ ├── onboarding_screen.dart │ ├── profile_screen.dart │ ├── session_detail_screen.dart │ └── settings_screen.dart ├── services/ │ ├── achievement_service.dart │ ├── di.dart │ ├── encouragement_service.dart │ ├── notification_service.dart │ ├── points_service.dart │ ├── service_locator.dart │ └── storage_service.dart └── theme/ ├── app_colors.dart ├── app_text_styles.dart └── app_theme.dart ``` ### 11.3 Theme Definition **AppColors Class:** ```dart class AppColors { static const primary = Color(0xFFA7C4BC); static const background = Color(0xFFF8F6F2); static const textPrimary = Color(0xFF5B6D6D); static const textSecondary = Color(0xFF8A9B9B); static const distractionButton = Color(0xFFE0E0E0); static const success = Color(0xFF88C9A1); static const white = Color(0xFFFFFFFF); // Method to create color with custom alpha static Color withValues({required double alpha}) { return Color.fromRGBO(255, 255, 255, alpha); } } ``` **AppTextStyles Class:** ```dart class AppTextStyles { static const appTitle = TextStyle( fontFamily: 'Nunito', fontSize: 24, fontWeight: FontWeight.bold, color: AppColors.textPrimary, ); static const timerDisplay = TextStyle( fontFamily: 'Nunito', fontSize: 64, fontWeight: FontWeight.w800, letterSpacing: 2, color: AppColors.textPrimary, ); static const buttonText = TextStyle( fontFamily: 'Nunito', fontSize: 18, fontWeight: FontWeight.w600, color: AppColors.white, ); // Additional text styles... } ``` ``` --- ## 12. Quality Assurance Checklist ### 12.1 Visual QA - [x] All colors match design system - [x] Fonts render correctly on iOS/Android - [x] Animations run smoothly - [x] No pixel shifts when rotating - [x] Safe areas respected on all devices ### 12.2 Interaction QA - [x] Buttons have press states - [x] Timer counts down accurately - [x] Bottom sheet dismisses on backdrop tap - [x] Settings persist after app restart - [x] Language changes apply immediately ### 12.3 Accessibility QA - [x] Screen reader announces all elements - [x] Font scaling doesn't break layout - [x] Minimum touch target: 44×44 (iOS) / 48×48 (Android) --- ## Appendix: Encouragement Messages Library Store in `assets/encouragements.json`: ```json [ "Showing up is half the battle.", "Every minute counts.", "You're learning, not failing.", "Gentleness is strength.", "Progress over perfection.", "Your effort matters.", "Small steps, big journey.", "Be kind to your brain.", "You're doing your best.", "One moment at a time.", "Focus is a practice, not a trait.", "It's okay to take breaks.", "You came back — that's what matters.", "Celebrate trying, not just succeeding.", "Your attention is valid." ] ``` **Usage:** Randomly select one message per focus completion. --- **Document Status:** ✅ MVP 已实现 **Last Updated:** 2025年11月27日 **Next Steps:** 上架应用商店