Files
FocusBuddy/ui-design-spec.md
2025-11-27 14:00:13 +08:00

24 KiB
Raw Permalink Blame History

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 (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:

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:

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:

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 (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:

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:

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:

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: 上架应用商店