redesign: duolingo-pattern onboarding, no gradient, pressable button

- Nunito font replacing Plus Jakarta Sans
- SButton: Stack-based 3D pressable (dark shadow layer + top layer translates on press)
- SCard: flat border-based selection, no shadows
- SProgressBar: 4px thin bar, animated fill
- All screens: white bg, no gradients
- Duolingo layout: illustration top zone, content below, sticky button
This commit is contained in:
mav
2026-05-28 16:34:04 +02:00
parent 30cee5a486
commit 6311088256
9 changed files with 1168 additions and 638 deletions

306
DESIGN_DOC.md Normal file
View File

@@ -0,0 +1,306 @@
# Shaynee Flutter — Design System (Duolingo-study edition)
## 1. How Duolingo Screens Actually Work (first 20 screens)
### Master Layout Template (used on ~80% of screens)
```
┌─────────────────────────────────┐ safe area top
│ [←/×] ████████░░░░░░ [skip] │ nav row: 48px tall, 16px padding
├─────────────────────────────────┤
│ │
│ [ILLUSTRATION / MASCOT] │ top zone: ~40% of remaining height
│ centered, ~220px │ image sits here, NO text
│ │
├─────────────────────────────────┤
│ │
│ Headline │ 24px h-padding
│ (bold, 22-26px, dark) │
│ │
│ Sub text (15px, gray) │
│ │
│ ┌─────────────────────────┐ │ option cards: 16px h-padding
│ │ [icon] Label [radio○] │ │ card height: 62px
│ └─────────────────────────┘ │ gap between cards: 8px
│ ┌─────────────────────────┐ │
│ │ [icon] Label [radio○] │ │
│ └─────────────────────────┘ │
│ ┌─────────────────────────┐ │
│ │ [icon] Label [radio○] │ │
│ └─────────────────────────┘ │
│ │
├─────────────────────────────────┤
│ ┌─────────────────────────┐ │ button zone: 16px h-padding
│ │ CONTINUE │ │ button: 52px tall
│ └─────────────────────────┘ │
└─────────────────────────────────┘ safe area bottom
```
### Nav Row breakdown
- Left: back arrow `←` in 36×36 box with gray border OR `×` to exit
- Center: thin progress bar (4px height, full remaining width)
- Right: "Skip" as plain gray text link (no box, no border)
- Background: white, no shadow
### Illustration Zone rules
- NO text inside illustration zone
- Image centered horizontally
- ~40% of screen height (not fixed pixel — scales)
- Mascot/character always faces slightly right or center
- White background behind image (no colored backdrop)
### Card style (EXACT)
```
height: 62px
borderRadius: 12px
background: white (default) / #f7f7f7 tint (hover)
border: 1.5px solid #e5e5e5 (default)
2px solid #58CC02 (Duolingo green, selected)
→ for Shaynee: 2px solid #5B4FCF
icon box: 40×40, radius 10, bg #f7f7f7, icon 22px
label: left-aligned, bold 16px, dark #3c3c3c
radio circle: right side, 22px, empty or filled+check
gap between: 8px
h-padding: 16px from screen edge
```
### Pressable Button (THE KEY THING — not box-shadow, uses border-bottom trick)
```
height: 52px
borderRadius: 16px
background: #58CC02 (Duo green) → Shaynee: #5B4FCF
border-bottom: 4px solid #58A700 → Shaynee: 4px solid #3D32A8
(this IS the shadow — not box-shadow, not gradient)
text: WHITE, ExtraBold, 15px, uppercase or title-case
disabled state: bg #e5e5e5, border-bottom #b0b0b0, text gray
pressed state: translateY(+4px), border-bottom: 0 (collapses — button "sinks")
width: full (16px h-padding each side)
```
### Specific screen patterns
**Screen 1 — Splash/Welcome**
```
BG: white (NOT gradient)
Center: Duo mascot (large, ~280px, animated float)
Below mascot:
"Learn a language\nfor free." (bold 28px, centered)
Bottom stack:
[GET STARTED] green pressable button
[I already have an account] — plain text link, no button style
```
**Screen 2 — Reason/Goal (first question)**
```
Nav: [×] ░░░░░░░░░░ [no skip]
Illustration: topic-specific art (school bag, brain, etc), centered
Headline: "What is your reason for learning?" (22px bold)
Cards: list of 5-7 options (career, family, travel, school, brain, other)
Bottom: [CONTINUE] — disabled until selection
```
**Screen 3 — Language selection**
```
Nav row with progress
Grid of flag+name cards (2 columns or scrollable list)
Searchable (search bar at top of list area)
Bottom: [CONTINUE]
```
**Screen 4-5 — Proficiency / experience**
```
Illustration centered
Big question text
3-4 cards: "I'm new" / "I know a little" / "I'm comfortable" / "It's complicated"
[CONTINUE]
```
**Screen 6-7 — Daily goal**
```
Illustration: Duo with calendar or clock
Question: "Choose your daily goal"
Cards: Casual (5min) / Regular (10min) / Serious (15min) / Intense (20min)
Each card has icon + name + description (3 lines in card)
Selected card: green border + light green bg
[CONTINUE]
```
**Screen 8-10 — First mini lesson (before signup)**
```
Quiz layout:
Top: progress bar (green fill) + × + hearts ♥♥♥
Middle: question illustration
Question text below illustration
Answer options (A/B/C/D) as square/rounded cards in 2×2 grid or vertical
Bottom: [CHECK] button (green, disabled until pick)
After correct: [CHECK] becomes green checkmark animation, then [CONTINUE]
After wrong: button turns red, explanation text appears below
```
**Screen 11 — Lesson complete / celebration**
```
Confetti animation full screen
Mascot celebrating (arms up)
"You did it!" bold centered
XP earned badge
[CONTINUE]
```
**Screen 12 — Streak intro**
```
Flame icon (large, centered)
"You're on a streak!"
Explanation of how streaks work
[CONTINUE]
```
**Screen 13-16 — Signup gate**
```
Illustration: Duo with "Save your progress"
"Create a profile to save your progress"
[CREATE PROFILE] green button
[Maybe later] plain text link (NOT a button)
```
**Screen 17-20 — Account creation**
```
Individual input screens, one field per screen:
Enter your age → Enter your name → Enter email → Set password
Each screen: input field centered, big, full-width below headline
[CONTINUE] stays disabled until field valid
```
---
## 2. Shaynee Design Rules (derived from Duolingo study)
### RULE 1: NO gradients anywhere (kills premium feel on cheap gradient)
### RULE 2: White backgrounds on all content screens
### RULE 3: Pressable button = border-bottom trick, NOT box-shadow
### RULE 4: One illustration zone (top 40%) + one content zone (bottom 60%)
### RULE 5: Button always stuck to bottom, full width, 16px h-padding
### RULE 6: Cards: 62px, border-based selection, no shadows
### RULE 7: Mascot only on: splash, analysing complete, result reveal
### RULE 8: "Skip" / "Maybe later" = plain text, never in a button/box
---
## 3. Shaynee Color System (no gradients)
```dart
// Backgrounds
bgPage: #FAFAFE // very light lavender-white
bgSurface: #FFFFFF // pure white (cards, inputs)
// Primary (Indigo — replaces Duo's green)
primary: #5B4FCF
primaryDark: #3D32A8 // button bottom border
primaryLight: #EAE7FB // selected card bg tint
primaryBorder: #5B4FCF // selected card border
// Text
textHead: #1C1A2E // nearly black
textBody: #4B4B6B // medium dark
textSub: #9898AA // gray subtext
textDisabled: #C4C4D4
// Borders
borderLight: #E8E6F0 // card default border
borderMedium: #D0CDEA // input default
// Accent
accent: #FF7EB3 // pink — celebrations, badges only
accentLight: #FFF0F6
// States
success: #4CAF50
error: #FF4B4B
```
---
## 4. Typography — Nunito (Google Fonts)
```dart
// Weights to use:
// 900 Black → main headlines (36px+)
// 800 ExtraBold → section heads (22-28px), button text
// 700 Bold → card labels (16px), input text
// 600 SemiBold → body (15px), subtitles
// 500 Medium → captions (12-13px), subtext
// 400 Regular → (avoid — too thin)
// Scale:
headline1: Nunito 900, 36px, lh 1.15
headline2: Nunito 800, 26px, lh 1.2
title: Nunito 800, 22px, lh 1.25
subtitle: Nunito 600, 15px, lh 1.5
body: Nunito 600, 15px, lh 1.5
caption: Nunito 500, 12px, lh 1.4
button: Nunito 800, 15px, lh 1.0, letterSpacing 0.3
```
---
## 5. Component Specs (Flutter implementation)
### SButton (Pressable)
```dart
// Use GestureDetector with onTapDown/onTapUp for press animation
// AnimatedContainer: on press, translate Y +4, remove bottom border
decoration: BoxDecoration(
color: SColors.primary, // flat, NO gradient
borderRadius: BorderRadius.circular(16),
border: Border(
bottom: BorderSide(
color: SColors.primaryDark, // #3D32A8
width: 4, // THIS is the "shadow"
),
),
),
// On press: transform translate(0, 4), border bottom 0
// Duration: 80ms
```
### SCard (Option row)
```dart
height: 62,
decoration: BoxDecoration(
color: selected ? SColors.primaryLight : SColors.bgSurface,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: selected ? SColors.primary : SColors.borderLight,
width: selected ? 2.0 : 1.5,
),
),
// NO shadow
// Icon box: 40×40, radius 10, bg #f4f2ff (selected) or #f7f7f7
// Radio: right side, 22×22 circle
```
### SProgressBar
```dart
height: 4,
borderRadius: BorderRadius.circular(2),
// Track: SColors.borderLight
// Fill: SColors.primary
// Animate width change: 300ms ease-out
```
---
## 6. Screen Flow & Rules per Screen
| Screen | BG | Illustration zone | Nav | Button text |
|--------|----|--------------------|-----|-------------|
| Splash | White | Shaynee hero (center, large) | none | auto-advance |
| Intro/Welcome | White | Feature art or stats visual | none | "Get started" |
| Name | White | Small Shaynee avatar (top, 100px) | ← + 1/5 + skip | "Continue" |
| Skin type | White | Skin illustration (120px) | ← + 2/5 | "Continue" |
| Age | White | Age illustration (120px) | ← + 3/5 | "Continue" |
| Concerns | White | Skincare illustration (120px) | ← + 4/5 | "Continue" |
| Goal | White | Goal illustration (120px) | ← + 5/5 | "See my results" |
| Analysing | White + spinner | Shaynee pulsing (center) | none | auto-advance |
| Result | White | Shaynee hero mascot (top 35%) | none | "Start my routine" |
| Sign up | White | none | × | "Save my results" |