Documentation

Guide UX Design — Pixel Night

Philosophie de design

Zéro friction pour les participants. Pas de compte, pas d'inscription — un lien suffit. L'organisateur gère tout, les participants votent en quelques secondes.

Minimalisme opinioné. Interface sombre (thème cinéma), actions claires, une seule chose à faire par écran.

Système de design

Composants UI

Pixel Night utilise shadcn/ui (Radix UI) avec Tailwind CSS 4.

  • Composants dans components/ui/ — auto-générés, ne pas modifier directement
  • Configuration dans components.json
  • Tokens de couleur définis dans styles/globals.css (variables CSS Tailwind)

Palette de couleurs

TokenUsage
backgroundFond principal — sombre (#1a1625 environ)
foregroundTexte principal
primaryAccent — actions principales, liens actifs
mutedTexte secondaire, placeholders
muted-foregroundLabels, métadonnées
borderSéparateurs, contours de cartes
cardFond des cartes et panneaux
accentHover, état actif

Typographie

  • Police principale : Geist (Next.js Google Fonts)
  • Police mono : Geist Mono (codes, slugs)
  • Tailles : système Tailwind standard

Parcours utilisateurs

Parcours Participant

Accueil (/)
    │
    ├── Saisit le code de la salle (ex: "cine-des-potes")
    │
    ▼
Page salle (/s/{slug})
    │
    ├── [Phase theme_vote]
    │     └── Affiche les thèmes → Clique sur un thème → Vote enregistré → Confirmation
    │
    ├── [Phase film_proposal]
    │     ├── Voit le thème gagnant
    │     ├── Recherche un film (TMDb) → Propose (max 3)
    │     └── Voit les propositions des autres participants
    │
    ├── [Phase film_vote]
    │     └── Affiche les films → Clique sur un film → Vote enregistré → Confirmation
    │
    └── [Phase completed]
          └── Affiche le film gagnant + résultats détaillés

Parcours Organisateur

Connexion (/auth/login)
    │
    ▼
Dashboard (/admin)
    │
    ├── Créer une soirée (/admin/soirees/nouvelle)
    │     ├── Titre, date, nombre de thèmes/films
    │     ├── Activer les propositions ? (+ durée : "2 jours", "1h30"...)
    │     └── → Soirée créée en phase "planned"
    │
    ├── Gérer la soirée (/admin/soirees/{id})
    │     │
    │     ├── [planned] → Lancer le vote thème
    │     ├── [theme_vote] → Finaliser le thème (désigne le gagnant)
    │     │                → OU lancer les propositions (si activé)
    │     ├── [film_proposal] → Clore les propositions
    │     ├── [film_vote] → Finaliser le film
    │     └── [Toute phase] → Annuler / Supprimer
    │
    └── Paramètres (/admin/parametres) → Configurer token TMDb

Inventaire des écrans

RouteAudiencePhase(s)Description
/ParticipantToutesAccueil : saisie du code salle
/s/{slug}ParticipantToutesPage principale de vote
/auth/loginOrganisateurConnexion
/auth/sign-upOrganisateurInscription
/adminOrganisateurDashboard soirées
/admin/soirees/nouvelleOrganisateurCréation soirée
/admin/soirees/{id}OrganisateurToutesGestion soirée
/admin/sallesOrganisateurGestion salles
/admin/themesOrganisateurCatalogue thèmes
/admin/parametresOrganisateurConfig TMDb
/roadmapTousFeuille de route (GitHub Issues)
/docsDéveloppeurDocumentation API (Redoc)

États et feedback utilisateur

Toasts (Sonner)

  • Succès : vert, position bottom-right
  • Erreur : rouge
  • Info : neutre

Exemples :

  • « Vote enregistré ! »
  • « Connexion réussie ! »
  • « Erreur lors de la recherche »

États de chargement

  • Boutons : spinner inline pendant l'action
  • Listes de films : skeleton (Tailwind animate-pulse)
  • Recherche TMDb : indicateur de chargement + état "aucun résultat"

États vides

  • Aucun résultat de recherche : « Aucun résultat pour '{terme}' »
  • Erreur de recherche : « Erreur lors de la recherche »
  • Aucune proposition : message explicatif

Identifiant votant anonyme

L'identifiant est un UUID v4 généré au premier accès et stocké dans localStorage sous la clé sp_voter_id. Aucune donnée personnelle n'est collectée.

Conséquences UX :

  • Vider le localStorage = perte de l'ID = possibilité de voter à nouveau (edge case accepté)
  • Navigation privée = nouvel ID à chaque session
  • Pas de "vous avez déjà voté" si l'ID est perdu

Accessibilité

  • Composants Radix UI : gestion ARIA, focus, clavier nativement
  • Contrastes : vérifier primary sur background (ratio WCAG AA minimum 4.5:1)
  • Images TMDb : attribut alt avec titre du film
  • Navigation clavier : tous les éléments interactifs focusables

Responsive

  • Layout : max-w-5xl mx-auto px-4
  • Grilles films : grid-cols-2 sm:grid-cols-3 md:grid-cols-4
  • Footer : colonne mobile, ligne desktop
  • Breakpoints Tailwind standards : sm (640px), md (768px), lg (1024px)

Composants métier notables

ComposantDescription
film-proposal-search.tsxRecherche TMDb avec états erreur/vide/chargement
soiree-phase-badge.tsxBadge coloré selon la phase
site-footer.tsxFooter avec liens GitHub, docs, roadmap
site-header.tsxEn-tête avec navigation admin conditionnelle

Points d'attention UX

  1. Durée des propositions : champ texte libre ("2 jours", "1h30") + aperçu en direct (« Durée : 1h30 »). Si format non reconnu → bouton désactivé.
  2. Thème gagnant en cas d'égalité : tirage au sort côté serveur. L'UI ne montre pas l'égalité — elle annonce directement le gagnant.
  3. Repli TMDb automatique : si la phase propositions se clôt sans proposition, les films sont récupérés automatiquement depuis TMDb. L'organisateur voit fallback: true dans la réponse API mais l'expérience participant est transparente.
  4. Annulation : un badge "Annulée" rouge s'affiche sur la page publique. Pas de vote possible.