24 KiB
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
#A7C4BC1Ato#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
SafeAreawidget - 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:
#A7C4BCgradient to#88C9A1 - Style: Minimal, rounded, approachable
10.3 Screenshots (for stores)
Required shots (6.5" iPhone):
- Home screen with "Start Focusing" button
- During focus with timer + distraction button
- Focus complete with achievement badge
- History screen with weekly chart
- Settings with theme preview
- (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: 上架应用商店