diff --git a/CLAUDE.md b/CLAUDE.md index 4d298f2..dd2575a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,123 +1,213 @@ -# TabataGo — CLAUDE.md -> Lis ce fichier EN ENTIER avant chaque session. C'est la constitution du projet. +# TabataFit — CLAUDE.md +> "Apple Fitness+ for Tabata" — Lis ce fichier EN ENTIER avant chaque session. -## Projet -Application mobile Tabata (iOS + Android) construite avec Expo SDK 52 + Expo Router v3. -Modèle freemium via RevenueCat. Analytics via PostHog. Offline-first. +--- -## Environnement de développement -**Test sur device physique via Expo Go** — pas de simulateur iOS. -- Scanner le QR code affiché par `npx expo start` avec l'app Expo Go sur le téléphone -- Le téléphone et le Mac doivent être sur le **même réseau Wi-Fi** -- En cas de problème réseau : `npx expo start --tunnel` (utilise ngrok, plus lent mais fiable) +## 🎯 Vision -### Contraintes Expo Go à respecter -- **Pas de modules natifs custom** — uniquement les modules inclus dans le SDK Expo Go -- `react-native-purchases` (RevenueCat) **ne fonctionne PAS dans Expo Go** → mocker le paywall en dev, tester sur build EAS uniquement -- `expo-notifications` fonctionne partiellement dans Expo Go → tester les notifications sur build EAS dev -- Modules **compatibles Expo Go SDK 52** (utilisables sans build) : - `expo-av`, `expo-haptics`, `expo-keep-awake`, `expo-router`, `expo-secure-store`, - `@react-native-async-storage/async-storage`, `expo-localization`, `react-native-posthog` +**TabataFit est l'Apple Fitness+ du Tabata.** -### Workflow de test -1. **Expo Go** → développement UI, timer, audio, exercices (90% du dev) -2. **EAS Build (Development)** → tester RevenueCat, notifications avancées -3. **EAS Build (Production)** → build final App Store / Play Store +Une expérience premium, video-first, guidée par des coachs, qui transforme 4 minutes d'exercice en une expérience de fitness immersive. -## Stack technique — règles non-négociables -| Domaine | Solution | Interdit | -|---|---|---| -| Framework | Expo SDK 52 (managed workflow) | Bare workflow sauf si absolument nécessaire | -| Navigation | Expo Router v3 (file-based) | React Navigation seul | -| State global | Zustand + AsyncStorage | Redux, MobX, Context pour state global | -| Timer engine | Date.now() delta dans un hook isolé | setInterval seul (drift inacceptable) | -| Audio | expo-av avec AVAudioSession | expo-audio (instable), react-native-sound | -| Paiements | react-native-purchases (RevenueCat) | IAP natif direct — **MOCKER en dev Expo Go** | -| Analytics | react-native-posthog | Firebase Analytics, Amplitude | -| Styles | StyleSheet.create() | Styles inline, Tailwind, NativeWind | -| Types | TypeScript strict (`"strict": true`) | any, @ts-ignore sauf justification | +*"Workouts that work. Beautifully."* + +--- + +## 📱 Produit + +### Positionnement +- **Analogy** : "If Apple made a Tabata app" +- **Focus** : Tabata/HIIT uniquement (pas multi-activité) +- **Durée** : 4-20 min (format Tabata) +- **Différenciateur** : Video-led + Coaching audio + Timer intelligent + +### Stack Technique +| Domaine | Solution | +|---------|----------| +| Framework | Expo SDK 52 (managed) | +| Navigation | Expo Router v3 | +| State | Zustand + AsyncStorage | +| Video | expo-av → HLS streaming | +| Audio | expo-av (coaching + music) | +| Animations | React Native Animated | +| Payments | RevenueCat | +| Analytics | PostHog | + +--- + +## 📚 Documentation + +| Document | Description | +|----------|-------------| +| `TabataFit_PRD_v2.0.md` | Product Requirements — features, roadmap | +| `TabataFit_PDD_v2.0.md` | Product Design — screens, UX, flows | +| `TabataFit_BDSD_v2.0.md` | Brand Design — colors, typography, style | + +**TOUJOURS lire ces documents avant de développer.** + +--- + +## 🏗️ Architecture -## Architecture — structure de fichiers ``` src/ features/ - timer/ - hooks/useTimerEngine.ts ← moteur central, AUCUN JSX - hooks/useTimerSync.ts ← synchronise audio + exercice sur les events timer - components/TimerDisplay.tsx ← affichage uniquement, reçoit tout par props - components/TimerControls.tsx ← boutons start/pause/stop/skip - types.ts ← TimerPhase, TimerState, TimerConfig - audio/ - hooks/useAudioEngine.ts ← gestion expo-av, preload, crossfade - hooks/useAudioSettings.ts ← préférences utilisateur (ambiance, volume) - data/tracks.ts ← catalogue des tracks (offline) - data/sounds.ts ← catalogue des signaux de phase - types.ts - exercises/ - hooks/useExercise.ts ← sélection, navigation entre exercices - components/ExerciseDisplay.tsx ← rendu selon la phase courante - components/ExerciseGif.tsx ← affichage GIF avec fallback - data/exercises.ts ← les 38 exercices (offline) - types.ts - programs/ - hooks/useProgram.ts - components/ProgramBuilder.tsx - data/defaultPrograms.ts - onboarding/ - hooks/useOnboarding.ts - screens/ ← 6 écrans (1 fichier par écran) - paywall/ - hooks/usePaywall.ts ← RevenueCat wrapper - components/PaywallScreen.tsx + home/ # Home tab - For You, Continue, Collections + workouts/ # Workouts tab - Categories, workout list + player/ # Active workout - Video, timer, stats + activity/ # Activity tab - Stats, trends, calendar + browse/ # Browse tab - Filters, trainers + profile/ # Profile tab - Settings, achievements shared/ - components/ ← Button, Card, Typography, etc. - hooks/ ← useHaptics, useKeepAwake, useAppState - utils/ ← formatTime, etc. - constants/ ← couleurs, durées par défaut - app/ ← Expo Router (fichiers de route uniquement) + components/ # Button, Card, VideoPlayer, etc. + hooks/ # useTimer, useVideo, useHaptics + utils/ # formatTime, etc. + constants/ # colors, typography, spacing + app/ # Expo Router routes (tabs)/ - index.tsx ← Home - history.tsx - settings.tsx - timer/index.tsx - programs/[id].tsx - onboarding/index.tsx - paywall/index.tsx + index.tsx # Home + workouts.tsx # Workouts + activity.tsx # Activity + browse.tsx # Browse + profile.tsx # Profile + player/ + [id].tsx # Workout player ``` -## Règles de code -1. **Un fichier = une responsabilité** — si un hook dépasse 150 lignes, il doit être découpé -2. **Toute logique métier dans les hooks** — les composants n'ont QUE du JSX + appel de hooks -3. **Barrel exports** — chaque feature expose un `index.ts` propre -4. **Tests colocalisés** — `ComponentName.test.tsx` dans le même dossier -5. **Pas d'effet secondaire dans le render** — tout dans useEffect ou les handlers -6. **Typage strict des events** — pas de `any` dans les callbacks de timer/audio +--- + +## 🎨 Design System + +### Couleurs Principales +```typescript +BACKGROUND: '#000000' // Pure black +SURFACE: '#1C1C1E' // Charcoal +BRAND: '#FF6B35' // Flame orange +REST: '#5AC8FA' // Ice blue +SUCCESS: '#30D158' // Energy green +``` + +### Phase Colors (Critique) +```typescript +PREP: '#FF9500' // Orange-yellow +WORK: '#FF6B35' // Flame orange +REST: '#5AC8FA' // Ice blue +COMPLETE: '#30D158' // Green +``` + +### Typography +- **Font**: Inter (Google Fonts) +- **Timer**: 96px, Black weight +- **Titles**: 34px/28px/22px +- **Body**: 17px + +--- + +## 📋 Priorités Développement + +### Phase 1 — MVP (Semaines 1-4) +1. ✅ Design system setup +2. 🔲 Home tab (Featured, Continue Watching) +3. 🔲 Workouts tab (Categories) +4. 🔲 Pre-workout detail screen +5. 🔲 Video player avec timer overlay +6. 🔲 Workout complete screen +7. 🔲 20 workouts (mock data) + +### Phase 2 — Core (Semaines 5-8) +1. 🔲 Activity tab (Stats, Calendar) +2. 🔲 Browse tab (Filters, Trainers) +3. 🔲 Profile tab (Settings) +4. 🔲 Apple Watch integration +5. 🔲 50 workouts total + +### Phase 3 — Premium (Semaines 9-12) +1. 🔲 Offline downloads +2. 🔲 Burn Bar +3. 🔲 Subscription system +4. 🔲 Achievements +5. 🔲 100+ workouts + +--- + +## 🧪 Test Environment + +**Expo Go sur device physique** — pas de simulateur. + +1. `npx expo start` +2. Scanner le QR code avec Expo Go +3. Même réseau Wi-Fi requis + +--- + +## 📝 Règles de Code + +1. **Un fichier = une responsabilité** +2. **Toute logique métier dans les hooks** +3. **Components = JSX uniquement** +4. **TypeScript strict** — pas de `any` +5. **Styles avec StyleSheet.create()** +6. **Dark mode only** — pas de light mode + +--- + +## 🎬 Contenu Video + +### Format Workout Video +- **Resolution**: 1080p minimum +- **Duration**: Match workout duration +- **Structure**: + - Intro (5s): Trainer greeting + - Prep (3s): 3-2-1 countdown + - Work (20s): Exercise demonstration + - Rest (10s): Recovery, next exercise preview + - Repeat for each round + - Outro (5s): Celebration, trainer sign-off + +### Trainers (5 au launch) +1. **Emma** — Energy queen, beginner-friendly +2. **Jake** — Strength focus +3. **Mia** — Form perfectionist +4. **Alex** — Cardio beast +5. **Sofia** — Chill but effective + +--- + +## 💰 Monetization + +### Free Tier +- 3 workouts free forever +- Basic stats +- Ads between workouts + +### Premium ($6.99/mo or $49.99/yr) +- Unlimited workouts +- Offline downloads +- Apple Watch integration +- Advanced stats +- No ads +- Family Sharing + +--- + +## 🚀 Commands -## Commandes du projet ```bash -npx expo start # dev — scanner le QR avec Expo Go -npx expo start --tunnel # si problème réseau Wi-Fi (ngrok) -npx expo start --clear # vider le cache Metro si comportement bizarre -jest --watchAll # tests en continu -eas build --profile development # build dev (pour tester RevenueCat, notifs) -eas build --platform ios # build TestFlight -npx expo export # bundle production +npx expo start # Development +npx expo start --tunnel # If network issues +npx expo start --clear # Clear cache +npx tsc --noEmit # Type check +eas build --profile dev # Dev build ``` -## Comment utiliser les skills +--- -Quand tu travailles sur une feature spécifique, lis le skill correspondant : -- Timer → `.claude/skills/timer/SKILL.md` -- Audio → `.claude/skills/audio/SKILL.md` -- Exercices → `.claude/skills/exercises/SKILL.md` -- Workflow général → `.claude/skills/workflow/SKILL.md` +## 📖 Comment Utiliser les Skills -## Priorité d'implémentation V1 -1. `useTimerEngine` + `TimerDisplay` (plein écran) -2. `useAudioEngine` + synchronisation avec timer -3. `ExerciseDisplay` + données des 38 exercices -4. Synchronisation triple timer × audio × exercice -5. Onboarding 6 écrans + mini-démo live -6. Paywall RevenueCat -7. Streak + historique -8. Notifications de rappel +Voir `.claude/skills/` pour les guides spécialisés. + +--- + +*Document updated: February 18, 2026* +*Version: 2.0* +*Project: TabataFit — Apple Fitness+ for Tabata* diff --git a/README.md b/README.md index 48dd63f..5cda777 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,75 @@ -# Welcome to your Expo app 👋 +# TabataFit -This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app). +> **Apple Fitness+ for Tabata** — The Premium HIIT Experience -## Get started +![Expo](https://img.shields.io/badge/Expo-52-black) +![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue) +![License](https://img.shields.io/badge/License-Proprietary-red) -1. Install dependencies +## Vision - ```bash - npm install - ``` +TabataFit est l'Apple Fitness+ du Tabata. Une expérience premium, video-first, guidée par des coachs, qui transforme 4 minutes d'exercice en une expérience de fitness immersive. -2. Start the app +## Features - ```bash - npx expo start - ``` +- 🎬 **Video-led workouts** — HD video demonstrations by professional trainers +- ⏱️ **Smart timer** — Tabata timer with work/rest phases +- 🔥 **Burn Bar** — Compare your calories with the community +- 📊 **Activity tracking** — Streaks, stats, and trends +- 🎵 **Music sync** — Curated playlists for each workout +- ⌚ **Apple Watch** — Heart rate and activity rings -In the output, you'll find options to open the app in a +## Tech Stack -- [development build](https://docs.expo.dev/develop/development-builds/introduction/) -- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/) -- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/) -- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo +- **Framework**: Expo SDK 52 +- **Navigation**: Expo Router v3 +- **State**: Zustand +- **Video**: expo-av (HLS streaming) +- **Payments**: RevenueCat +- **Analytics**: PostHog -You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction). - -## Get a fresh project - -When you're ready, run: +## Getting Started ```bash -npm run reset-project +# Install dependencies +npm install + +# Start development server +npx expo start + +# Run on device (scan QR with Expo Go) ``` -This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing. +## Documentation -## Learn more +| Document | Description | +|----------|-------------| +| [PRD v2.0](./TabataFit_PRD_v2.0.md) | Product Requirements | +| [PDD v2.0](./TabataFit_PDD_v2.0.md) | Product Design | +| [BDSD v2.0](./TabataFit_BDSD_v2.0.md) | Brand Design | -To learn more about developing your project with Expo, look at the following resources: +## Project Structure -- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides). -- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web. +``` +src/ + features/ + home/ # Home tab + workouts/ # Workouts browser + player/ # Video player + timer + activity/ # Stats & history + browse/ # Filters & trainers + profile/ # User settings + shared/ + components/ # Reusable UI + hooks/ # Custom hooks + constants/ # Design tokens +app/ # Expo Router routes +``` -## Join the community +## License -Join our community of developers creating universal apps. +Proprietary — All rights reserved. -- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute. -- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions. +--- + +Built with ❤️ for HIIT lovers diff --git a/TabataFit_BDSD_v2.0.md b/TabataFit_BDSD_v2.0.md new file mode 100644 index 0000000..704f1a9 --- /dev/null +++ b/TabataFit_BDSD_v2.0.md @@ -0,0 +1,594 @@ +# TabataFit — Brand Design Specification v2.0 +> Apple Liquid Glass Design for Tabata + +--- + +## Brand Positioning + +**TabataFit = Apple Fitness+ avec Liquid Glass (iOS 18.4)** + +| Attribute | Description | +|-----------|-------------| +| **Analogy** | "If Apple made a Tabata app in 2026" | +| **Vibe** | Premium, glassy, fluid, immersive | +| **Emotion** | Confident, empowering, sleek | +| **Differentiator** | Video-led + Liquid Glass UI | + +--- + +## 🪟 Liquid Glass System (iOS 18.4 Style) + +### Concept +Le **Liquid Glass** est le nouveau design language d'Apple qui combine : +- **Glassmorphism avancé** — Blur dynamique, transparence multicouche +- **Fluidité organique** — Formes arrondies, animations liquides +- **Lumière réactive** — Reflets, glows qui répondent au contenu +- **Profondeur atmosphérique** — Layers de verre empilés + +### Glass Layers + +```typescript +const GLASS = { + // Base glass (surfaces) + BASE: { + backgroundColor: 'rgba(255, 255, 255, 0.05)', + backdropFilter: 'blur(40px)', + borderWidth: 1, + borderColor: 'rgba(255, 255, 255, 0.1)', + shadowColor: '#000', + shadowOffset: { width: 0, height: 8 }, + shadowOpacity: 0.3, + shadowRadius: 32, + }, + + // Elevated glass (cards, modals) + ELEVATED: { + backgroundColor: 'rgba(255, 255, 255, 0.08)', + backdropFilter: 'blur(60px)', + borderWidth: 1, + borderColor: 'rgba(255, 255, 255, 0.15)', + shadowColor: '#000', + shadowOffset: { width: 0, height: 12 }, + shadowOpacity: 0.4, + shadowRadius: 48, + }, + + // Inset glass (input fields, controls) + INSET: { + backgroundColor: 'rgba(0, 0, 0, 0.2)', + backdropFilter: 'blur(20px)', + borderWidth: 1, + borderColor: 'rgba(255, 255, 255, 0.05)', + }, + + // Tinted glass (accent overlays) + TINTED: { + backgroundColor: 'rgba(255, 107, 53, 0.15)', // Brand tint + backdropFilter: 'blur(40px)', + borderWidth: 1, + borderColor: 'rgba(255, 107, 53, 0.3)', + }, +} +``` + +### Liquid Animations + +```typescript +const LIQUID = { + // Morphing shapes + MORPH: { + duration: 600, + easing: 'cubic-bezier(0.4, 0, 0.2, 1)', + }, + + // Ripple effect on tap + RIPPLE: { + scale: { from: 0.8, to: 1 }, + opacity: { from: 0.5, to: 0 }, + duration: 400, + }, + + // Breathing glow + BREATHE: { + scale: { from: 1, to: 1.02 }, + shadowRadius: { from: 20, to: 30 }, + duration: 2000, + loop: true, + }, + + // Slide with liquid easing + SLIDE: { + damping: 20, + stiffness: 300, + mass: 1, + }, +} +``` + +--- + +## Visual Identity + +### Logo Concept + +``` +┌─────────────────────────────┐ +│ │ +│ TABATA │ ← Bold, black +│ FIT │ ← Accent orange +│ │ +│ [Flame icon] │ ← Optional mark +│ │ +└─────────────────────────────┘ +``` + +### Brand Voice + +| DO | DON'T | +|----|-------| +| "Let's burn." | "Get ripped fast!" | +| "4 minutes to stronger." | "Lose weight now!" | +| "Your daily dose of HIIT." | "The #1 fitness app!" | +| Minimal, confident copy | Excessive exclamation marks!! | + +--- + +## Color Palette + +### Primary Colors + +``` +┌─────────────────────────────────────────────────────────┐ +│ │ +│ BLACK ████████████ #000000 Background │ +│ CHARCOAL ████████████ #1C1C1E Surfaces │ +│ SLATE ████████████ #2C2C2E Elevated │ +│ │ +│ FLAME ████████████ #FF6B35 Brand accent │ +│ FLAME LIGHT ████████████ #FF8C5A Highlights │ +│ │ +│ ICE ████████████ #5AC8FA Rest phases │ +│ GLOW ████████████ #FFD60A Achievement │ +│ ENERGY ████████████ #30D158 Success/Complete│ +│ │ +└─────────────────────────────────────────────────────────┘ +``` + +### Semantic Usage + +| Color | Hex | Usage | +|-------|-----|-------| +| **Black** | #000000 | Main background, video frames | +| **Charcoal** | #1C1C1E | Cards, raised surfaces | +| **Slate** | #2C2C2E | Modals, elevated elements | +| **Flame** | #FF6B35 | Work phase, CTAs, brand | +| **Ice** | #5AC8FA | Rest phase, calm states | +| **Glow** | #FFD60A | Achievement badges, streaks | +| **Energy** | #30D158 | Complete states, success | + +### Phase Colors (Critical) + +```typescript +const PHASE_COLORS = { + PREP: '#FF9500', // Orange-yellow - get ready + WORK: '#FF6B35', // Flame orange - WORK! + REST: '#5AC8FA', // Ice blue - recover + COMPLETE: '#30D158', // Energy green - done! +} +``` + +--- + +## Typography + +### Font Stack + +**Primary**: Inter (Google Fonts) +- Clean, modern, excellent readability +- Variable weight support +- Apple SF Pro alternative + +### Type Scale + +| Style | Size | Weight | Use Case | +|-------|------|--------|----------| +| **HERO** | 48px | 900 | Marketing, celebration | +| **TITLE_1** | 34px | 700 | Screen titles | +| **TITLE_2** | 28px | 700 | Section headers | +| **TITLE_3** | 22px | 600 | Card titles | +| **BODY** | 17px | 400 | Default text | +| **BODY_BOLD** | 17px | 600 | Emphasis | +| **CAPTION** | 15px | 400 | Metadata | +| **MICRO** | 13px | 400 | Small labels | +| **TIMER** | 96px | 900 | Countdown display | + +### Timer Typography (Special) + +```typescript +const TIMER_STYLES = { + // Main countdown number + NUMBER: { + fontFamily: 'Inter_900Black', + fontSize: 96, + fontVariant: ['tabular-nums'], // Monospace digits + letterSpacing: -2, + }, + + // Phase label (WORK, REST) + PHASE: { + fontFamily: 'Inter_700Bold', + fontSize: 24, + letterSpacing: 2, + textTransform: 'uppercase', + }, + + // Round indicator + ROUND: { + fontFamily: 'Inter_500Medium', + fontSize: 17, + fontVariant: ['tabular-nums'], + }, +} +``` + +--- + +## Spacing System + +```typescript +const SPACING = { + // Base unit: 4px + 0: 0, + 1: 4, + 2: 8, + 3: 12, + 4: 16, + 5: 20, + 6: 24, + 8: 32, + 10: 40, + 12: 48, + 16: 64, + + // Semantic + XS: 4, + SM: 8, + MD: 16, + LG: 24, + XL: 32, + XXL: 48, +} + +const LAYOUT = { + SCREEN_PADDING: 24, // Horizontal screen padding + CARD_RADIUS: 16, // Standard card radius + BUTTON_RADIUS: 12, // Button radius + TAB_BAR_HEIGHT: 80, // Bottom tab bar + STATUS_BAR: 44, // iOS status bar +} +``` + +--- + +## Component Styles + +### Cards + +```typescript +const CARD = { + CONTAINER: { + backgroundColor: '#1C1C1E', + borderRadius: 16, + overflow: 'hidden', + }, + + THUMBNAIL: { + aspectRatio: 16/9, + backgroundColor: '#2C2C2E', + }, + + CONTENT: { + padding: 16, + }, + + // Variants + FEATURED: { + borderRadius: 20, + }, + + COMPACT: { + flexDirection: 'row', + borderRadius: 12, + }, +} +``` + +### Buttons + +```typescript +const BUTTON = { + PRIMARY: { + backgroundColor: '#FF6B35', + paddingVertical: 16, + paddingHorizontal: 24, + borderRadius: 12, + alignItems: 'center', + justifyContent: 'center', + }, + + PRIMARY_TEXT: { + color: '#FFFFFF', + fontFamily: 'Inter_600SemiBold', + fontSize: 17, + letterSpacing: 0.5, + }, + + SECONDARY: { + backgroundColor: 'transparent', + borderWidth: 1, + borderColor: '#3A3A3C', + }, + + GHOST: { + backgroundColor: 'transparent', + }, +} +``` + +### Timer Display + +```typescript +const TIMER = { + CONTAINER: { + position: 'absolute', + bottom: 0, + left: 0, + right: 0, + padding: 24, + background: 'linear-gradient(transparent, rgba(0,0,0,0.8))', + }, + + NUMBER: { + fontFamily: 'Inter_900Black', + fontSize: 96, + color: '#FFFFFF', + textAlign: 'center', + }, + + PROGRESS_BAR: { + height: 4, + backgroundColor: 'rgba(255,255,255,0.2)', + borderRadius: 2, + marginTop: 16, + }, + + PROGRESS_FILL: { + height: '100%', + borderRadius: 2, + // Color based on phase + }, +} +``` + +--- + +## Animation Specifications + +### Timing Constants + +```typescript +const DURATION = { + INSTANT: 100, + FAST: 200, + NORMAL: 300, + SLOW: 500, + XSLow: 800, +} + +const EASING = { + // Standard iOS ease + DEFAULT: 'ease-out', + + // Spring animations + BOUNCY: { + damping: 15, + stiffness: 180, + }, + + GENTLE: { + damping: 20, + stiffness: 100, + }, +} +``` + +### Key Animations + +**Timer Countdown:** +```typescript +// Number pulses slightly each second +Animated.sequence([ + Animated.timing(scale, { toValue: 1.05, duration: 100 }), + Animated.timing(scale, { toValue: 1, duration: 100 }), +]) +``` + +**Progress Bar:** +```typescript +// Smooth linear fill during phase +Animated.timing(width, { + toValue: 100, + duration: phaseDuration, + easing: Easing.linear, +}) +``` + +**Phase Transition:** +```typescript +// Color crossfade +Animated.timing(colorProgress, { + toValue: 1, + duration: 300, +}) +``` + +**Workout Complete:** +```typescript +// Celebration with scale + fade +Animated.parallel([ + Animated.spring(scale, { toValue: 1, ...BOUNCY }), + Animated.timing(opacity, { toValue: 1, duration: 500 }), +]) +``` + +--- + +## Icon System + +Using SF Symbols / Ionicons equivalent: + +| Context | Icon | Size | +|---------|------|------| +| Home Tab | house.fill | 24 | +| Workouts Tab | flame.fill | 24 | +| Activity Tab | chart.bar.fill | 24 | +| Browse Tab | square.grid.2x2.fill | 24 | +| Profile Tab | person.fill | 24 | +| Play | play.fill | 20 | +| Pause | pause.fill | 20 | +| Close | xmark | 20 | +| Back | chevron.left | 20 | +| Forward | chevron.right | 20 | +| Heart | heart.fill | 20 | +| Search | magnifyingglass | 20 | + +--- + +## Video Player UI + +### Overlay Layout + +``` +┌─────────────────────────────────────────────┐ +│ [Close X] [♥︎] [···] │ ← Top bar +│ │ +│ │ +│ [VIDEO CONTENT] │ +│ │ +│ │ +│ │ +│ ┌─────────────────────────────────────────┐ │ +│ │ 🔥 WORK │ │ +│ │ │ │ +│ │ 00:14 │ │ ← Timer overlay +│ │ │ │ +│ │ Round 3 of 8 │ │ +│ │ ████████████░░░░ │ │ +│ └─────────────────────────────────────────┘ │ +└─────────────────────────────────────────────┘ +``` + +### Video Requirements + +- **Resolution**: 1080p minimum +- **Aspect**: 16:9 (landscape) or 9:16 (portrait mode) +- **Format**: HLS (m3u8) for streaming +- **Audio**: AAC, 128kbps minimum +- **Thumbnail**: JPG, same aspect ratio + +--- + +## Sound Design + +### Sound Effects + +| Event | Sound | Description | +|-------|-------|-------------| +| Phase Start | "ding" | Quick, bright chime | +| Count 3-2-1 | "tick" | Subtle tick sound | +| Workout Start | "whoosh" | Energy whoosh | +| Workout Complete | "success" | Celebratory chime | +| Button Tap | "tap" | Soft tap feedback | +| Streak Achieved | "fire" | Crackling fire | + +### Haptics + +| Event | Haptic | +|-------|--------| +| Phase change | Medium | +| Button tap | Light | +| Countdown tick | Selection | +| Workout complete | Success | +| Error | Error | + +--- + +## Dark Mode Only + +TabataFit is **dark mode only** — no light mode. This is a deliberate design choice matching Apple Fitness+ and creating an immersive, cinematic experience. + +Reasons: +1. Better video contrast +2. Less eye strain during workouts +3. Premium feel +4. Consistent with fitness studio lighting + +--- + +## Image Guidelines + +### Trainer Photos + +- Professional, high-quality headshots +- Warm, approachable expressions +- Fitness attire visible +- Consistent lighting style +- Background: Dark or studio setting + +### Workout Thumbnails + +- Action shot from the workout +- Clear exercise demonstration +- Trainer visible +- Dark/gradient background +- Text overlay: Title, duration, level + +### Collection Banners + +- 16:9 aspect ratio +- Composite of trainer + exercises +- Gradient overlay for text +- Brand accent color elements + +--- + +## Copy Guidelines + +### Tone + +- **Confident** but not arrogant +- **Encouraging** but not cheesy +- **Clear** and direct +- **Minimal** — let the content speak + +### Examples + +| Context | Good | Bad | +|---------|------|-----| +| CTA | "Start Workout" | "Start Your Workout Now!" | +| Empty state | "No workouts yet" | "You haven't done any workouts :(" | +| Error | "Connection lost" | "Oh no! Something went wrong!" | +| Success | "Workout complete" | "AMAZING! You crushed it!!!" | + +### Coach Dialogue + +- Motivational but authentic +- Form cues during exercises +- Breathing reminders during rest +- Encouragement without clichés + +--- + +*Document created: February 18, 2026* +*Version: 2.0* +*Brand: Apple Fitness+ inspired* diff --git a/TabataFit_PDD_v2.0.md b/TabataFit_PDD_v2.0.md new file mode 100644 index 0000000..e368f86 --- /dev/null +++ b/TabataFit_PDD_v2.0.md @@ -0,0 +1,765 @@ +# TabataFit — Product Design Document v2.0 +> Apple Fitness+ Design Language for Tabata + +--- + +## Design Philosophy + +**"Make it feel like a premium fitness studio in your pocket."** + +TabataFit adopts le design language d'Apple Fitness+ : +- **Dark mode premium** — Fond noir profond, couleurs vibrantes +- **Video-first** — Le contenu est le héros +- **Typography bold** — Gros titres, textes épurés +- **Subtle animations** — Transitions fluides, feedback délicat +- **Inclusive imagery** — Diversité des coachs et body types + +--- + +## Color System — Dark Premium + +### Background Colors + +```typescript +const COLORS = { + // Backgrounds + BACKGROUND: '#000000', // Pure black — comme Apple TV + SURFACE: '#1C1C1E', // Raised surfaces + ELEVATED: '#2C2C2E', // Cards, modals + OVERLAY: 'rgba(0,0,0,0.6)', // Video overlays + + // Brand Accent (Vibrant Orange-Red) + BRAND: '#FF6B35', // Energy, action + BRAND_LIGHT: '#FF8C5A', // Highlights + BRAND_DARK: '#E55A25', // Pressed states + + // Secondary Accents + SUCCESS: '#34C759', // Completed, streaks + WARNING: '#FF9500', // Rest phases + INFO: '#5AC8FA', // Tips, info + + // Text + TEXT_PRIMARY: '#FFFFFF', // Main text + TEXT_SECONDARY: '#EBEBF5', // Secondary (87% opacity) + TEXT_TERTIARY: '#EBEBF599', // Tertiary (60% opacity) + TEXT_DISABLED: '#3A3A3C', // Disabled text + + // Semantic + WORK: '#FF6B35', // Active work phase + REST: '#5AC8FA', // Rest phase (calm blue) + PREP: '#FF9500', // Countdown prep +} +``` + +### Gradient Presets + +```typescript +const GRADIENTS = { + // Hero banners + HERO_WORK: ['#FF6B35', '#E55A25'], + HERO_REST: ['#5AC8FA', '#007AFF'], + HERO_FEAT: ['#1C1C1E', '#000000'], + + // Video overlays + VIDEO_OVERLAY: ['transparent', 'rgba(0,0,0,0.8)'], + VIDEO_TOP: ['rgba(0,0,0,0.4)', 'transparent'], + + // Buttons + CTA: ['#FF6B35', '#FF8C5A'], +} +``` + +--- + +## Typography System — Apple SF Pro Style + +```typescript +const TYPOGRAPHY = { + // Hero/Display + HERO: { + fontFamily: 'Inter_900Black', + fontSize: 48, + lineHeight: 56, + letterSpacing: -1, + }, + + // Section Headers (like Apple Fitness+) + TITLE_1: { + fontFamily: 'Inter_700Bold', + fontSize: 34, + lineHeight: 41, + letterSpacing: 0.37, + }, + + TITLE_2: { + fontFamily: 'Inter_700Bold', + fontSize: 28, + lineHeight: 34, + letterSpacing: 0.36, + }, + + TITLE_3: { + fontFamily: 'Inter_600SemiBold', + fontSize: 22, + lineHeight: 28, + letterSpacing: 0.35, + }, + + // Body + BODY: { + fontFamily: 'Inter_400Regular', + fontSize: 17, + lineHeight: 22, + letterSpacing: -0.41, + }, + + BODY_BOLD: { + fontFamily: 'Inter_600SemiBold', + fontSize: 17, + lineHeight: 22, + letterSpacing: -0.41, + }, + + // Metadata + CAPTION_1: { + fontFamily: 'Inter_400Regular', + fontSize: 15, + lineHeight: 20, + letterSpacing: -0.24, + }, + + CAPTION_2: { + fontFamily: 'Inter_400Regular', + fontSize: 14, + lineHeight: 18, + letterSpacing: -0.15, + }, + + // Timer (special) + TIMER: { + fontFamily: 'Inter_900Black', + fontSize: 96, + lineHeight: 96, + letterSpacing: -2, + }, + + TIMER_PHASE: { + fontFamily: 'Inter_700Bold', + fontSize: 24, + lineHeight: 28, + letterSpacing: 2, // Uppercase tracking + textTransform: 'uppercase', + }, +} +``` + +--- + +## Screen Designs + +### 1. Home Tab — "For You" + +#### Layout Structure + +``` +┌─────────────────────────────────────────────────────┐ +│ status bar │ +├─────────────────────────────────────────────────────┤ +│ │ +│ Bonjour, Alex [Profile] │ ← 24px padding +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ [VIDEO PREVIEW - LOOPING] │ │ ← Hero Card +│ │ │ │ 16:9 aspect +│ │ ┌─────────────────────────────────┐ │ │ +│ │ │ 🔥 FEATURED │ │ │ +│ │ │ │ │ │ +│ │ │ FULL BODY BURN │ │ │ ← Text overlay +│ │ │ 4 min • Beginner • Emma │ │ │ on video +│ │ │ │ │ │ +│ │ │ [▶️ START] [♡ Save] │ │ │ +│ │ └─────────────────────────────────┘ │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Continue See All → │ ← Section header +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ [Thumb] │ │ [Thumb] │ │ [Thumb] │ │ ← Horizontal scroll +│ │ ━━━━━ │ │ ━━━━━ │ │ ━━━━━ │ │ 140x200px cards +│ │ 65% │ │ 30% │ │ 10% │ │ +│ │ Core │ │ HIIT │ │ Full │ │ +│ │ Burn │ │ Extreme │ │ Body │ │ +│ └─────────┘ └─────────┘ └─────────┘ │ +│ │ +│ Popular This Week │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ [Thumb] │ │ [Thumb] │ │ [Thumb] │ │ [Thumb] │ │ ← Smaller cards +│ │ │ │ │ │ │ │ │ │ │ 120x120px +│ │ Quick │ │ Strength│ │ Cardio │ │ Core │ │ +│ │ Burn │ │ Tabata │ │ Blast │ │ Crush │ │ +│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ +│ │ +│ Collections │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ 🌅 Morning Energizer │ │ ← Full-width cards +│ │ 5 workouts • 20 min total │ │ +│ └─────────────────────────────────────────────┘ │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ 🔥 7-Day Challenge │ │ +│ │ 7 workouts • Progressive intensity │ │ +│ └─────────────────────────────────────────────┘ │ +│ │ +├─────────────────────────────────────────────────────┤ +│ [Home] [Workouts] [Activity] [Browse] [Profile] │ +└─────────────────────────────────────────────────────┘ +``` + +#### Component Specs + +**Hero Card:** +- Full width - 48px padding +- 16:9 aspect ratio +- Video preview looping (muted) +- Gradient overlay: transparent → rgba(0,0,0,0.8) +- Featured badge top-left +- Title, metadata, CTA bottom + +**Continue Watching Card:** +- 140px width × 200px height +- Thumbnail with progress bar overlay +- Progress percentage badge +- Workout name + duration + +**Popular Card:** +- 120px × 120px square +- Thumbnail only +- Category name below + +**Collection Card:** +- Full width - 48px padding +- 80px height +- Icon + title + description +- Chevron right + +--- + +### 2. Workouts Tab + +#### Layout Structure + +``` +┌─────────────────────────────────────────────────────┐ +│ status bar │ +├─────────────────────────────────────────────────────┤ +│ │ +│ Workouts [🔍 Search] │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ [LARGE CATEGORY THUMBNAIL] │ │ +│ │ │ │ +│ │ 🔥 QUICK BURN │ │ +│ │ 4 min • All levels │ │ +│ │ 12 workouts │ │ +│ │ [→] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ [LARGE CATEGORY THUMBNAIL] │ │ +│ │ │ │ +│ │ 💪 STRENGTH TABATA │ │ +│ │ 8 min • Intermediate │ │ +│ │ 8 workouts │ │ +│ │ [→] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 🏃 CARDIO BLAST │ │ +│ │ 4-12 min • All levels • 15 workouts [→] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 🧘 CORE & FLEXIBILITY │ │ +│ │ 4 min • Beginner • 6 workouts [→] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ ⚡ HIIT EXTREME │ │ +│ │ 12-20 min • Advanced • 10 workouts [→] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +├─────────────────────────────────────────────────────┤ +│ [Home] [Workouts] [Activity] [Browse] [Profile] │ +└─────────────────────────────────────────────────────┘ +``` + +#### Category Detail View + +``` +┌─────────────────────────────────────────────────────┐ +│ ← Quick Burn │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 4 min • All levels • 12 workouts │ │ +│ │ │ │ +│ │ Filter: [All] [Beginner] [Intermediate] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ ┌──────┐ │ │ +│ │ │[Vid] │ Full Body Ignite │ │ +│ │ │ │ 4 min • Beginner • Emma │ │ +│ │ └──────┘ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ ┌──────┐ │ │ +│ │ │[Vid] │ Cardio Crusher │ │ +│ │ │ │ 4 min • Intermediate • Alex │ │ +│ │ └──────┘ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ ┌──────┐ │ │ +│ │ │[Vid] │ Lower Body Blast │ │ +│ │ │ │ 4 min • Intermediate • Jake │ │ +│ │ └──────┘ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +### 3. Pre-Workout Detail Screen + +``` +┌─────────────────────────────────────────────────────┐ +│ ← [♡] [···] │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ │ │ +│ │ [VIDEO PREVIEW - LOOPING] │ │ +│ │ │ │ +│ │ Coach Emma in action │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ FULL BODY IGNITE │ +│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ +│ │ +│ 👩 Emma • 💪 Beginner • ⏱️ 4 min • 🔥 45cal │ +│ │ +│ ───────────────────────────────────────────────── │ +│ │ +│ What You'll Need │ +│ ○ No equipment required │ +│ ○ Yoga mat optional │ +│ │ +│ ───────────────────────────────────────────────── │ +│ │ +│ Exercises (8 rounds) │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ 1. Jump Squats 20s work │ │ +│ │ 2. Mountain Climbers 20s work │ │ +│ │ 3. Burpees 20s work │ │ +│ │ 4. High Knees 20s work │ │ +│ │ ─────────────────────── │ │ +│ │ Repeat × 2 rounds │ │ +│ └─────────────────────────────────────────────┘ │ +│ │ +│ ───────────────────────────────────────────────── │ +│ │ +│ Music │ +│ 🎵 Electronic Energy │ +│ Upbeat, high-energy electronic tracks │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ ▶️ START WORKOUT │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +### 4. Active Workout Screen — The Core Experience + +#### Work Phase + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ [FULL SCREEN VIDEO] │ │ +│ │ │ │ +│ │ Coach doing Jump Squats │ │ +│ │ in perfect form │ │ +│ │ │ │ +│ │ │ │ +│ │ ┌───────────────────────────────────────┐ │ │ +│ │ │ ┌─────────────────────────────────┐ │ │ │ +│ │ │ │ 🔥 WORK │ │ │ │ ← Timer overlay +│ │ │ │ │ │ │ │ bottom gradient +│ │ │ │ 00:14 │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ Round 3 of 8 │ │ │ │ +│ │ │ │ ████████████░░░░ 65% │ │ │ │ +│ │ │ └─────────────────────────────────┘ │ │ │ +│ │ └───────────────────────────────────────┘ │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ JUMP SQUATS │ +│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ +│ │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ +│ │ 52 │ │ 142 │ │ 85% │ │ +│ │ CALORIES │ │ BPM │ │ EFFORT │ │ +│ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +│ Burn Bar │ +│ ░░░░░░░░████████████████░░░░ 72nd percentile │ +│ │ +│ [⏸️ Pause] [⛶ Fullscreen]│ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +#### Rest Phase + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ [COACH IN REST POSITION] │ │ +│ │ │ │ +│ │ "Shake it out, take a breath" │ │ +│ │ │ │ +│ │ ┌───────────────────────────────────────┐ │ │ +│ │ │ ┌─────────────────────────────────┐ │ │ │ +│ │ │ │ 💙 REST │ │ │ │ ← Blue rest theme +│ │ │ │ │ │ │ │ +│ │ │ │ 00:08 │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ Next: Mountain Climbers │ │ │ │ +│ │ │ │ ░░░░░░░░░░░░░░░░░░░ 40% │ │ │ │ +│ │ │ └─────────────────────────────────┘ │ │ │ +│ │ └───────────────────────────────────────┘ │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ UP NEXT │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ ┌──────┐ │ │ +│ │ │ GIF │ Mountain Climbers │ │ +│ │ │preview│ "Core engaged, drive knees forward" │ │ +│ │ └──────┘ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ [⏸️ Pause] [⛶ Fullscreen]│ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +#### 3-2-1 Countdown (Pre-Work) + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ GET READY! │ │ +│ │ │ │ +│ │ 3 │ │ ← Giant number +│ │ │ │ centered +│ │ │ │ +│ │ JUMP SQUATS │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +### 5. Workout Complete Screen + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ │ +│ 🎉 │ +│ │ +│ WORKOUT COMPLETE │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ [ANIMATED CELEBRATION RINGS] │ │ +│ │ │ │ +│ │ 🔥 💪 ⚡ │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ +│ │ 52 │ │ 4 │ │ 100% │ │ +│ │ CALORIES │ │ MINUTES │ │ COMPLETE │ │ +│ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +│ Burn Bar │ +│ You beat 73% of users! │ +│ ░░░░░░░░████████████████░░░░ │ +│ │ +│ ───────────────────────────────────────────────── │ +│ │ +│ 🔥 7 Day Streak! │ +│ Keep the momentum going! │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 📤 SHARE YOUR WORKOUT │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ ← BACK TO HOME │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Recommended Next │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ [Thumb] │ │ [Thumb] │ │ [Thumb] │ │ +│ │ Core │ │ Upper │ │ Cardio │ │ +│ │ Crush │ │ Body │ │ Blast │ │ +│ └─────────┘ └─────────┘ └─────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +### 6. Activity Tab + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ Activity │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ 🔥 STREAK │ │ +│ │ │ │ +│ │ 7 │ │ +│ │ DAYS │ │ +│ │ │ │ +│ │ ● ● ● ● ● ● ● ○ ○ ○ │ │ +│ │ M T W T F S S M T W │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ This Week │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ +│ │ 5 │ │ 156 │ │ 20 │ │ +│ │ WORKOUTS │ │ CALORIES │ │ MINUTES │ │ +│ │ 5 goal │ │ 150 goal │ │ 20 goal │ │ +│ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +│ Monthly Summary │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ [CALENDAR HEAT MAP] │ │ +│ │ │ │ +│ │ Jan 2026 │ │ +│ │ S M T W T F S │ │ +│ │ 1 2 3 4 5 6 │ │ +│ │ 7 8 9 10 11 12 13 │ │ +│ │ 14 15 16 17 18 19 20 │ │ +│ │ ░ ░ █ █ ░ █ █ │ │ +│ │ █ █ ░ █ █ ░ ░ │ │ +│ │ ░ █ █ █ █ █ █ │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Trends │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 📈 Workouts trending up! │ │ +│ │ +23% vs last month │ │ +│ │ │ │ +│ │ [WEEKLY CHART] │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Burn Bar Position │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ Your average: 45 cal/workout │ │ +│ │ ████████████░░░░ 68th percentile │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +### 7. Browse Tab + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ Browse │ +│ │ +│ Filters [Edit] │ +│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ +│ │ All ▼ │ │ 4 min │ │ 8 min │ │ Begin │ │ +│ └────────┘ └────────┘ └────────┘ └────────┘ │ +│ │ +│ Trainers │ +│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ +│ │ 👩 │ │ 👨 │ │ 👩 │ │ 👨 │ │ +│ │ Emma │ │ Jake │ │ Mia │ │ Alex │ │ +│ │ 12 wk │ │ 8 wk │ │ 10 wk │ │ 6 wk │ │ +│ └────────┘ └────────┘ └────────┘ └────────┘ │ +│ │ +│ Duration │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ ○ 4 min (Classic Tabata) 20 │ │ +│ │ ○ 8 min (Double Tabata) 15 │ │ +│ │ ○ 12 min (Triple Tabata) 10 │ │ +│ │ ○ 20 min (Tabata Marathon) 5 │ │ +│ └─────────────────────────────────────────────┘ │ +│ │ +│ Focus Area │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ ○ Full Body 20 │ │ +│ │ ○ Upper Body 8 │ │ +│ │ ○ Lower Body 8 │ │ +│ │ ○ Core 8 │ │ +│ │ ○ Cardio 6 │ │ +│ └─────────────────────────────────────────────┘ │ +│ │ +│ Music Vibe │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ ○ Electronic Energy 18 │ │ +│ │ ○ Hip-Hop Beats 12 │ │ +│ │ ○ Rock Power 10 │ │ +│ │ ○ Chill Focus 10 │ │ +│ └─────────────────────────────────────────────┘ │ +│ │ +│ Collections │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ 🌅 Morning Energizer • 5 workouts │ │ +│ └─────────────────────────────────────────────┘ │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ 💪 No Equipment • 15 workouts │ │ +│ └─────────────────────────────────────────────┘ │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ 🔥 7-Day Challenge • 7 workouts │ │ +│ └─────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +### 8. Profile Tab + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ Profile │ +│ │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ 👤 Alex Martin │ │ +│ │ Member since Jan 2026 │ │ +│ │ ✨ Premium │ │ +│ │ │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Weekly Goal │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 5 workouts per week │ │ +│ │ ████████████████░░░░ 4/5 this week │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Achievements │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 🏆 7-Day Streak 🥵 First Sweat │ │ +│ │ 💯 100 Workouts 🌅 Early Bird │ │ +│ │ 🔥 500 Calories ⚡ Speed Demon │ │ +│ │ │ │ +│ │ [See All Achievements →] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Settings │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ Notifications [→] │ │ +│ │ Apple Watch [→] │ │ +│ │ Music Preferences [→] │ │ +│ │ Workout Preferences [→] │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ Account │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ Subscription [→] │ │ +│ │ Privacy & Security [→] │ │ +│ │ Help & Support [→] │ │ +│ │ Sign Out │ │ +│ └───────────────────────────────────────────────┘ │ +│ │ +│ TabataFit v1.0.0 │ +│ Made with ❤️ for HIIT lovers │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +## Animation Specifications + +### Screen Transitions +- **Push/Pop**: 300ms ease-out +- **Modal**: Slide up from bottom, 350ms + +### Micro-interactions +- **Button press**: Scale to 0.96, 100ms +- **Card tap**: Scale to 0.98, 150ms +- **Toggle**: 200ms spring animation + +### Timer Animations +- **Countdown**: Number scales up/down each second +- **Progress bar**: Smooth width animation +- **Phase change**: Color crossfade 300ms + +### Celebration +- **Confetti**: Lottie animation on workout complete +- **Rings**: Animated fill when stats update +- **Streak badge**: Pulse animation + +--- + +## Accessibility + +- **Dynamic Type**: Support up to 200% text scaling +- **VoiceOver**: Full screen reader support +- **Reduce Motion**: Disable animations when requested +- **High Contrast**: Alternative color scheme option + +--- + +*Document created: February 18, 2026* +*Version: 2.0* +*Design System: Apple Fitness+ Inspired* diff --git a/TabataFit_PRD_v2.0.md b/TabataFit_PRD_v2.0.md new file mode 100644 index 0000000..dcd4c66 --- /dev/null +++ b/TabataFit_PRD_v2.0.md @@ -0,0 +1,545 @@ +# TabataFit — Product Requirements Document v2.0 +> Apple Fitness+ for Tabata — The Premium HIIT Experience + +--- + +## Vision Statement + +**TabataFit est l'Apple Fitness+ du Tabata.** Une expérience premium, visuellement stunante, guidée par des coachs, qui transforme 4 minutes d'exercice en une expérience de fitness immersive. + +*"Workouts that work. Beautifully."* + +--- + +## Positionnement + +| Aspect | Apple Fitness+ | TabataFit | +|--------|---------------|-----------| +| **Focus** | Multi-activité (Yoga, HIIT, Strength, etc.) | Spécialiste Tabata/HIIT | +| **Durée** | 5-45 min | 4-20 min (format Tabata) | +| **Différenciateur** | Intégration Apple Watch | Timer intelligent + Coaching audio | +| **Cible** | Grand public fitness | Athlètes HIIT, busy professionals | +| **Vibe** | Studio californien | Énergie explosive, motivational | + +--- + +## Core Philosophy — Apple Fitness+ Principles + +1. **Content is King** — Vidéos HD, coachs charismatiques, production Netflix-quality +2. **Inclusive** — Tous niveaux, modifications montrées +3. **Personalized** — Recommandations basées sur l'historique +4. **Immersive** — Music sync, Burn Bar, stats temps réel +5. **Beautiful** — Design épuré, animations fluides, dark theme élégant + +--- + +## Architecture Produit + +### Tab Bar (5 onglets — comme Apple Fitness+) + +``` +┌─────────────────────────────────────────────────────────────┐ +│ │ +│ 🏠 Home 🔥 Workouts 📊 Activity 🔍 Browse 👤 Profile │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 1. Home Tab — "For You" + +**Inspiration**: Apple Fitness+ Home — grande bannière, collections, recommandations + +``` +┌─────────────────────────────────────────┐ +│ ☀️ Bonjour Alex │ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ 🎬 FEATURED WORKOUT │ │ +│ │ ─────────────────────── │ │ +│ │ Full Body Burn │ │ +│ │ 4 min • Beginner • Emma │ │ +│ │ │ │ +│ │ [▶️ START NOW] │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ Continue Watching │ +│ ┌─────┐ ┌─────┐ ┌─────┐ │ +│ │ 65%│ │ 30%│ │ 10%│ │ +│ └─────┘ └─────┘ └─────┘ │ +│ │ +│ Popular This Week │ +│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ +│ └─────┘ └─────┘ └─────┘ └─────┘ │ +│ │ +│ Collections │ +│ 🌅 Morning Energizer │ +│ 💪 No Equipment Needed │ +│ 🔥 7-Day Challenge │ +│ │ +└─────────────────────────────────────────┘ +``` + +**Elements clés:** +- Hero banner avec vidéo preview en boucle +- "Continue Watching" — workouts non terminés +- "Popular This Week" — trending workouts +- Collections thématiques +- Coach du moment + +### 2. Workouts Tab — Parcourir par type + +**Inspiration**: Apple Fitness+ workout browser — categories visuelles + +``` +┌─────────────────────────────────────────┐ +│ WORKOUTS 🔍 │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ 🔥 QUICK BURN │ │ +│ │ 4 min • All levels │ │ +│ │ 12 workouts │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ 💪 STRENGTH TABATA │ │ +│ │ 8 min • Intermediate │ │ +│ │ 8 workouts │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ 🏃 CARDIO BLAST │ │ +│ │ 4-12 min • All levels │ │ +│ │ 15 workouts │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ 🧘 CORE & FLEXIBILITY │ │ +│ │ 4 min • Beginner friendly │ │ +│ │ 6 workouts │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ ⚡ HIIT EXTREME │ │ +│ │ 12-20 min • Advanced │ │ +│ │ 10 workouts │ │ +│ └─────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────┘ +``` + +**Categories:** +1. **Quick Burn** — 4 min, perfect for beginners +2. **Strength Tabata** — Resistance exercises +3. **Cardio Blast** — Pure cardio, no equipment +4. **Core & Flexibility** — Abs, stretching +5. **HIIT Extreme** — Advanced, longer sessions + +### 3. Activity Tab — Stats & Progress + +**Inspiration**: Apple Fitness+ Activity rings + trends + +``` +┌─────────────────────────────────────────┐ +│ ACTIVITY │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ 🔥 STREAK │ │ +│ │ ───────── │ │ +│ │ 7 │ │ +│ │ DAYS │ │ +│ │ │ │ +│ │ ○ ○ ○ ○ ○ ○ ○ ● ○ ○ │ │ +│ │ M T W T F S S M T │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ This Week │ +│ ┌───────┐ ┌───────┐ ┌───────┐ │ +│ │ 5 │ │ 156 │ │ 32 │ │ +│ │Workout│ │ Calories│ │ Minutes│ │ +│ └───────┘ └───────┘ └───────┘ │ +│ │ +│ Trends │ +│ ┌─────────────────────────────────┐ │ +│ │ 📈 Workouts are trending up! │ │ +│ │ +23% vs last month │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ Burn Bar Position │ +│ ┌─────────────────────────────────┐ │ +│ │ Your avg: 45 cal/workout │ │ +│ │ ████████░░░░ 68th percentile │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ Monthly Summary │ +│ [ Calendar view with heat map ] │ +│ │ +└─────────────────────────────────────────┘ +``` + +**Features:** +- Streak counter avec calendrier visuel +- Stats hebdomadaires (workouts, calories, minutes) +- Trends ("You're on fire! 🔥") +- Burn Bar — comparaison avec autres utilisateurs +- Calendar heat map + +### 4. Browse Tab — Tout le contenu + +**Inspiration**: Apple Fitness+ Browse — filtres, trainers, music + +``` +┌─────────────────────────────────────────┐ +│ BROWSE │ +│ │ +│ Filters [Edit]│ +│ [All ▼] [4 min] [8 min] [Beginner] │ +│ │ +│ By Trainer │ +│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ +│ │ 👩 │ │ 👨 │ │ 👩 │ │ 👨 │ │ +│ │Emma │ │Jake │ │Mia │ │Alex │ │ +│ └─────┘ └─────┘ └─────┘ └─────┘ │ +│ │ +│ By Duration │ +│ ○ 4 min (Classic Tabata) │ +│ ○ 8 min (Double Tabata) │ +│ ○ 12 min (Triple Tabata) │ +│ ○ 20 min (Tabata Marathon) │ +│ │ +│ By Focus Area │ +│ ○ Full Body │ +│ ○ Upper Body │ +│ ○ Lower Body │ +│ ○ Core │ +│ ○ Cardio │ +│ │ +│ Music Vibe │ +│ ○ Electronic Energy │ +│ ○ Hip-Hop Beats │ +│ ○ Rock Power │ +│ ○ Chill Focus │ +│ │ +└─────────────────────────────────────────┘ +``` + +### 5. Profile Tab — Settings & Account + +**Inspiration**: Apple Fitness+ Profile — minimal, clean + +``` +┌─────────────────────────────────────────┐ +│ PROFILE │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ 👤 Alex Martin │ │ +│ │ Member since Jan 2026 │ │ +│ │ Premium ✨ │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ Goals │ +│ ┌─────────────────────────────────┐ │ +│ │ Weekly Goal: 5 workouts │ │ +│ │ ████████░░ 4/5 this week │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ Achievements │ +│ 🏆 7-Day Streak │ +│ 🥵 First Sweat │ +│ 💯 100 Workouts │ +│ [See all →] │ +│ │ +│ Settings │ +│ • Notifications │ +│ • Apple Watch │ +│ • Music Preferences │ +│ • Account │ +│ • Subscription │ +│ │ +└─────────────────────────────────────────┘ +``` + +--- + +## The Workout Experience — Cœur du Produit + +### Pre-Workout Screen + +**Inspiration**: Apple Fitness+ workout preview — trailer, details, start + +``` +┌─────────────────────────────────────────┐ +│ ← │ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ │ │ +│ │ [VIDEO PREVIEW LOOP] │ │ +│ │ Coach Emma demonstrating │ │ +│ │ Jump Squats │ │ +│ │ │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ FULL BODY BURN │ +│ ───────────────────────────────────── │ +│ │ +│ 👩 Emma • 💪 Intermediate • ⏱️ 4 min │ +│ │ +│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ +│ │ +│ What You'll Need │ +│ ○ No equipment │ +│ ○ Mat recommended │ +│ │ +│ Exercises Preview │ +│ 1. Jump Squats (20s work) │ +│ 2. Mountain Climbers (20s work) │ +│ 3. Burpees (20s work) │ +│ 4. High Knees (20s work) │ +│ × 2 rounds │ +│ │ +│ Music │ +│ 🎵 Electronic Energy playlist │ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ ▶️ START WORKOUT │ │ +│ └───────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────┘ +``` + +### Active Workout Screen — Apple Fitness+ Style + +**Inspiration**: Apple Fitness+ player — video dominant, stats overlay + +``` +┌─────────────────────────────────────────┐ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ │ │ +│ │ │ │ +│ │ [FULL SCREEN VIDEO] │ │ +│ │ │ │ +│ │ Coach doing exercise │ │ +│ │ in perfect form │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ ┌─────────────────────────────┐ │ │ +│ │ │ 🔥 WORK • 00:14 │ │ │ +│ │ │ Round 3 of 8 │ │ │ +│ │ │ ████████████░░░░ 65% │ │ │ +│ │ └─────────────────────────────┘ │ │ +│ │ │ │ +│ │ │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ JUMP SQUATS │ +│ ───────────────────────────────────── │ +│ │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ 14 │ │ 52 │ │ 85% │ │ +│ │ cal │ │ bpm │ │ effort │ │ +│ └─────────┘ └─────────┘ └─────────┘ │ +│ │ +│ Burn Bar: ████████░░░░ 72% │ +│ │ +└─────────────────────────────────────────┘ +``` + +**Key Features:** +- Video full screen avec coach +- Timer overlay (phase + countdown) +- Round indicator +- Progress bar +- Stats temps réel (calories, bpm si Apple Watch) +- Burn Bar + +### During Rest Phase + +``` +┌─────────────────────────────────────────┐ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ │ │ +│ │ [COACH IN REST POSE] │ │ +│ │ Stretching / breathing │ │ +│ │ │ │ +│ │ ┌─────────────────────────────┐ │ │ +│ │ │ 💙 REST • 00:08 │ │ │ +│ │ │ Next: Mountain Climbers │ │ │ +│ │ │ ░░░░░░░░░░░░░░░░░░ 40% │ │ │ +│ │ └─────────────────────────────┘ │ │ +│ │ │ │ +│ │ "Shake it out, you're │ │ +│ │ doing great!" │ │ +│ │ │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ Up Next: Mountain Climbers │ +│ [GIF preview of next exercise] │ +│ │ +└─────────────────────────────────────────┘ +``` + +### Workout Complete — Celebration + +**Inspiration**: Apple Fitness+ celebration screen + +``` +┌─────────────────────────────────────────┐ +│ │ +│ 🎉 WORKOUT COMPLETE! │ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ │ │ +│ │ [ANIMATED RINGS] │ │ +│ │ 🔥 🔥 🔥 │ │ +│ │ │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ YOUR STATS │ +│ ───────────────────────────────────── │ +│ │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ 52 │ │ 4 │ │ 100% │ │ +│ │ CALORIES│ │ MINUTES │ │ COMPLETE│ │ +│ └─────────┘ └─────────┘ └─────────┘ │ +│ │ +│ Burn Bar │ +│ ████████████░░░ You beat 73%! │ +│ │ +│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ +│ │ +│ 🔥 7 Day Streak! Keep it going! │ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ SHARE YOUR WORKOUT │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ ← BACK TO HOME │ │ +│ └───────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────┘ +``` + +--- + +## Content Strategy — 50+ Workouts au Launch + +### Par Durée + +| Duration | Format | Rounds | Count | +|----------|--------|--------|-------| +| 4 min | Classic Tabata | 8 rounds | 20 workouts | +| 8 min | Double Tabata | 16 rounds | 15 workouts | +| 12 min | Triple Tabata | 24 rounds | 10 workouts | +| 20 min | Tabata Marathon | 40 rounds | 5 workouts | + +### Par Focus + +- **Full Body** — 20 workouts +- **Upper Body** — 8 workouts +- **Lower Body** — 8 workouts +- **Core** — 8 workouts +- **Cardio Only** — 6 workouts + +### Par Niveau + +- **Beginner** — 15 workouts +- **Intermediate** — 20 workouts +- **Advanced** — 15 workouts + +### Trainers (5 au launch) + +1. **Emma** — Energy queen, beginner-friendly +2. **Jake** — Strength focus, motivating +3. **Mia** — Form perfectionist, technical +4. **Alex** — Cardio beast, intense +5. **Sofia** — Chill but effective, recovery + +--- + +## Technical Requirements + +### Video Pipeline +- HLS streaming (adaptive bitrate) +- 1080p minimum, 4K for featured +- Offline download for Premium +- Preload next exercise during rest + +### Audio +- Multiple music tracks (by vibe) +- Coach voice-over (can be muted) +- Sound effects (beeps, transitions) +- Haptic feedback sync + +### Apple Watch Integration +- Heart rate display +- Calories calculation +- Activity rings update +- Now Playing controls + +### Offline Support +- Download workouts for offline +- Sync when back online +- Local stats caching + +--- + +## Monetization + +### Free Tier +- 3 workouts free forever +- Basic stats +- Ads between workouts + +### Premium ($6.99/mo or $49.99/yr) +- Unlimited workouts +- All trainers +- Offline downloads +- Advanced stats & trends +- Apple Watch integration +- No ads +- Family Sharing (up to 5) + +--- + +## Success Metrics + +| Metric | Target (Month 3) | +|--------|------------------| +| DAU | 10,000 | +| Workout completion rate | 75% | +| 7-day retention | 40% | +| Premium conversion | 8% | +| Average workouts/user/week | 3.5 | + +--- + +## Roadmap + +### Phase 1 — MVP (Weeks 1-4) +- [ ] Home + Workouts tabs +- [ ] 20 workouts (4 min only) +- [ ] 2 trainers +- [ ] Basic timer + video player + +### Phase 2 — Core (Weeks 5-8) +- [ ] Activity tab with stats +- [ ] 30 workouts total +- [ ] 4 trainers +- [ ] Apple Watch integration + +### Phase 3 — Premium (Weeks 9-12) +- [ ] Browse + Profile tabs +- [ ] 50+ workouts +- [ ] 5 trainers +- [ ] Offline downloads +- [ ] Burn Bar +- [ ] Subscription system + +--- + +*Document created: February 18, 2026* +*Version: 2.0* +*Status: Ready for Design Phase* diff --git a/app.json b/app.json index 1f24dfe..af299d1 100644 --- a/app.json +++ b/app.json @@ -9,7 +9,8 @@ "userInterfaceStyle": "automatic", "newArchEnabled": true, "ios": { - "supportsTablet": true + "supportsTablet": true, + "bundleIdentifier": "com.anonymous.tabatago" }, "android": { "adaptiveIcon": { @@ -38,7 +39,8 @@ "backgroundColor": "#000000" } } - ] + ], + "expo-video" ], "experiments": { "typedRoutes": true, diff --git a/package-lock.json b/package-lock.json index 681f7d2..8d44110 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "name": "tabatago", "version": "1.0.0", "dependencies": { + "@expo-google-fonts/inter": "^0.4.2", + "@expo/ui": "~0.2.0-beta.9", "@expo/vector-icons": "^15.0.3", "@react-native-async-storage/async-storage": "^2.2.0", "@react-navigation/bottom-tabs": "^7.4.0", @@ -24,10 +26,12 @@ "expo-linear-gradient": "~15.0.8", "expo-linking": "~8.0.11", "expo-router": "~6.0.23", + "expo-sharing": "~14.0.8", "expo-splash-screen": "~31.0.13", "expo-status-bar": "~3.0.9", "expo-symbols": "~1.0.8", "expo-system-ui": "~6.0.9", + "expo-video": "~3.0.16", "expo-web-browser": "~15.0.10", "react": "19.1.0", "react-dom": "19.1.0", @@ -1728,6 +1732,12 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@expo-google-fonts/inter": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@expo-google-fonts/inter/-/inter-0.4.2.tgz", + "integrity": "sha512-syfiImMaDmq7cFi0of+waE2M4uSCyd16zgyWxdPOY7fN2VBmSLKEzkfbZgeOjJq61kSqPBNNtXjggiQiSD6gMQ==", + "license": "MIT AND OFL-1.1" + }, "node_modules/@expo/code-signing-certificates": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.6.tgz", @@ -2186,6 +2196,20 @@ "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==", "license": "MIT" }, + "node_modules/@expo/ui": { + "version": "0.2.0-beta.9", + "resolved": "https://registry.npmjs.org/@expo/ui/-/ui-0.2.0-beta.9.tgz", + "integrity": "sha512-RaBcp0cMe5GykQogJwRZGy4o4JHDLtrr+HaurDPhwPKqVATsV0rR11ysmFe4QX8XWLP/L3od7NOkXUi5ailvaw==", + "license": "MIT", + "dependencies": { + "sf-symbols-typescript": "^2.1.0" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, "node_modules/@expo/vector-icons": { "version": "15.0.3", "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.3.tgz", @@ -6507,6 +6531,15 @@ "node": ">=20.16.0" } }, + "node_modules/expo-sharing": { + "version": "14.0.8", + "resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-14.0.8.tgz", + "integrity": "sha512-A1pPr2iBrxypFDCWVAESk532HK+db7MFXbvO2sCV9ienaFXAk7lIBm6bkqgE6vzRd9O3RGdEGzYx80cYlc089Q==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-splash-screen": { "version": "31.0.13", "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-31.0.13.tgz", @@ -6565,6 +6598,17 @@ } } }, + "node_modules/expo-video": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/expo-video/-/expo-video-3.0.16.tgz", + "integrity": "sha512-H1HlxcHGomZItqisGfW3YL/G9BHtNBfVSimDJcLuyxyU87wFnV8loO9tCjuhufkfh/aTa2sW5BYAjLjg9DvnBQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, "node_modules/expo-web-browser": { "version": "15.0.10", "resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-15.0.10.tgz", diff --git a/package.json b/package.json index 398e1f6..ac6691c 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,14 @@ "scripts": { "start": "expo start", "reset-project": "node ./scripts/reset-project.js", - "android": "expo start --android", - "ios": "expo start --ios", + "android": "expo run:android", + "ios": "expo run:ios", "web": "expo start --web", "lint": "expo lint" }, "dependencies": { + "@expo-google-fonts/inter": "^0.4.2", + "@expo/ui": "~0.2.0-beta.9", "@expo/vector-icons": "^15.0.3", "@react-native-async-storage/async-storage": "^2.2.0", "@react-navigation/bottom-tabs": "^7.4.0", @@ -27,10 +29,12 @@ "expo-linear-gradient": "~15.0.8", "expo-linking": "~8.0.11", "expo-router": "~6.0.23", + "expo-sharing": "~14.0.8", "expo-splash-screen": "~31.0.13", "expo-status-bar": "~3.0.9", "expo-symbols": "~1.0.8", "expo-system-ui": "~6.0.9", + "expo-video": "~3.0.16", "expo-web-browser": "~15.0.10", "react": "19.1.0", "react-dom": "19.1.0", diff --git a/src/shared/constants/CLAUDE.md b/src/shared/constants/CLAUDE.md new file mode 100644 index 0000000..430e808 --- /dev/null +++ b/src/shared/constants/CLAUDE.md @@ -0,0 +1,19 @@ + +# Recent Activity + + + +### Feb 18, 2026 + +| ID | Time | T | Title | Read | +|----|------|---|-------|------| +| #4831 | 2:57 PM | 🔄 | Spacing Constants Enhanced with Semantic Aliases and Documentation | ~358 | +| #4830 | 2:56 PM | 🔵 | Design System Constants Index Review | ~293 | +| #4829 | " | 🔵 | Existing Animation Constants Reviewed | ~331 | +| #4828 | " | 🔵 | Color System Constants Review for BDSD Planning | ~412 | +| #4827 | " | 🔵 | Spacing Constants Implementation Review | ~254 | +| #4826 | " | 🔵 | Shadow System Constants Reviewed | ~296 | +| #4825 | " | 🔵 | Typography Constants Implementation Verification | ~264 | +| #4779 | 1:21 PM | 🔵 | Typography System Constants Analysis | ~354 | +| #4778 | 1:20 PM | 🔵 | Design System Color Constants Analysis | ~392 | + \ No newline at end of file diff --git a/src/shared/constants/animations.ts b/src/shared/constants/animations.ts index fa3c215..7d4a240 100644 --- a/src/shared/constants/animations.ts +++ b/src/shared/constants/animations.ts @@ -1,51 +1,132 @@ +/** + * TabataFit Animation System + * Liquid Glass — fluid, organic motion + */ + import { Easing } from 'react-native' +// ═══════════════════════════════════════════════════════════════════════════ +// DURATIONS +// ═══════════════════════════════════════════════════════════════════════════ + export const DURATION = { - SNAP: 60, - QUICK: 120, - FAST: 300, - NORMAL: 400, - SLOW: 600, - XSLOW: 1000, - BREATH: 1800, + INSTANT: 100, + FAST: 200, + NORMAL: 300, + SLOW: 500, + XSLOW: 800, + + // Special + BREATH: 2500, // Breathing animation cycle + BREATH_HALF: 1250, // Half breath cycle + LIQUID: 600, // Liquid morph duration + RIPPLE: 400, // Tap ripple + PHASE_CHANGE: 300, // Phase transition } as const -export const EASING = { - STANDARD: Easing.inOut(Easing.ease), - DECELERATE: Easing.out(Easing.ease), - LINEAR: Easing.linear, +// ═══════════════════════════════════════════════════════════════════════════ +// EASING CURVES +// ═══════════════════════════════════════════════════════════════════════════ + +export const EASE = { + // Standard iOS easing + DEFAULT: Easing.bezier(0.25, 0.1, 0.25, 1), + EASE_OUT: Easing.bezier(0, 0, 0.2, 1), + EASE_IN: Easing.bezier(0.4, 0, 1, 1), + EASE_IN_OUT: Easing.bezier(0.4, 0, 0.2, 1), + + // Liquid / Fluid + LIQUID: Easing.bezier(0.4, 0, 0.2, 1), + BOUNCE: Easing.bezier(0.68, -0.55, 0.265, 1.55), + + // Sharp / Snappy + SNAPPY: Easing.bezier(0.2, 0, 0, 1), } as const +// ═══════════════════════════════════════════════════════════════════════════ +// SPRING CONFIGS (for react-native Animated.spring) +// ═══════════════════════════════════════════════════════════════════════════ + export const SPRING = { - BOUNCY: { tension: 50, friction: 7 }, + // Bouncy (playful) + BOUNCY: { + damping: 15, + stiffness: 180, + mass: 1, + }, + + // Gentle (smooth) + GENTLE: { + damping: 20, + stiffness: 100, + mass: 1, + }, + + // Snappy (quick) + SNAPPY: { + damping: 18, + stiffness: 300, + mass: 1, + }, + + // Slow (dramatic) + SLOW: { + damping: 25, + stiffness: 80, + mass: 1.5, + }, + + // Liquid (fluid) + LIQUID: { + damping: 20, + stiffness: 200, + mass: 1, + }, } as const +// ═══════════════════════════════════════════════════════════════════════════ +// PRESET ANIMATION CONFIGS +// ═══════════════════════════════════════════════════════════════════════════ + export const ANIMATION = { - PULSE_UP: { - toValue: 1.08, - duration: DURATION.SNAP, - useNativeDriver: true, - }, - PULSE_DOWN: { - toValue: 1, - duration: DURATION.QUICK, - easing: EASING.DECELERATE, - useNativeDriver: true, - }, - GRADIENT_CROSSFADE: { - toValue: 1, - duration: DURATION.SLOW, - easing: EASING.STANDARD, - useNativeDriver: true, - }, + // Fade in FADE_IN: { - toValue: 1, duration: DURATION.NORMAL, - useNativeDriver: true, + easing: EASE.EASE_OUT, }, - BREATH_HALF: { + + // Scale up (pop in) + POP_IN: { + spring: SPRING.BOUNCY, + }, + + // Slide up + SLIDE_UP: { + duration: DURATION.NORMAL, + easing: EASE.EASE_OUT, + }, + + // Liquid morph + LIQUID_MORPH: { + duration: DURATION.LIQUID, + easing: EASE.LIQUID, + }, + + // Breathing glow + BREATHE: { duration: DURATION.BREATH, - easing: EASING.STANDARD, - useNativeDriver: false, + easing: EASE.EASE_IN_OUT, + }, + + // Timer tick pulse + TIMER_TICK: { + duration: 150, + easing: EASE.EASE_OUT, + }, + + // Phase transition + PHASE_TRANSITION: { + duration: DURATION.PHASE_CHANGE, + easing: EASE.EASE_IN_OUT, }, } as const diff --git a/src/shared/constants/borderRadius.ts b/src/shared/constants/borderRadius.ts index 609595f..1b0c5c7 100644 --- a/src/shared/constants/borderRadius.ts +++ b/src/shared/constants/borderRadius.ts @@ -1,11 +1,23 @@ +/** + * TabataFit Border Radius System + * Liquid Glass uses generous rounding + */ + export const RADIUS = { + NONE: 0, XS: 4, - SM: 6, + SM: 8, MD: 12, LG: 16, XL: 20, - '2XL': 28, - '3XL': 32, - '4XL': 36, + XXL: 24, + XXXL: 32, + + // Special FULL: 9999, + + // Liquid glass specific + GLASS_CARD: 20, + GLASS_MODAL: 28, + GLASS_BUTTON: 14, } as const diff --git a/src/shared/constants/colors.ts b/src/shared/constants/colors.ts index 2ef4ec5..fd13030 100644 --- a/src/shared/constants/colors.ts +++ b/src/shared/constants/colors.ts @@ -1,76 +1,248 @@ -export const PHASE_COLORS = { - IDLE: '#1E1E2E', - GET_READY: '#EAB308', - WORK: '#F97316', - REST: '#3B82F6', - COMPLETE: '#22C55E', -} as const +/** + * TabataFit Color System + * Liquid Glass Design (iOS 18.4 inspired) + */ -export const PHASE_GRADIENTS = { - IDLE: ['#0A0A14', '#12101F', '#1E1E2E'] as const, - GET_READY: ['#451A03', '#92400E', '#D97706'] as const, - WORK: ['#450A0A', '#991B1B', '#EA580C'] as const, - REST: ['#0C1929', '#1E3A5F', '#2563EB'] as const, - COMPLETE: ['#052E16', '#166534', '#16A34A'] as const, -} as const - -export const ACCENT = { - ORANGE: '#F97316', - ORANGE_GLOW: '#FB923C', - RED_HOT: '#EF4444', - GOLD: '#FBBF24', - WHITE: '#FFFFFF', - WHITE_DIM: 'rgba(255, 255, 255, 0.6)', - WHITE_FAINT: 'rgba(255, 255, 255, 0.15)', -} as const +// ═══════════════════════════════════════════════════════════════════════════ +// BRAND COLORS +// ═══════════════════════════════════════════════════════════════════════════ export const BRAND = { - PRIMARY: '#F97316', - PRIMARY_LIGHT: '#FB923C', - SECONDARY: '#FBBF24', - DANGER: '#EF4444', - SUCCESS: '#22C55E', - INFO: '#3B82F6', + PRIMARY: '#FF6B35', + PRIMARY_LIGHT: '#FF8C5A', + PRIMARY_DARK: '#E55A25', + SECONDARY: '#FFD60A', + DANGER: '#FF453A', + SUCCESS: '#30D158', + INFO: '#5AC8FA', } as const -export const SURFACE = { - BASE: '#0A0A14', - RAISED: '#12101F', - ELEVATED: '#1E1E2E', - OVERLAY_LIGHT: 'rgba(255, 255, 255, 0.08)', - OVERLAY_MEDIUM: 'rgba(255, 255, 255, 0.15)', - OVERLAY_STRONG: 'rgba(255, 255, 255, 0.25)', - SCRIM: 'rgba(0, 0, 0, 0.3)', +// ═══════════════════════════════════════════════════════════════════════════ +// BACKGROUND COLORS (Pure black for OLED) +// ═══════════════════════════════════════════════════════════════════════════ + +export const DARK = { + BASE: '#000000', + SURFACE: '#1C1C1E', + ELEVATED: '#2C2C2E', + OVERLAY_1: 'rgba(255, 255, 255, 0.05)', + OVERLAY_2: 'rgba(255, 255, 255, 0.08)', + OVERLAY_3: 'rgba(255, 255, 255, 0.12)', + SCRIM: 'rgba(0, 0, 0, 0.6)', } as const +// ═══════════════════════════════════════════════════════════════════════════ +// TEXT COLORS +// ═══════════════════════════════════════════════════════════════════════════ + export const TEXT = { PRIMARY: '#FFFFFF', - SECONDARY: 'rgba(255, 255, 255, 0.85)', - TERTIARY: 'rgba(255, 255, 255, 0.75)', - MUTED: 'rgba(255, 255, 255, 0.6)', - HINT: 'rgba(255, 255, 255, 0.45)', - DISABLED: 'rgba(255, 255, 255, 0.15)', + SECONDARY: '#EBEBF5', + TERTIARY: 'rgba(235, 235, 245, 0.6)', + MUTED: 'rgba(235, 235, 245, 0.5)', + HINT: 'rgba(235, 235, 245, 0.3)', + DISABLED: '#3A3A3C', } as const -export const BORDER = { - SUBTLE: 'rgba(255, 255, 255, 0.05)', - LIGHT: 'rgba(255, 255, 255, 0.06)', - MEDIUM: 'rgba(255, 255, 255, 0.15)', - STRONG: 'rgba(255, 255, 255, 0.3)', +// ═══════════════════════════════════════════════════════════════════════════ +// PHASE COLORS (Timer phases) +// ═══════════════════════════════════════════════════════════════════════════ + +export const PHASE = { + PREP: '#FF9500', + PREP_LIGHT: 'rgba(255, 149, 0, 0.2)', + + WORK: '#FF6B35', + WORK_LIGHT: 'rgba(255, 107, 53, 0.2)', + WORK_GLOW: 'rgba(255, 107, 53, 0.5)', + + REST: '#5AC8FA', + REST_LIGHT: 'rgba(90, 200, 250, 0.2)', + REST_GLOW: 'rgba(90, 200, 250, 0.5)', + + COMPLETE: '#30D158', + COMPLETE_LIGHT: 'rgba(48, 209, 88, 0.2)', } as const -export const APP_GRADIENTS = { - HOME: ['#0A0A14', '#1A0E2E', '#2D1810'] as const, -} as const +// ═══════════════════════════════════════════════════════════════════════════ +// LIQUID GLASS SYSTEM +// ═══════════════════════════════════════════════════════════════════════════ export const GLASS = { - FILL: 'rgba(255, 255, 255, 0.03)', - FILL_MEDIUM: 'rgba(255, 255, 255, 0.06)', - FILL_STRONG: 'rgba(255, 255, 255, 0.10)', - BORDER: 'rgba(255, 255, 255, 0.08)', - BORDER_TOP: 'rgba(255, 255, 255, 0.15)', - BLUR_LIGHT: 15, - BLUR_MEDIUM: 25, - BLUR_HEAVY: 40, - BLUR_ATMOSPHERE: 60, + // Base glass surface + BASE: { + backgroundColor: 'rgba(255, 255, 255, 0.05)', + borderColor: 'rgba(255, 255, 255, 0.1)', + borderWidth: 1, + }, + + // Elevated glass (cards, modals) + ELEVATED: { + backgroundColor: 'rgba(255, 255, 255, 0.08)', + borderColor: 'rgba(255, 255, 255, 0.15)', + borderWidth: 1, + }, + + // Inset glass (inputs, controls) + INSET: { + backgroundColor: 'rgba(0, 0, 0, 0.25)', + borderColor: 'rgba(255, 255, 255, 0.05)', + borderWidth: 1, + }, + + // Brand tinted glass + TINTED: { + backgroundColor: 'rgba(255, 107, 53, 0.12)', + borderColor: 'rgba(255, 107, 53, 0.25)', + borderWidth: 1, + }, + + // Success tinted + SUCCESS_TINTED: { + backgroundColor: 'rgba(48, 209, 88, 0.12)', + borderColor: 'rgba(48, 209, 88, 0.25)', + borderWidth: 1, + }, + + // Blur intensities (for expo-blur) + BLUR_LIGHT: 20, + BLUR_MEDIUM: 40, + BLUR_HEAVY: 60, + BLUR_ULTRA: 80, +} as const + +// ═══════════════════════════════════════════════════════════════════════════ +// SHADOWS & GLOWS +// ═══════════════════════════════════════════════════════════════════════════ + +export const SHADOW = { + // Glass shadows + sm: { + shadowColor: '#000', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.15, + shadowRadius: 12, + elevation: 4, + }, + md: { + shadowColor: '#000', + shadowOffset: { width: 0, height: 8 }, + shadowOpacity: 0.25, + shadowRadius: 24, + elevation: 8, + }, + lg: { + shadowColor: '#000', + shadowOffset: { width: 0, height: 12 }, + shadowOpacity: 0.35, + shadowRadius: 40, + elevation: 12, + }, + xl: { + shadowColor: '#000', + shadowOffset: { width: 0, height: 16 }, + shadowOpacity: 0.4, + shadowRadius: 48, + elevation: 16, + }, + + // Brand glow + BRAND_GLOW: { + shadowColor: BRAND.PRIMARY, + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.5, + shadowRadius: 20, + elevation: 10, + }, + BRAND_GLOW_SUBTLE: { + shadowColor: BRAND.PRIMARY, + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.3, + shadowRadius: 12, + elevation: 6, + }, + + // Liquid glow (breathing effect base) + LIQUID_GLOW: { + shadowColor: BRAND.PRIMARY, + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.4, + shadowRadius: 30, + elevation: 15, + }, +} as const + +// ═══════════════════════════════════════════════════════════════════════════ +// BORDER COLORS +// ═══════════════════════════════════════════════════════════════════════════ + +export const BORDER = { + GLASS: 'rgba(255, 255, 255, 0.1)', + GLASS_LIGHT: 'rgba(255, 255, 255, 0.05)', + GLASS_STRONG: 'rgba(255, 255, 255, 0.2)', + BRAND: 'rgba(255, 107, 53, 0.3)', + SUCCESS: 'rgba(48, 209, 88, 0.3)', +} as const + +// ═══════════════════════════════════════════════════════════════════════════ +// GRADIENTS +// ═══════════════════════════════════════════════════════════════════════════ + +export const GRADIENTS = { + // Video overlays + VIDEO_OVERLAY: ['transparent', 'rgba(0, 0, 0, 0.8)'], + VIDEO_TOP: ['rgba(0, 0, 0, 0.5)', 'transparent'], + + // Phase gradients + WORK: [BRAND.PRIMARY, BRAND.PRIMARY_LIGHT], + REST: [PHASE.REST, '#7DD3FC'], + PREP: [PHASE.PREP, '#FFB340'], + + // CTA + CTA: [BRAND.PRIMARY, BRAND.PRIMARY_LIGHT], + + // Glass shimmers + GLASS_SHIMMER: ['rgba(255,255,255,0.1)', 'rgba(255,255,255,0.05)', 'rgba(255,255,255,0.1)'], +} as const + +// ═══════════════════════════════════════════════════════════════════════════ +// PHASE COLORS (For timer UI) +// ═══════════════════════════════════════════════════════════════════════════ + +export const PHASE_COLORS: Record = { + PREP: { + fill: PHASE.PREP, + glow: 'rgba(255, 149, 0, 0.5)', + }, + WORK: { + fill: BRAND.PRIMARY, + glow: PHASE.WORK_GLOW, + }, + REST: { + fill: PHASE.REST, + glow: PHASE.REST_GLOW, + }, + COMPLETE: { + fill: PHASE.COMPLETE, + glow: 'rgba(48, 209, 88, 0.5)', + }, +} + +// ═══════════════════════════════════════════════════════════════════════════ +// BARREL EXPORT +// ═══════════════════════════════════════════════════════════════════════════ + +export const COLORS = { + ...BRAND, + ...DARK, + ...TEXT, + ...PHASE, + ...SHADOW, + BRAND, + DARK, + TEXT, + PHASE, + GLASS, + BORDER, + GRADIENTS, } as const diff --git a/src/shared/constants/index.ts b/src/shared/constants/index.ts index ea19544..7ddaeee 100644 --- a/src/shared/constants/index.ts +++ b/src/shared/constants/index.ts @@ -1,16 +1,10 @@ -export { - PHASE_COLORS, - PHASE_GRADIENTS, - ACCENT, - BRAND, - SURFACE, - TEXT, - BORDER, - APP_GRADIENTS, - GLASS, -} from './colors' -export { TYPOGRAPHY } from './typography' -export { SPACING, LAYOUT } from './spacing' -export { SHADOW, TEXT_SHADOW } from './shadows' -export { RADIUS } from './borderRadius' -export { DURATION, EASING, SPRING, ANIMATION } from './animations' +/** + * TabataFit Design System Constants + * Liquid Glass Design + */ + +export * from './colors' +export * from './typography' +export * from './spacing' +export * from './borderRadius' +export * from './animations' diff --git a/src/shared/constants/spacing.ts b/src/shared/constants/spacing.ts index add388c..4cfcd38 100644 --- a/src/shared/constants/spacing.ts +++ b/src/shared/constants/spacing.ts @@ -1,25 +1,42 @@ +/** + * TabataFit Spacing System + * Base: 4px + */ + export const SPACING = { 0: 0, - 0.5: 2, 1: 4, - 1.5: 6, 2: 8, - 2.5: 10, 3: 12, - 3.5: 14, 4: 16, 5: 20, 6: 24, + 7: 28, 8: 32, 10: 40, 12: 48, 14: 56, - 15: 60, + 16: 64, + 20: 80, + 24: 96, +} as const + +export const SPACE = { + NONE: 0, + XS: 4, + SM: 8, + MD: 16, + LG: 24, + XL: 32, + XXL: 48, } as const export const LAYOUT = { - PAGE_HORIZONTAL: 24, - SECTION_GAP: 40, - INLINE_GAP: 16, - CONTROLS_GAP: 32, + SCREEN_PADDING: 24, + CARD_PADDING: 16, + BUTTON_HEIGHT: 56, + BUTTON_HEIGHT_SM: 44, + TAB_BAR_HEIGHT: 83, + HEADER_HEIGHT: 44, + TOUCH_TARGET: 44, } as const diff --git a/src/shared/constants/typography.ts b/src/shared/constants/typography.ts index 5745a1c..606ae44 100644 --- a/src/shared/constants/typography.ts +++ b/src/shared/constants/typography.ts @@ -1,73 +1,262 @@ -import type { TextStyle } from 'react-native' +/** + * TabataFit Typography System + * Inter font family, Apple-inspired scale + */ + +import { TextStyle } from 'react-native' + +// ═══════════════════════════════════════════════════════════════════════════ +// FONT WEIGHTS (using Inter from @expo-google-fonts/inter) +// ═══════════════════════════════════════════════════════════════════════════ + +const FONT = { + REGULAR: 'Inter_400Regular', + MEDIUM: 'Inter_500Medium', + SEMIBOLD: 'Inter_600SemiBold', + BOLD: 'Inter_700Bold', + BLACK: 'Inter_900Black', +} as const + +// ═══════════════════════════════════════════════════════════════════════════ +// TYPE SCALE +// ═══════════════════════════════════════════════════════════════════════════ export const TYPOGRAPHY = { - countdown: { - fontSize: 140, - fontWeight: '900', - fontVariant: ['tabular-nums'], + // Display / Hero + HERO: { + fontFamily: FONT.BLACK, + fontSize: 48, + lineHeight: 56, + letterSpacing: -1, } as TextStyle, - timeDisplay: { - fontSize: 72, - fontWeight: '900', - fontVariant: ['tabular-nums'], + // Large Title (like iOS) + LARGE_TITLE: { + fontFamily: FONT.BOLD, + fontSize: 34, + lineHeight: 41, + letterSpacing: 0.37, } as TextStyle, - brandTitle: { - fontSize: 56, - fontWeight: '900', - letterSpacing: 12, + // Title 1 + TITLE_1: { + fontFamily: FONT.BOLD, + fontSize: 28, + lineHeight: 34, + letterSpacing: 0.36, } as TextStyle, - displayLarge: { - fontSize: 42, - fontWeight: '900', - letterSpacing: 4, + // Title 2 + TITLE_2: { + fontFamily: FONT.BOLD, + fontSize: 22, + lineHeight: 28, + letterSpacing: 0.35, } as TextStyle, - displaySmall: { - fontSize: 32, - fontWeight: '900', - letterSpacing: 20, - } as TextStyle, - - buttonHero: { - fontSize: 30, - fontWeight: '900', - letterSpacing: 5, - } as TextStyle, - - heading: { - fontSize: 24, - fontWeight: '800', - } as TextStyle, - - buttonMedium: { + // Title 3 + TITLE_3: { + fontFamily: FONT.SEMIBOLD, fontSize: 20, - fontWeight: '700', - letterSpacing: 2, + lineHeight: 25, + letterSpacing: 0.38, } as TextStyle, - body: { - fontSize: 18, - fontWeight: '700', + // Headline + HEADLINE: { + fontFamily: FONT.SEMIBOLD, + fontSize: 17, + lineHeight: 22, + letterSpacing: -0.41, } as TextStyle, - caption: { + // Body + BODY: { + fontFamily: FONT.REGULAR, + fontSize: 17, + lineHeight: 22, + letterSpacing: -0.41, + } as TextStyle, + + // Body Bold + BODY_BOLD: { + fontFamily: FONT.SEMIBOLD, + fontSize: 17, + lineHeight: 22, + letterSpacing: -0.41, + } as TextStyle, + + // Callout + CALLOUT: { + fontFamily: FONT.REGULAR, fontSize: 16, - fontWeight: '500', + lineHeight: 21, + letterSpacing: -0.32, } as TextStyle, - label: { + // Subheadline + SUBHEADLINE: { + fontFamily: FONT.REGULAR, fontSize: 15, - fontWeight: '800', - letterSpacing: 1, + lineHeight: 20, + letterSpacing: -0.24, } as TextStyle, - overline: { - fontSize: 11, - fontWeight: '600', - textTransform: 'uppercase', - letterSpacing: 1, + // Footnote + FOOTNOTE: { + fontFamily: FONT.REGULAR, + fontSize: 13, + lineHeight: 18, + letterSpacing: -0.08, } as TextStyle, + + // Caption 1 + CAPTION_1: { + fontFamily: FONT.REGULAR, + fontSize: 12, + lineHeight: 16, + letterSpacing: 0, + } as TextStyle, + + // Caption 2 + CAPTION_2: { + fontFamily: FONT.REGULAR, + fontSize: 11, + lineHeight: 13, + letterSpacing: 0.07, + } as TextStyle, + + // ───────────────────────────────────────────────────────────────────────── + // SPECIAL: TIMER TYPOGRAPHY + // ───────────────────────────────────────────────────────────────────────── + + // Main countdown number + TIMER_NUMBER: { + fontFamily: FONT.BLACK, + fontSize: 96, + lineHeight: 96, + letterSpacing: -2, + fontVariant: ['tabular-nums'], + } as TextStyle, + + // Timer number (compact version) + TIMER_NUMBER_COMPACT: { + fontFamily: FONT.BLACK, + fontSize: 72, + lineHeight: 72, + letterSpacing: -1.5, + fontVariant: ['tabular-nums'], + } as TextStyle, + + // Phase label (WORK, REST) + TIMER_PHASE: { + fontFamily: FONT.BOLD, + fontSize: 24, + lineHeight: 28, + letterSpacing: 2, + textTransform: 'uppercase', + } as TextStyle, + + // Round indicator + TIMER_ROUND: { + fontFamily: FONT.MEDIUM, + fontSize: 17, + lineHeight: 22, + letterSpacing: 0, + fontVariant: ['tabular-nums'], + } as TextStyle, + + // Exercise name during workout + EXERCISE_NAME: { + fontFamily: FONT.BOLD, + fontSize: 28, + lineHeight: 34, + letterSpacing: 0.36, + textAlign: 'center', + } as TextStyle, + + // ───────────────────────────────────────────────────────────────────────── + // SPECIAL: BUTTON TYPOGRAPHY + // ───────────────────────────────────────────────────────────────────────── + + BUTTON_LARGE: { + fontFamily: FONT.SEMIBOLD, + fontSize: 18, + lineHeight: 22, + letterSpacing: 0.5, + } as TextStyle, + + BUTTON_MEDIUM: { + fontFamily: FONT.SEMIBOLD, + fontSize: 16, + lineHeight: 20, + letterSpacing: 0.3, + } as TextStyle, + + BUTTON_SMALL: { + fontFamily: FONT.SEMIBOLD, + fontSize: 14, + lineHeight: 18, + letterSpacing: 0.2, + } as TextStyle, + + // ───────────────────────────────────────────────────────────────────────── + // SPECIAL: CARD TYPOGRAPHY + // ───────────────────────────────────────────────────────────────────────── + + CARD_TITLE: { + fontFamily: FONT.SEMIBOLD, + fontSize: 17, + lineHeight: 22, + letterSpacing: -0.41, + } as TextStyle, + + CARD_SUBTITLE: { + fontFamily: FONT.REGULAR, + fontSize: 14, + lineHeight: 18, + letterSpacing: -0.15, + } as TextStyle, + + CARD_METADATA: { + fontFamily: FONT.MEDIUM, + fontSize: 13, + lineHeight: 16, + letterSpacing: 0, + } as TextStyle, + + // ───────────────────────────────────────────────────────────────────────── + // SPECIAL: STATS TYPOGRAPHY + // ───────────────────────────────────────────────────────────────────────── + + STAT_VALUE: { + fontFamily: FONT.BLACK, + fontSize: 32, + lineHeight: 38, + letterSpacing: -0.5, + fontVariant: ['tabular-nums'], + } as TextStyle, + + STAT_LABEL: { + fontFamily: FONT.MEDIUM, + fontSize: 12, + lineHeight: 16, + letterSpacing: 0.5, + textTransform: 'uppercase', + } as TextStyle, + + // ───────────────────────────────────────────────────────────────────────── + // SPECIAL: OVERLINE / SECTION HEADER + // ───────────────────────────────────────────────────────────────────────── + + OVERLINE: { + fontFamily: FONT.SEMIBOLD, + fontSize: 13, + lineHeight: 16, + letterSpacing: 1.5, + textTransform: 'uppercase', + } as TextStyle, + } as const + +export { FONT }