743 lines
24 KiB
Markdown
743 lines
24 KiB
Markdown
# 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:** 上架应用商店 |