ORIGIN_UI_UX_SYSTEM.md (v2.0.0 lock) defined a generic Tailwind sky-blue palette (#0ea5e9 etc.) that contradicted the SUMI ink-wash brand identity (#0098B5 Mizu cyan unique + data viz pigments). This commit aligns the ORIGIN lock. New file : ORIGIN_BRAND_IDENTITY.md (v1.0.0) - Codifies the canonical SUMI palette (charte §4) - Documents data viz exception (charte §4.5 — 5 viz pigments allowed) - Lists all immutable rules (no #FFFFFF, no #000000, cyan unique, etc.) - Points to source : packages/design-system/tokens/ + CHARTE_GRAPHIQUE_TALAS.md - Documents motion classification (goutte/trait/lavis/vague/maree) - Documents typography (Space Grotesk + Inter + JetBrains Mono, woff2 only) - Documents ESLint guard (no-restricted-syntax for hex literals) Updated : ORIGIN_UI_UX_SYSTEM.md - Header note marks Sections 2/3/4 as superseded by ORIGIN_BRAND_IDENTITY. - The interaction patterns / accessibility rules / anti-patterns / user flows remain authoritative. Only the numeric palette/typography stays. Updated : checksums.txt - New SHA-256 for ORIGIN_UI_UX_SYSTEM.md (header note added). - New entry for ORIGIN_BRAND_IDENTITY.md. Closes Sprint 2 follow-up #4. Sprint 2 fully shipped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1143 lines
33 KiB
Markdown
1143 lines
33 KiB
Markdown
# ORIGIN_UI_UX_SYSTEM.md
|
|
|
|
> **⚠️ NOTE post Sprint 2 (27 avril 2026)** — Les sections 2 (Design Tokens),
|
|
> 3 (Typography) et 4 (Color System) de ce document décrivaient en v2.0.0 une
|
|
> palette générique Tailwind sky-blue (`--color-primary-500: #0ea5e9` etc.).
|
|
>
|
|
> **Ces sections sont superseded par [`ORIGIN_BRAND_IDENTITY.md`](./ORIGIN_BRAND_IDENTITY.md)**,
|
|
> qui codifie la vraie palette SUMI (cyan Mizu unique #0098B5 + data viz
|
|
> exceptionnelle) alignée sur `CHARTE_GRAPHIQUE_TALAS.md`.
|
|
>
|
|
> Le présent document reste la source de vérité pour les **règles d'interaction,
|
|
> accessibilité, anti-patterns UX, user flows, breakpoints, animations
|
|
> classification**. La palette numérique stricte est dans BRAND_IDENTITY.
|
|
|
|
## 📋 RÉSUMÉ EXÉCUTIF
|
|
|
|
Ce document définit le système de design UI/UX complet et définitif pour la plateforme Veza. Il spécifie 200+ composants réutilisables, design tokens (couleurs, typographie, spacing), patterns d'interaction, responsive breakpoints, accessibility WCAG AA minimum (WCAG AAA pour les fonctions critiques), animations, anti-patterns UX interdits, et user flows assurant cohérence visuelle, expérience utilisateur éthique et maintenabilité design sur 24 mois.
|
|
|
|
## 🎯 OBJECTIFS
|
|
|
|
### Objectif Principal
|
|
Établir un design system cohérent, accessible (WCAG AA minimum, WCAG AAA pour les fonctions critiques), responsive (mobile-first), éthique (aucun dark pattern, aucune gamification), et maintenable avec 200+ composants documentés, garantissant expérience utilisateur respectueuse et réduction 50% temps développement UI.
|
|
|
|
### Objectifs Secondaires
|
|
- Cohérence visuelle absolue (zero inconsistencies)
|
|
- Accessibility WCAG AA minimum, WCAG AAA pour les fonctions critiques (navigation, lecture audio, upload, inscription)
|
|
- Responsive design (mobile, tablet, desktop)
|
|
- Dark mode support natif
|
|
- Performance (60 FPS animations)
|
|
- Éthique UX : aucun dark pattern, aucune gamification, aucun mécanisme addictif
|
|
|
|
## 📖 TABLE DES MATIÈRES
|
|
|
|
1. [Design Philosophy](#1-design-philosophy)
|
|
2. [Design Tokens](#2-design-tokens)
|
|
3. [Typography System](#3-typography-system)
|
|
4. [Color System](#4-color-system)
|
|
5. [Spacing & Layout](#5-spacing--layout)
|
|
6. [Component Library](#6-component-library)
|
|
7. [Interaction Patterns](#7-interaction-patterns)
|
|
8. [Responsive Design](#8-responsive-design)
|
|
9. [Accessibility](#9-accessibility)
|
|
10. [Animations & Transitions](#10-animations--transitions)
|
|
11. [User Flows](#11-user-flows)
|
|
12. [Figma & Prototyping](#12-figma--prototyping)
|
|
13. [Anti-patterns UX interdits](#13-anti-patterns-ux-interdits)
|
|
14. [Patterns UX positifs](#14-patterns-ux-positifs)
|
|
|
|
## 🔒 RÈGLES IMMUABLES
|
|
|
|
1. **Mobile-First**: Toujours designer mobile d'abord, desktop après
|
|
2. **Accessibility First**: WCAG AA minimum obligatoire, WCAG AAA pour les fonctions critiques (navigation, lecture audio, upload, inscription)
|
|
3. **Design Tokens Only**: Jamais de valeurs hardcodées (use CSS variables)
|
|
4. **Component Reuse**: Aucun composant custom si équivalent existe dans DS
|
|
5. **Spacing System**: Utiliser échelle 4px (4, 8, 12, 16, 24, 32, 48, 64)
|
|
6. **Dark Mode**: Support obligatoire pour tous composants
|
|
7. **Keyboard Navigation**: Tout cliquable doit être accessible au clavier
|
|
8. **Screen Reader**: Tous labels ARIA requis
|
|
9. **Performance**: 60 FPS animations (no jank)
|
|
10. **Consistency**: Zero visual inconsistencies tolérées
|
|
|
|
## 1. DESIGN PHILOSOPHY
|
|
|
|
### 1.1 Design Principles
|
|
|
|
**SIMPLICITY**
|
|
- Clean, minimal interfaces
|
|
- Remove unnecessary elements
|
|
- Focus on core actions
|
|
- Progressive disclosure
|
|
|
|
**CONSISTENCY**
|
|
- Same patterns everywhere
|
|
- Predictable interactions
|
|
- Unified visual language
|
|
- Muscle memory friendly
|
|
|
|
**ACCESSIBILITY**
|
|
- Inclusive by default
|
|
- Keyboard navigation
|
|
- Screen reader support
|
|
- High contrast modes
|
|
|
|
**PERFORMANCE**
|
|
- Fast, responsive
|
|
- 60 FPS animations
|
|
- Optimized assets
|
|
- Perceived performance
|
|
|
|
### 1.2 Visual Style
|
|
|
|
**Modern & Professional**:
|
|
- Clean, spacious layouts
|
|
- Subtle shadows and depth
|
|
- Bold, readable typography
|
|
- Vibrant accent colors
|
|
|
|
**Audio-Focused**:
|
|
- Waveform visualizations
|
|
- Audio player prominence
|
|
- Music-centric imagery
|
|
- Genre-specific themes
|
|
|
|
## 2. DESIGN TOKENS
|
|
|
|
### 2.1 Color Palette
|
|
|
|
**Primary Colors** (Brand):
|
|
```css
|
|
:root {
|
|
--color-primary-50: #f0f9ff;
|
|
--color-primary-100: #e0f2fe;
|
|
--color-primary-200: #bae6fd;
|
|
--color-primary-300: #7dd3fc;
|
|
--color-primary-400: #38bdf8;
|
|
--color-primary-500: #0ea5e9; /* Main brand color */
|
|
--color-primary-600: #0284c7;
|
|
--color-primary-700: #0369a1;
|
|
--color-primary-800: #075985;
|
|
--color-primary-900: #0c4a6e;
|
|
--color-primary-950: #082f49;
|
|
}
|
|
```
|
|
|
|
**Neutral Colors**:
|
|
```css
|
|
:root {
|
|
--color-gray-50: #f9fafb;
|
|
--color-gray-100: #f3f4f6;
|
|
--color-gray-200: #e5e7eb;
|
|
--color-gray-300: #d1d5db;
|
|
--color-gray-400: #9ca3af;
|
|
--color-gray-500: #6b7280;
|
|
--color-gray-600: #4b5563;
|
|
--color-gray-700: #374151;
|
|
--color-gray-800: #1f2937;
|
|
--color-gray-900: #111827;
|
|
--color-gray-950: #030712;
|
|
}
|
|
```
|
|
|
|
**Semantic Colors**:
|
|
```css
|
|
:root {
|
|
--color-success-500: #10b981; /* Green */
|
|
--color-warning-500: #f59e0b; /* Amber */
|
|
--color-error-500: #ef4444; /* Red */
|
|
--color-info-500: #3b82f6; /* Blue */
|
|
}
|
|
```
|
|
|
|
**Dark Mode**:
|
|
```css
|
|
:root[data-theme="dark"] {
|
|
--bg-primary: var(--color-gray-950);
|
|
--bg-secondary: var(--color-gray-900);
|
|
--bg-tertiary: var(--color-gray-800);
|
|
|
|
--text-primary: var(--color-gray-50);
|
|
--text-secondary: var(--color-gray-300);
|
|
--text-tertiary: var(--color-gray-500);
|
|
|
|
--border-primary: var(--color-gray-800);
|
|
--border-secondary: var(--color-gray-700);
|
|
}
|
|
|
|
:root[data-theme="light"] {
|
|
--bg-primary: var(--color-gray-50);
|
|
--bg-secondary: var(--color-white);
|
|
--bg-tertiary: var(--color-gray-100);
|
|
|
|
--text-primary: var(--color-gray-900);
|
|
--text-secondary: var(--color-gray-600);
|
|
--text-tertiary: var(--color-gray-500);
|
|
|
|
--border-primary: var(--color-gray-200);
|
|
--border-secondary: var(--color-gray-300);
|
|
}
|
|
```
|
|
|
|
### 2.2 Spacing Scale
|
|
|
|
**4px Base Unit**:
|
|
```css
|
|
:root {
|
|
--spacing-0: 0;
|
|
--spacing-1: 0.25rem; /* 4px */
|
|
--spacing-2: 0.5rem; /* 8px */
|
|
--spacing-3: 0.75rem; /* 12px */
|
|
--spacing-4: 1rem; /* 16px */
|
|
--spacing-5: 1.25rem; /* 20px */
|
|
--spacing-6: 1.5rem; /* 24px */
|
|
--spacing-8: 2rem; /* 32px */
|
|
--spacing-10: 2.5rem; /* 40px */
|
|
--spacing-12: 3rem; /* 48px */
|
|
--spacing-16: 4rem; /* 64px */
|
|
--spacing-20: 5rem; /* 80px */
|
|
--spacing-24: 6rem; /* 96px */
|
|
}
|
|
```
|
|
|
|
### 2.3 Typography Scale
|
|
|
|
**Font Family**:
|
|
```css
|
|
:root {
|
|
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
--font-mono: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
|
|
}
|
|
```
|
|
|
|
**Font Sizes**:
|
|
```css
|
|
:root {
|
|
--text-xs: 0.75rem; /* 12px */
|
|
--text-sm: 0.875rem; /* 14px */
|
|
--text-base: 1rem; /* 16px */
|
|
--text-lg: 1.125rem; /* 18px */
|
|
--text-xl: 1.25rem; /* 20px */
|
|
--text-2xl: 1.5rem; /* 24px */
|
|
--text-3xl: 1.875rem; /* 30px */
|
|
--text-4xl: 2.25rem; /* 36px */
|
|
--text-5xl: 3rem; /* 48px */
|
|
--text-6xl: 3.75rem; /* 60px */
|
|
}
|
|
```
|
|
|
|
**Font Weights**:
|
|
```css
|
|
:root {
|
|
--font-light: 300;
|
|
--font-normal: 400;
|
|
--font-medium: 500;
|
|
--font-semibold: 600;
|
|
--font-bold: 700;
|
|
--font-extrabold: 800;
|
|
}
|
|
```
|
|
|
|
### 2.4 Shadows
|
|
|
|
```css
|
|
:root {
|
|
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
--shadow-base: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
|
}
|
|
```
|
|
|
|
### 2.5 Border Radius
|
|
|
|
```css
|
|
:root {
|
|
--radius-none: 0;
|
|
--radius-sm: 0.125rem; /* 2px */
|
|
--radius-base: 0.25rem; /* 4px */
|
|
--radius-md: 0.375rem; /* 6px */
|
|
--radius-lg: 0.5rem; /* 8px */
|
|
--radius-xl: 0.75rem; /* 12px */
|
|
--radius-2xl: 1rem; /* 16px */
|
|
--radius-full: 9999px; /* Pill shape */
|
|
}
|
|
```
|
|
|
|
## 3. TYPOGRAPHY SYSTEM
|
|
|
|
### 3.1 Headings
|
|
|
|
```tsx
|
|
// Typography components
|
|
<h1 className="text-4xl font-bold tracking-tight text-gray-900 dark:text-white">
|
|
Heading 1
|
|
</h1>
|
|
|
|
<h2 className="text-3xl font-semibold tracking-tight text-gray-900 dark:text-white">
|
|
Heading 2
|
|
</h2>
|
|
|
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white">
|
|
Heading 3
|
|
</h3>
|
|
|
|
<h4 className="text-xl font-medium text-gray-900 dark:text-white">
|
|
Heading 4
|
|
</h4>
|
|
```
|
|
|
|
### 3.2 Body Text
|
|
|
|
```tsx
|
|
<p className="text-base text-gray-700 dark:text-gray-300">
|
|
Regular body text for content
|
|
</p>
|
|
|
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
|
Secondary body text for captions
|
|
</p>
|
|
|
|
<p className="text-xs text-gray-500 dark:text-gray-500">
|
|
Small text for metadata
|
|
</p>
|
|
```
|
|
|
|
### 3.3 Line Height
|
|
|
|
```css
|
|
:root {
|
|
--leading-none: 1;
|
|
--leading-tight: 1.25;
|
|
--leading-snug: 1.375;
|
|
--leading-normal: 1.5;
|
|
--leading-relaxed: 1.625;
|
|
--leading-loose: 2;
|
|
}
|
|
```
|
|
|
|
## 4. COLOR SYSTEM
|
|
|
|
### 4.1 Usage Guidelines
|
|
|
|
**Primary Color** (Blue): Brand identity, primary actions, links
|
|
**Gray**: Text, borders, backgrounds (neutral)
|
|
**Success** (Green): Success messages, confirmations
|
|
**Warning** (Amber): Warnings, cautions
|
|
**Error** (Red): Errors, destructive actions
|
|
**Info** (Blue): Informational messages
|
|
|
|
### 4.2 Color Contrast
|
|
|
|
**WCAG AA Requirements (toute la plateforme)** :
|
|
- **Normal Text**: Contrast ratio ≥ 4.5:1
|
|
- **Large Text** (18pt+ or 14pt+ bold): Contrast ratio ≥ 3:1
|
|
- **UI Components**: Contrast ratio ≥ 3:1
|
|
|
|
**WCAG AAA Requirements (fonctions critiques)** :
|
|
- **Normal Text**: Contrast ratio ≥ 7:1
|
|
- **Large Text** (18pt+ or 14pt+ bold): Contrast ratio ≥ 4.5:1
|
|
|
|
**Color Contrast Checker**:
|
|
```
|
|
Text on Background:
|
|
✅ Gray-900 on White: 21:1 (AAA)
|
|
✅ Gray-700 on White: 12.6:1 (AAA)
|
|
✅ Gray-600 on White: 7.5:1 (AAA)
|
|
⚠️ Gray-500 on White: 4.6:1 (AA only)
|
|
❌ Gray-400 on White: 2.9:1 (Fail)
|
|
```
|
|
|
|
## 5. SPACING & LAYOUT
|
|
|
|
### 5.1 Container Widths
|
|
|
|
```css
|
|
:root {
|
|
--container-sm: 640px;
|
|
--container-md: 768px;
|
|
--container-lg: 1024px;
|
|
--container-xl: 1280px;
|
|
--container-2xl: 1536px;
|
|
}
|
|
```
|
|
|
|
### 5.2 Grid System
|
|
|
|
**12-Column Grid**:
|
|
```tsx
|
|
<div className="grid grid-cols-12 gap-4">
|
|
<div className="col-span-12 md:col-span-8">Main content</div>
|
|
<div className="col-span-12 md:col-span-4">Sidebar</div>
|
|
</div>
|
|
```
|
|
|
|
### 5.3 Common Layouts
|
|
|
|
**Dashboard Layout**:
|
|
```
|
|
┌────────────────────────────────────┐
|
|
│ Header (sticky) │
|
|
├──────┬─────────────────────────────┤
|
|
│ │ │
|
|
│ Side │ │
|
|
│ bar │ Main Content │
|
|
│ │ │
|
|
│ │ │
|
|
└──────┴─────────────────────────────┘
|
|
```
|
|
|
|
**Track Player Layout**:
|
|
```
|
|
┌────────────────────────────────────┐
|
|
│ Header │
|
|
├────────────────────────────────────┤
|
|
│ │
|
|
│ Cover Art │
|
|
│ (centered) │
|
|
│ │
|
|
├────────────────────────────────────┤
|
|
│ Waveform Visualizer │
|
|
├────────────────────────────────────┤
|
|
│ Playback Controls │
|
|
├────────────────────────────────────┤
|
|
│ Track Info & Metadata │
|
|
└────────────────────────────────────┘
|
|
```
|
|
|
|
## 6. COMPONENT LIBRARY
|
|
|
|
### 6.1 Buttons
|
|
|
|
**Primary Button**:
|
|
```tsx
|
|
<button className="
|
|
px-4 py-2
|
|
bg-primary-600 hover:bg-primary-700 active:bg-primary-800
|
|
text-white font-medium
|
|
rounded-lg
|
|
transition-colors duration-150
|
|
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2
|
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
">
|
|
Primary Action
|
|
</button>
|
|
```
|
|
|
|
**Secondary Button**:
|
|
```tsx
|
|
<button className="
|
|
px-4 py-2
|
|
bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600
|
|
text-gray-900 dark:text-white font-medium
|
|
rounded-lg
|
|
transition-colors duration-150
|
|
">
|
|
Secondary Action
|
|
</button>
|
|
```
|
|
|
|
**Sizes**:
|
|
```tsx
|
|
// Small
|
|
<button className="px-3 py-1.5 text-sm">Small</button>
|
|
|
|
// Medium (default)
|
|
<button className="px-4 py-2 text-base">Medium</button>
|
|
|
|
// Large
|
|
<button className="px-6 py-3 text-lg">Large</button>
|
|
```
|
|
|
|
### 6.2 Inputs
|
|
|
|
**Text Input**:
|
|
```tsx
|
|
<div>
|
|
<label htmlFor="email" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Email
|
|
</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
className="
|
|
w-full px-4 py-2
|
|
border border-gray-300 dark:border-gray-600
|
|
rounded-lg
|
|
bg-white dark:bg-gray-800
|
|
text-gray-900 dark:text-white
|
|
placeholder:text-gray-400
|
|
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent
|
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
"
|
|
placeholder="you@example.com"
|
|
/>
|
|
</div>
|
|
```
|
|
|
|
**States**:
|
|
```tsx
|
|
// Error state
|
|
<input className="border-red-500 focus:ring-red-500" aria-invalid="true" aria-describedby="email-error" />
|
|
<p id="email-error" className="mt-1 text-sm text-red-600">Invalid email format</p>
|
|
|
|
// Success state
|
|
<input className="border-green-500 focus:ring-green-500" />
|
|
<p className="mt-1 text-sm text-green-600">Email available</p>
|
|
```
|
|
|
|
### 6.3 Cards
|
|
|
|
```tsx
|
|
<div className="
|
|
bg-white dark:bg-gray-800
|
|
rounded-xl
|
|
shadow-md
|
|
overflow-hidden
|
|
transition-shadow duration-200
|
|
hover:shadow-lg
|
|
">
|
|
<img src="/cover.jpg" alt="Track cover" className="w-full h-48 object-cover" />
|
|
<div className="p-4">
|
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">Track Title</h3>
|
|
<p className="text-sm text-gray-600 dark:text-gray-400">Artist Name</p>
|
|
<div className="mt-4 flex items-center justify-between">
|
|
<span className="text-xs text-gray-500">3:45</span>
|
|
<button className="text-primary-600 hover:text-primary-700">
|
|
<PlayIcon className="w-6 h-6" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### 6.4 Modals
|
|
|
|
```tsx
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm">
|
|
<div
|
|
className="
|
|
bg-white dark:bg-gray-800
|
|
rounded-2xl
|
|
shadow-2xl
|
|
max-w-md w-full
|
|
max-h-[90vh]
|
|
overflow-y-auto
|
|
"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="modal-title"
|
|
>
|
|
<div className="p-6">
|
|
<h2 id="modal-title" className="text-2xl font-bold text-gray-900 dark:text-white mb-4">
|
|
Modal Title
|
|
</h2>
|
|
<p className="text-gray-600 dark:text-gray-300">
|
|
Modal content goes here
|
|
</p>
|
|
<div className="mt-6 flex gap-3 justify-end">
|
|
<button className="px-4 py-2 text-gray-700 dark:text-gray-300">Cancel</button>
|
|
<button className="px-4 py-2 bg-primary-600 text-white rounded-lg">Confirm</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### 6.5 Audio Player
|
|
|
|
```tsx
|
|
<div className="fixed bottom-0 left-0 right-0 bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-800 shadow-2xl">
|
|
<div className="max-w-screen-2xl mx-auto px-4 py-3">
|
|
{/* Progress Bar */}
|
|
<div className="mb-2">
|
|
<div className="h-1 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
|
<div className="h-full bg-primary-600" style={{ width: '35%' }} />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Player Controls */}
|
|
<div className="flex items-center justify-between">
|
|
{/* Track Info */}
|
|
<div className="flex items-center gap-3 flex-1 min-w-0">
|
|
<img src="/cover.jpg" alt="Cover" className="w-12 h-12 rounded-md" />
|
|
<div className="min-w-0">
|
|
<h4 className="text-sm font-medium text-gray-900 dark:text-white truncate">Track Title</h4>
|
|
<p className="text-xs text-gray-600 dark:text-gray-400 truncate">Artist Name</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Controls */}
|
|
<div className="flex items-center gap-4">
|
|
<button aria-label="Previous">⏮️</button>
|
|
<button aria-label="Play/Pause" className="w-10 h-10 rounded-full bg-primary-600 text-white">▶️</button>
|
|
<button aria-label="Next">⏭️</button>
|
|
</div>
|
|
|
|
{/* Volume */}
|
|
<div className="flex items-center gap-2 flex-1 justify-end">
|
|
<button aria-label="Mute">🔊</button>
|
|
<input type="range" min="0" max="100" value="75" className="w-24" aria-label="Volume" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
## 7. INTERACTION PATTERNS
|
|
|
|
### 7.1 Hover States
|
|
|
|
```css
|
|
/* Interactive elements */
|
|
.interactive-element {
|
|
transition: all 150ms ease-in-out;
|
|
}
|
|
|
|
.interactive-element:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
```
|
|
|
|
### 7.2 Focus States
|
|
|
|
```css
|
|
/* Keyboard focus */
|
|
:focus-visible {
|
|
outline: 2px solid var(--color-primary-500);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* Remove default outline for mouse users */
|
|
:focus:not(:focus-visible) {
|
|
outline: none;
|
|
}
|
|
```
|
|
|
|
### 7.3 Loading States
|
|
|
|
```tsx
|
|
<button disabled className="relative">
|
|
<span className="opacity-0">Button Text</span>
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
|
|
</div>
|
|
</button>
|
|
```
|
|
|
|
### 7.4 Empty States
|
|
|
|
```tsx
|
|
<div className="flex flex-col items-center justify-center p-12 text-center">
|
|
<EmptyIcon className="w-24 h-24 text-gray-400 mb-4" />
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">
|
|
No tracks yet
|
|
</h3>
|
|
<p className="text-gray-600 dark:text-gray-400 mb-6">
|
|
Upload your first track to get started
|
|
</p>
|
|
<button className="px-4 py-2 bg-primary-600 text-white rounded-lg">
|
|
Upload Track
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
## 8. RESPONSIVE DESIGN
|
|
|
|
### 8.1 Breakpoints
|
|
|
|
```css
|
|
/* Mobile First */
|
|
/* Base styles (mobile): 0 - 640px */
|
|
|
|
@media (min-width: 640px) { /* sm: tablet portrait */ }
|
|
@media (min-width: 768px) { /* md: tablet landscape */ }
|
|
@media (min-width: 1024px) { /* lg: laptop */ }
|
|
@media (min-width: 1280px) { /* xl: desktop */ }
|
|
@media (min-width: 1536px) { /* 2xl: large desktop */ }
|
|
```
|
|
|
|
### 8.2 Responsive Grid
|
|
|
|
```tsx
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
|
{/* Mobile: 1 column, Tablet: 2-3 columns, Desktop: 4 columns */}
|
|
</div>
|
|
```
|
|
|
|
### 8.3 Mobile Navigation
|
|
|
|
**Bottom Tab Bar** (Mobile):
|
|
```tsx
|
|
<nav className="fixed bottom-0 left-0 right-0 bg-white dark:bg-gray-900 border-t md:hidden">
|
|
<div className="flex justify-around py-2">
|
|
<a href="/" className="flex flex-col items-center text-primary-600">
|
|
<HomeIcon className="w-6 h-6" />
|
|
<span className="text-xs mt-1">Home</span>
|
|
</a>
|
|
<a href="/search" className="flex flex-col items-center text-gray-600">
|
|
<SearchIcon className="w-6 h-6" />
|
|
<span className="text-xs mt-1">Search</span>
|
|
</a>
|
|
<a href="/library" className="flex flex-col items-center text-gray-600">
|
|
<LibraryIcon className="w-6 h-6" />
|
|
<span className="text-xs mt-1">Library</span>
|
|
</a>
|
|
</div>
|
|
</nav>
|
|
```
|
|
|
|
## 9. ACCESSIBILITY
|
|
|
|
### 9.1 WCAG AA/AAA Compliance
|
|
|
|
**Niveaux d'accessibilité** :
|
|
- **WCAG AA** : Obligatoire pour l'ensemble de la plateforme (niveau minimum)
|
|
- **WCAG AAA** : Obligatoire pour les fonctions critiques (navigation principale, lecture audio, upload de tracks, inscription/connexion, gestion de profil)
|
|
|
|
**Checklist AA (toute la plateforme)** :
|
|
- [ ] Color contrast ≥ 4.5:1 (normal text)
|
|
- [ ] Color contrast ≥ 3:1 (large text, composants UI)
|
|
- [ ] Keyboard navigation (Tab, Shift+Tab, Enter, Space, Arrow keys)
|
|
- [ ] Screen reader support (ARIA labels, roles, states)
|
|
- [ ] Focus indicators visible
|
|
- [ ] Skip links for main content
|
|
- [ ] No reliance on color alone
|
|
- [ ] Alt text for all images
|
|
- [ ] Captions for audio/video
|
|
- [ ] Form labels and error messages
|
|
|
|
**Checklist AAA (fonctions critiques)** :
|
|
- [ ] Color contrast ≥ 7:1 (normal text)
|
|
- [ ] Color contrast ≥ 4.5:1 (large text)
|
|
- [ ] Alternatives textuelles étendues
|
|
- [ ] Navigation au clavier complète sans piège de focus
|
|
- [ ] Identification cohérente des composants
|
|
- [ ] Aide contextuelle disponible
|
|
|
|
### 9.2 ARIA Labels
|
|
|
|
```tsx
|
|
// Button
|
|
<button aria-label="Play track">
|
|
<PlayIcon />
|
|
</button>
|
|
|
|
// Input
|
|
<input
|
|
type="text"
|
|
id="search"
|
|
aria-label="Search tracks"
|
|
aria-describedby="search-hint"
|
|
/>
|
|
<span id="search-hint" className="sr-only">
|
|
Search by track name, artist, or album
|
|
</span>
|
|
|
|
// Modal
|
|
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
|
|
<h2 id="modal-title">Modal Title</h2>
|
|
</div>
|
|
|
|
// Tab navigation
|
|
<div role="tablist" aria-label="Track sections">
|
|
<button role="tab" aria-selected="true" aria-controls="overview-panel">Overview</button>
|
|
<button role="tab" aria-selected="false" aria-controls="comments-panel">Comments</button>
|
|
</div>
|
|
```
|
|
|
|
### 9.3 Keyboard Navigation
|
|
|
|
**Focus Management**:
|
|
```tsx
|
|
// Trap focus in modal
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
const focusableElements = modalRef.current.querySelectorAll(
|
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
);
|
|
const firstElement = focusableElements[0];
|
|
const lastElement = focusableElements[focusableElements.length - 1];
|
|
|
|
firstElement.focus();
|
|
|
|
const handleTab = (e: KeyboardEvent) => {
|
|
if (e.key === 'Tab') {
|
|
if (e.shiftKey && document.activeElement === firstElement) {
|
|
e.preventDefault();
|
|
lastElement.focus();
|
|
} else if (!e.shiftKey && document.activeElement === lastElement) {
|
|
e.preventDefault();
|
|
firstElement.focus();
|
|
}
|
|
}
|
|
};
|
|
|
|
document.addEventListener('keydown', handleTab);
|
|
return () => document.removeEventListener('keydown', handleTab);
|
|
}
|
|
}, [isOpen]);
|
|
```
|
|
|
|
### 9.4 Screen Reader Only Content
|
|
|
|
```css
|
|
.sr-only {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
padding: 0;
|
|
margin: -1px;
|
|
overflow: hidden;
|
|
clip: rect(0, 0, 0, 0);
|
|
white-space: nowrap;
|
|
border-width: 0;
|
|
}
|
|
```
|
|
|
|
## 10. ANIMATIONS & TRANSITIONS
|
|
|
|
### 10.1 Transition Durations
|
|
|
|
```css
|
|
:root {
|
|
--duration-fast: 150ms;
|
|
--duration-base: 200ms;
|
|
--duration-slow: 300ms;
|
|
--duration-slower: 500ms;
|
|
}
|
|
```
|
|
|
|
### 10.2 Easing Functions
|
|
|
|
```css
|
|
:root {
|
|
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
```
|
|
|
|
### 10.3 Common Animations
|
|
|
|
**Fade In**:
|
|
```css
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
.fade-in {
|
|
animation: fadeIn 200ms ease-out;
|
|
}
|
|
```
|
|
|
|
**Slide Up**:
|
|
```css
|
|
@keyframes slideUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.slide-up {
|
|
animation: slideUp 300ms ease-out;
|
|
}
|
|
```
|
|
|
|
**Scale**:
|
|
```css
|
|
.scale-hover {
|
|
transition: transform 150ms ease-out;
|
|
}
|
|
|
|
.scale-hover:hover {
|
|
transform: scale(1.05);
|
|
}
|
|
```
|
|
|
|
### 10.4 Performance
|
|
|
|
**Use transform and opacity** (GPU-accelerated):
|
|
```css
|
|
/* ✅ GOOD - GPU accelerated */
|
|
.animate {
|
|
transform: translateX(100px);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
/* ❌ BAD - CPU intensive */
|
|
.animate {
|
|
left: 100px;
|
|
margin-top: 50px;
|
|
}
|
|
```
|
|
|
|
## 11. USER FLOWS
|
|
|
|
### 11.1 Registration Flow
|
|
|
|
```
|
|
1. Landing Page → Click "Sign Up"
|
|
2. Registration Form (Email, Username, Password)
|
|
3. Email Verification Sent
|
|
4. Verify Email (click link)
|
|
5. Welcome / Onboarding
|
|
6. Dashboard
|
|
```
|
|
|
|
### 11.2 Track Upload Flow
|
|
|
|
```
|
|
1. Dashboard → Click "Upload"
|
|
2. Select File (drag & drop or file picker)
|
|
3. Upload Progress (with cancel option)
|
|
4. Edit Metadata (title, artist, genre, cover art)
|
|
5. Privacy Settings (public, private, unlisted)
|
|
6. Confirm & Publish
|
|
7. Track Page (share, embed)
|
|
```
|
|
|
|
### 11.3 Audio Playback Flow
|
|
|
|
```
|
|
1. Browse Tracks → Click Track
|
|
2. Track Page Loads (cover, waveform, metadata)
|
|
3. Click Play Button
|
|
4. Audio Starts (with visualizer)
|
|
5. Mini Player Appears (bottom bar)
|
|
6. Continue Browsing (player persists)
|
|
7. Queue Management (add to queue, remove)
|
|
```
|
|
|
|
## 12. FIGMA & PROTOTYPING
|
|
|
|
### 12.1 Figma File Structure
|
|
|
|
```
|
|
Veza Design System (Figma)
|
|
├── 📄 Cover & README
|
|
├── 🎨 Design Tokens
|
|
│ ├── Colors
|
|
│ ├── Typography
|
|
│ ├── Spacing
|
|
│ └── Shadows
|
|
├── 🧩 Components
|
|
│ ├── Buttons
|
|
│ ├── Inputs
|
|
│ ├── Cards
|
|
│ ├── Modals
|
|
│ ├── Navigation
|
|
│ └── Audio Player
|
|
├── 📱 Mobile Screens
|
|
│ ├── Home
|
|
│ ├── Search
|
|
│ ├── Profile
|
|
│ └── Player
|
|
├── 💻 Desktop Screens
|
|
│ ├── Dashboard
|
|
│ ├── Upload
|
|
│ ├── Track Page
|
|
│ └── Settings
|
|
└── 🔗 Prototypes
|
|
├── Registration Flow
|
|
├── Upload Flow
|
|
└── Playback Flow
|
|
```
|
|
|
|
### 12.2 Component Variants
|
|
|
|
**Button Component**:
|
|
- Variants: Primary, Secondary, Ghost, Danger
|
|
- Sizes: Small, Medium, Large
|
|
- States: Default, Hover, Active, Disabled, Loading
|
|
|
|
### 12.3 Auto Layout
|
|
|
|
**Use Auto Layout** for:
|
|
- Flexible components (buttons, cards)
|
|
- Responsive layouts
|
|
- Consistent spacing
|
|
- Easy maintenance
|
|
|
|
## 13. ANTI-PATTERNS UX INTERDITS
|
|
|
|
Les patterns suivants sont **strictement interdits** dans toute l'interface Veza. Ils contreviennent aux principes éthiques fondamentaux du projet.
|
|
|
|
### 13.1 Gamification addictive
|
|
|
|
| Pattern interdit | Description | Raison |
|
|
|-----------------|-------------|--------|
|
|
| **Barres d'XP / points** | Systèmes de points d'expérience, niveaux, progression gamifiée | Mécanisme addictif, pression psychologique |
|
|
| **Badges de niveau** | Badges, rangs, tiers hiérarchiques entre utilisateurs | Crée des hiérarchies artificielles néfastes |
|
|
| **Compteurs de streak** | "X jours consécutifs", séries, streaks | FOMO et culpabilisation si rupture |
|
|
| **Classements publics** | Leaderboards, rankings entre artistes | Compétition toxique, découragement |
|
|
| **Récompenses variables** | Loot boxes, récompenses aléatoires | Mécanismes de jeu de hasard |
|
|
|
|
### 13.2 Notifications push agressives
|
|
|
|
- Interdit : notifications non sollicitées à haute fréquence
|
|
- Interdit : notifications de type "Vous nous manquez" / re-engagement
|
|
- Interdit : notifications qui ne correspondent pas à une action explicite de l'utilisateur
|
|
- Interdit : empilement de notifications pour forcer l'ouverture de l'app
|
|
|
|
### 13.3 FOMO (Fear Of Missing Out)
|
|
|
|
- Interdit : "X personnes regardent ceci en ce moment"
|
|
- Interdit : "Dernière chance", "Offre limitée", compteurs de temps artificiels
|
|
- Interdit : "Y personnes ont acheté ceci aujourd'hui"
|
|
- Interdit : fausse rareté ou urgence artificielle
|
|
|
|
### 13.4 Social proof anxiogène
|
|
|
|
- Interdit : compteurs publics de followers/abonnés visibles par tous
|
|
- Interdit : affichage public du nombre d'écoutes en temps réel comme métrique de valeur
|
|
- Interdit : comparaisons entre artistes ("X a plus d'écoutes que vous")
|
|
- Les métriques d'audience sont **privées**, visibles uniquement par le créateur concerné
|
|
|
|
### 13.5 Dark patterns dans les flows de paiement
|
|
|
|
- Interdit : cases pré-cochées pour abonnements ou options payantes
|
|
- Interdit : désabonnement plus difficile que l'abonnement
|
|
- Interdit : frais cachés révélés tardivement dans le flow
|
|
- Interdit : "confirm-shaming" ("Non merci, je ne veux pas soutenir les artistes")
|
|
- Interdit : renouvellement automatique sans rappel préalable clair
|
|
|
|
### 13.6 Auto-play et infinite scroll
|
|
|
|
- Interdit : auto-play de contenu audio/vidéo non sollicité
|
|
- Interdit : lecture automatique du track suivant sans consentement explicite
|
|
- Interdit : infinite scroll sans contrôle utilisateur (pagination ou bouton "Charger plus" requis)
|
|
- Interdit : pré-chargement agressif de contenu pour forcer la consommation
|
|
|
|
## 14. PATTERNS UX POSITIFS
|
|
|
|
Ces patterns sont **recommandés et encouragés** pour garantir une expérience respectueuse de l'utilisateur.
|
|
|
|
### 14.1 Contrôle utilisateur total sur les notifications
|
|
|
|
- L'utilisateur choisit exactement quelles notifications il reçoit (opt-in granulaire)
|
|
- Paramètres de fréquence configurables (immédiat, résumé quotidien, résumé hebdomadaire, désactivé)
|
|
- Un bouton "Tout désactiver" toujours accessible
|
|
- Respect du mode "Do Not Disturb" de l'OS : aucune notification ne doit contourner les paramètres système
|
|
|
|
### 14.2 Métriques privées et bienveillantes
|
|
|
|
- Les statistiques d'écoute, revenus et audience sont **visibles uniquement par le créateur concerné**
|
|
- Présentation des métriques sous forme de tendances (progression personnelle) plutôt que de valeurs absolues compétitives
|
|
- Pas de comparaison avec d'autres artistes
|
|
- Option de masquer ses propres statistiques si le créateur le souhaite
|
|
|
|
### 14.3 Confirmation explicite pour actions irréversibles
|
|
|
|
- Dialogue de confirmation clair pour : suppression de track, suppression de compte, publication publique
|
|
- Possibilité d'annulation (undo) pendant un délai raisonnable quand techniquement possible
|
|
- Wording explicite décrivant les conséquences de l'action ("Cette action supprimera définitivement votre track et toutes ses statistiques")
|
|
|
|
### 14.4 Mode hors-ligne et faible connectivité
|
|
|
|
- Les tracks téléchargées restent accessibles hors-ligne
|
|
- Indicateur clair de l'état de connectivité
|
|
- Les actions effectuées hors-ligne sont synchronisées automatiquement au retour de la connexion
|
|
- Dégradation gracieuse : l'interface reste fonctionnelle même avec une connexion lente (affichage progressif, placeholders)
|
|
|
|
### 14.5 Respect du mode "Do Not Disturb" OS
|
|
|
|
- L'application détecte et respecte le mode DND de l'OS
|
|
- Aucune notification sonore ou visuelle envoyée pendant le DND
|
|
- Les notifications en attente sont délivrées silencieusement à la fin du DND
|
|
|
|
### 14.6 Transparence et honnêteté
|
|
|
|
- Pricing affiché clairement dès le départ, sans frais cachés
|
|
- Processus de désabonnement aussi simple que l'abonnement (max 2 clics)
|
|
- Explication claire de l'utilisation des données personnelles
|
|
- Aucun tracking publicitaire, aucune revente de données
|
|
|
|
## ✅ CHECKLIST DE VALIDATION
|
|
|
|
### Design System
|
|
- [ ] Design tokens defined (colors, typography, spacing)
|
|
- [ ] 200+ components documented
|
|
- [ ] Figma library complete
|
|
- [ ] Dark mode support
|
|
- [ ] Responsive breakpoints defined
|
|
|
|
### Accessibility
|
|
- [ ] WCAG AA compliance sur toute la plateforme
|
|
- [ ] WCAG AAA compliance sur les fonctions critiques (navigation, lecture, upload, inscription)
|
|
- [ ] Keyboard navigation functional
|
|
- [ ] Screen reader tested (NVDA, JAWS, VoiceOver)
|
|
- [ ] Focus indicators visible
|
|
- [ ] Color contrast validated (AA : 4.5:1 normal, AAA : 7:1 fonctions critiques)
|
|
|
|
### Éthique UX
|
|
- [ ] Aucun pattern de gamification (XP, badges, streaks, leaderboards)
|
|
- [ ] Aucun dark pattern dans les flows de paiement/abonnement
|
|
- [ ] Notifications opt-in uniquement, granulaires
|
|
- [ ] Métriques privées (visibles uniquement par le créateur)
|
|
- [ ] Aucun auto-play non sollicité
|
|
- [ ] Aucun infinite scroll sans contrôle
|
|
- [ ] Confirmation explicite pour actions irréversibles
|
|
|
|
### Performance
|
|
- [ ] 60 FPS animations
|
|
- [ ] No layout shifts (CLS < 0.1)
|
|
- [ ] Optimized images (WebP, lazy loading)
|
|
- [ ] Bundle size optimized
|
|
|
|
### Documentation
|
|
- [ ] Component props documented
|
|
- [ ] Usage examples provided
|
|
- [ ] Do's and Don'ts specified
|
|
- [ ] Figma components synced with code
|
|
|
|
## 📊 MÉTRIQUES DE SUCCÈS
|
|
|
|
### Design System Adoption
|
|
- **Component Reuse**: > 80%
|
|
- **Custom Components**: < 10%
|
|
- **Design Consistency Score**: > 95%
|
|
- **Development Time Reduction**: > 50%
|
|
|
|
### Accessibility
|
|
- **WCAG AA Compliance**: 100% de la plateforme
|
|
- **WCAG AAA Compliance**: 100% des fonctions critiques (navigation, lecture, upload, inscription)
|
|
- **Keyboard Navigation**: 100% functional
|
|
- **Screen Reader Support**: 100% labeled
|
|
|
|
### User Experience
|
|
- **Lighthouse Accessibility**: 100
|
|
- **User Satisfaction**: > 4.5/5
|
|
- **Task Completion Rate**: > 90%
|
|
|
|
## 🔄 HISTORIQUE DES VERSIONS
|
|
|
|
| Version | Date | Changements |
|
|
|---------|------|-------------|
|
|
| 1.0.0 | 2025-11-02 | Version initiale - Design system complet |
|
|
| 2.0.0 | 2026-03-04 | Audit éthique : ajout anti-patterns UX interdits (gamification, FOMO, dark patterns), patterns UX positifs (contrôle notifications, métriques privées, mode hors-ligne), révision accessibilité WCAG AA minimum / AAA fonctions critiques |
|
|
|
|
---
|
|
|
|
## ⚠️ AVERTISSEMENT
|
|
|
|
**CE DESIGN SYSTEM EST IMMUABLE**
|
|
|
|
---
|
|
|
|
**Document créé par**: Design Team + UX Lead
|
|
**Date de création**: 2025-11-02
|
|
**Dernière révision**: 2026-03-04 (v2.0.0)
|
|
**Prochaine révision**: Quarterly (2026-06-01)
|
|
**Propriétaire**: Design Lead
|
|
|
|
**Statut**: ✅ **APPROUVÉ ET VERROUILLÉ**
|
|
|