Design: Platform Vision — Cross-Module UX Patterns¶
Brand: Papillon HR Suite¶
Date: 14/03/2026¶
Version: 1.0¶
Author: DESIGNER (Claude — Senior UX/UI Designer)¶
Depends on: docs/design/host-shell-design.md (Sprint 0 shell)¶
PRD: docs/prd/platform-vision-prd.md¶
For the DEVELOPER: This document defines every cross-cutting UX pattern shared by ALL modules. The host-shell-design.md covers the app shell (login, navigation, dashboard layout, sync indicator, notifications, PWA, dark mode, breakpoints). This document covers everything ELSE at the platform level: onboarding, tenant switching, module gating/upsell, approvals, billing, employee import, offline conflict resolution, and tenant status degradation.
If something is ambiguous, the design is wrong — flag it.
Table of Contents¶
- Design Decisions (Interview Summary)
- User Flow Diagrams
- Screen-by-Screen Wireframes
- Interaction Specifications
- Responsive Behavior
- Offline Behavior
- French Micro-copy
- Component Specs
- Motion Choreography
- Brand Compliance Checklist
1. Design Decisions¶
Nine UX decisions were resolved through collaborative interview with the Product Owner. Each decision is referenced by ID (D1–D9) throughout this document.
D1: Onboarding Flow — Step-by-Step Wizard¶
Decision: 5-step wizard with progress bar. One decision per screen. Auto-save per step. Resume on reconnect.
Rationale: Reduces cognitive load (Hick's Law). Familiar to target users from Wave/M-Pesa/Orange Money flows. Auto-save per step = offline-resilient. On 360px, each step fits without scrolling.
Steps: Account creation (public) → Company info → Owner status → Module selection + payment → Employee import (optional).
D2: Tenant Switcher — Top-Bar Company Badge¶
Decision: Company name always visible in the top bar. Tap opens tenant list (bottom sheet on mobile, dropdown on desktop). Single-tenant users see name only — no switcher UI.
Rationale: 80% of users belong to one tenant (zero overhead for them). 2-tap switch for the 20% (accountants managing multiple companies). Constant context awareness — Don Norman's principle of visibility.
D3: Module Upsell — Preview + CTA Card¶
Decision: Tapping a locked module opens a rich preview (bottom sheet on mobile, popover on desktop) with illustration, 3 benefits, segment-aware pricing, and "Essayer gratuitement (14j)" CTA.
Rationale: Zeigarnik Effect — showing what they COULD have creates upgrade desire. Segment-aware pricing enables instant mobile purchasing decisions (PLG). "Me notifier au lancement" toggle captures interest for unreleased modules.
D4: Unified Approval Inbox¶
Decision: Single "Approbations" screen lists ALL pending approvals across modules. Filter chips by module type. Swipe-to-approve on mobile. Online-only.
Rationale: Fitts's Law — grouping related actions reduces completion time. The DG opens ONE screen and processes all pending items in 2 minutes instead of visiting 3-4 module screens.
D5: Tenant Status Degradation — Persistent Banner + Functional Overlay¶
Decision: Warm-toned banner at top of every screen. All screens remain navigable (read-only). Write actions show contextual overlay with "Régulariser →" CTA. Never blocks navigation.
Rationale: Loss aversion — users feel losses 2x more than gains. Showing them their data (read-only) reminds them what they're losing. A full-screen block feels punitive and causes churn.
D6: Sync Conflicts — Auto-Resolve + Notification¶
Decision: 95% auto-resolved (server wins for approvals/financial ops, client wins for drafts). Clear notification explains what happened. 5% edge cases show "Garder ma version / Garder la version serveur" — no "Merge" option.
Rationale: Nielsen's heuristic — error recovery > error prevention. Most conflicts have an obvious correct answer. Manual merge is too complex for target users.
D7: Employee Import — Mobile-Capable with Desktop Nudge¶
Decision: Mobile uses card list per employee. Desktop uses editable spreadsheet table. For 30+ employees on mobile, non-blocking suggestion: "Pour plus de confort, terminez depuis un ordinateur."
Rationale: 85% of tenants (S1-S2) have ≤29 employees — card list works perfectly on mobile for them. Blocking mobile-only DGs (who may not have a desktop) violates mobile-first principle. Desktop nudge for large imports respects user choice.
D8: Owner Status — Checkbox Fork + Magic Link Delegation¶
Decision: Onboarding step 3 includes "Je suis le Représentant Légal" checkbox. - Checked → ask salarié/indépendant directly. - Unchecked → 3 options: "Oui salarié" / "Non indépendant" / "Je ne sais pas → envoyer un lien au gérant." - Magic link: tokenized URL, single-screen micro-form, no login, expires 7 days. Onboarding continues with INDEPENDANT as safe default.
Rationale: The person onboarding is typically the HR Manager, not the DG. Design for the real workflow: ask questions to the person who can answer them. When they can't answer, delegate asynchronously via magic link.
D9: Billing Page — Single Scrollable Page with Sections¶
Decision: One page: Plan summary card → Active modules list → Payment method → Invoice history. No tabs.
Rationale: DG reads top card and leaves (5-second glance). Comptable scrolls for invoice details. Progressive disclosure via scroll — no tab-switching needed.
2. User Flow Diagrams¶
2.1 Self-Onboarding Flow (D1, D8)¶
flowchart TD
A[Landing page / Marketing site] --> B[Tap 'Créer mon compte']
B --> C[Public signup form]
C -->|Email + Phone + Password| D{CAPTCHA valid?}
D -->|No| C
D -->|Yes| E[Account created — PENDING_VERIFICATION]
E --> F[Email verification sent]
F --> G{Email verified?}
G -->|No — resend| F
G -->|Yes| H[Wizard Step 1: Infos entreprise]
H -->|Company name, form, employee range, country| I[Wizard Step 2: Votre rôle + Statut gérant]
I -->|"Je suis le RL" checked| J[Ask salarié/indépendant directly]
I -->|"Je suis le RL" unchecked| K{HR knows DG status?}
K -->|Oui salarié| L[Set owner = SALARIE]
K -->|Non indépendant| M[Set owner = INDEPENDANT]
K -->|Je ne sais pas| N[Magic link form: DG name + contact]
N --> O[Send magic link to DG]
O --> P[Set owner = INDEPENDANT — pending DG response]
J --> Q[Set owner status]
L --> R[Wizard Step 3: Choix des modules]
M --> R
P --> R
Q --> R
R -->|Select modules, see pricing| S[Wizard Step 4: Paiement]
S -->|CinetPay: Orange Money / Wave / Card| T{Payment result?}
T -->|Success| U[Tenant = ACTIVE]
T -->|Failed| V[Tenant = PAYMENT_REQUIRED]
T -->|Bank transfer chosen| W[Tenant = ACTIVE_PAYMENT_PENDING]
T -->|Free trial| X[Tenant = TRIAL — 14 days]
U --> Y[Wizard Step 5: Import employés — optional]
V --> Y
W --> Y
X --> Y
Y -->|Skip| Z[First login — Dashboard]
Y -->|Upload Excel| AA[Parse + Editable confirmation]
AA --> AB{Errors?}
AB -->|Fix errors| AA
AB -->|All valid| AC[Submit — create employees + send invitations]
AC --> Z
Z --> AD[🎉 Confetti — Bienvenue sur Papillon !]
style U fill:#d4edda
style V fill:#f8d7da
style W fill:#fff3cd
style X fill:#cce5ff
2.2 CRM-Assisted Onboarding Flow¶
flowchart TD
A[Salesperson creates prospect in CRM] --> B[Prospect validated by CRM manager]
B --> C[Tenant = PENDING_VALIDATION]
C --> D{CRM manager approves?}
D -->|Yes| E[Tenant provisioned — PENDING]
D -->|No| F[Prospect rejected]
E --> G[Admin invitation email sent to DG/HR]
G --> H[DG/HR clicks link — lands on Wizard Step 1]
H --> I[Same wizard flow as self-onboarding]
2.3 Tenant Switching Flow (D2)¶
flowchart TD
A[User logged in — Tenant A active] --> B[Tap company badge in top bar]
B --> C[Tenant list opens — bottom sheet / dropdown]
C --> D[User selects Tenant B]
D --> E{Online?}
E -->|Yes| F[JWT re-issued with new tenant_id]
F --> G[Subtle transition animation]
G --> H[Dashboard reloads for Tenant B]
E -->|No — offline| I[Switch to cached Tenant B data]
I --> J[Show 'Données hors-ligne' indicator]
J --> H
2.4 Module Activation Flow (D3)¶
flowchart TD
A[User taps locked module in nav] --> B[Preview card opens — bottom sheet / popover]
B --> C{Module released?}
C -->|Yes — available| D[Show: illustration + benefits + pricing + CTA]
C -->|No — coming soon| E[Show: illustration + benefits + 'Me notifier' toggle]
D --> F{User taps 'Essayer gratuitement'?}
F -->|Yes| G{User is DG/Admin?}
G -->|Yes| H[Module activated — TRIAL — 14 days]
G -->|No| I[Show: 'Seul un administrateur peut activer un module.']
F -->|No — close| J[Preview dismissed]
H --> K[Nav item unlocked — full color]
K --> L[User navigates to new module]
E --> M{User toggles 'Me notifier'?}
M -->|Yes| N[Notification preference saved]
M -->|No| J
2.5 Employee Import Flow (D7)¶
flowchart TD
A[Admin opens 'Import employés'] --> B{Device?}
B -->|Mobile| C[Show upload zone + 'ou ajouter un par un']
B -->|Desktop| D[Show upload zone + template download]
C --> E[User selects Excel file]
D --> E
E --> F[Parsing — skeleton shimmer]
F --> G{Parse success?}
G -->|Error — bad format| H[Show: 'Format non reconnu. Téléchargez le modèle.']
G -->|Success| I{Employee count?}
I -->|≤29 on mobile| J[Show editable card list]
I -->|30+ on mobile| K[Show desktop nudge — non-blocking]
K --> J
I -->|Desktop| L[Show editable spreadsheet table]
J --> M[User reviews/edits — fixes errors]
L --> M
M --> N{Validation errors?}
N -->|Yes| O[Summary: '47 employés, 3 erreurs à corriger']
O --> M
N -->|All valid| P[Tap 'Créer X employés']
P --> Q[Confirm: contact method per employee — EMAIL / SMS]
Q --> R[Submit — create employees]
R --> S[Send password creation links via selected channel]
S --> T[Success: '47 employés créés ! Invitations envoyées.']
style H fill:#f8d7da
style T fill:#d4edda
2.6 Owner Status Magic Link Flow (D8)¶
flowchart TD
A[HR picks 'Je ne sais pas' during onboarding] --> B[Mini-form: DG name + email/phone]
B --> C[Tap 'Envoyer le lien']
C --> D[System sends tokenized magic link via email/SMS]
D --> E[Onboarding continues — owner = INDEPENDANT default]
F[DG receives SMS/email with link] --> G[DG taps link — single-screen micro-form]
G --> H{DG chooses?}
H -->|Oui salarié| I[System updates owner = SALARIE]
H -->|Non indépendant| J[System confirms owner = INDEPENDANT]
I --> K[Employee record created for owner]
K --> L[Dashboard shows updated status]
J --> L
M[Link expires after 7 days?] --> N[Reminder sent — new link]
N --> G
style I fill:#d4edda
style J fill:#d4edda
2.7 Cross-Module Approval Flow (D4)¶
flowchart TD
A[Employee submits request — leave/commitment/expense] --> B[Notification sent to approver]
B --> C[Approver sees badge on dashboard + notification bell]
C --> D[Approver opens Approbations screen]
D --> E[List of pending approvals — filtered by type]
E --> F{Approver action?}
F -->|Approve — tap button or swipe right| G{Online?}
F -->|Refuse — tap button or swipe left| H{Online?}
F -->|Tap card for detail| I[Full request detail screen]
I --> F
G -->|Yes| J[Request approved — notification to employee]
G -->|No| K[Show: 'Connexion requise pour approuver']
H -->|Yes| L[Refuse modal: mandatory comment field]
L --> M[Request refused — notification to employee]
H -->|No| K
style J fill:#d4edda
style M fill:#f8d7da
style K fill:#fff3cd
2.8 Billing Resolution Flow (D5, D9)¶
flowchart TD
A[Tenant status → PAYMENT_REQUIRED or SUSPENDED] --> B[Degradation banner appears on all screens]
B --> C[User taps 'Régulariser' on banner or overlay]
C --> D[Billing page — Plan summary shows overdue status]
D --> E{Payment method?}
E -->|CinetPay — Orange Money / Wave / Card| F{Payment result?}
E -->|Bank transfer| G[Show bank details + reference]
F -->|Success| H[Tenant → ACTIVE — banner removed]
F -->|Failed| I[Show: 'Paiement échoué. Réessayer.']
I --> E
G --> J[Tenant → ACTIVE_PAYMENT_PENDING — 10 day grace]
J --> K{Transfer received within 10 days?}
K -->|Yes — admin confirms| H
K -->|No| L[Tenant → SUSPENDED]
style H fill:#d4edda
style L fill:#f8d7da
2.9 Sync Conflict Resolution Flow (D6)¶
flowchart TD
A[Device reconnects — sync begins] --> B[Send queued offline writes to server]
B --> C{Server accepts?}
C -->|No conflict — accepted| D[✓ Synced notification]
C -->|Conflict detected| E{Conflict type?}
E -->|Approval on cancelled request| F[Auto-resolve: server wins]
E -->|Financial op — stale data| G[Auto-resolve: server wins]
E -->|Draft data — both modified| H{Same field modified?}
F --> I[Notification: 'Approbation non appliquée — demande annulée']
G --> J[Notification: 'Opération non appliquée — données modifiées']
H -->|No — different fields| K[Auto-merge: combine both]
H -->|Yes — same field| L[Manual resolution required]
L --> M[Show: 'Garder ma version' / 'Garder la version serveur']
M --> N[User chooses]
N --> O[Conflict resolved — data saved]
K --> D
I --> D
J --> D
O --> D
style D fill:#d4edda
style L fill:#fff3cd
3. Screen-by-Screen Wireframes¶
3.1 Onboarding Wizard — Public Signup (before wizard)¶
Shaped by: D1 (step-by-step wizard)
MOBILE (360px):
┌──────────────────────────────────┐
│ │
│ 🦋 Papillon HR Suite │
│ Votre assistant RH │
│ de confiance. │
│ │
│ Nom complet │
│ ┌────────────────────────────┐ │
│ │ Jean-Pierre Kouassi │ │
│ └────────────────────────────┘ │
│ │
│ Email │
│ ┌────────────────────────────┐ │
│ │ [email protected] │ │
│ └────────────────────────────┘ │
│ │
│ Téléphone │
│ ┌──────┐ ┌──────────────────┐ │
│ │+225 ▼│ │ 07 89 12 34 56 │ │
│ └──────┘ └──────────────────┘ │
│ │
│ Mot de passe │
│ ┌────────────────────────────┐ │
│ │ •••••••• 👁 │ │
│ └────────────────────────────┘ │
│ Min. 8 caractères, 1 majuscule │
│ │
│ ┌────────────────────────────┐ │
│ │ Créer mon compte │ │
│ └────────────────────────────┘ │
│ │
│ Déjà inscrit ? Se connecter │
│ │
│ En créant un compte, vous │
│ acceptez les CGU et la │
│ politique de confidentialité. │
└──────────────────────────────────┘
Components: uses Button variant=primary size=lg fullWidth, Input with label/helperText, phone prefix uses Select (or custom country code picker).
States: - Loading: Button shows spinner on submit - Error: Inline validation under each field. "Cette adresse email est déjà utilisée." / "Mot de passe trop court (min. 8 caractères)." - Offline: "Connexion requise pour créer un compte." overlay — account creation is online-only - Success: Navigate to email verification screen
3.2 Email Verification Screen¶
MOBILE (360px):
┌──────────────────────────────────┐
│ │
│ 🦋 Papillon │
│ │
│ ✉️ │
│ │
│ Vérifiez votre email │
│ │
│ Un lien de vérification a été │
│ envoyé à : │
│ [email protected] │
│ │
│ Cliquez sur le lien dans │
│ l'email pour continuer. │
│ │
│ │
│ Vous n'avez rien reçu ? │
│ ┌────────────────────────────┐ │
│ │ Renvoyer l'email │ │
│ └────────────────────────────┘ │
│ │
│ 💡 Vérifiez aussi vos │
│ courriers indésirables. │
│ │
└──────────────────────────────────┘
Components: uses Button variant=secondary size=lg fullWidth
States: - Loading: "Renvoi en cours..." on button - Success (resend): "Email renvoyé ✓" toast - Error: "Impossible de renvoyer. Réessayez." toast
3.3 Wizard Step 1: Infos entreprise¶
Shaped by: D1
MOBILE (360px):
┌──────────────────────────────────┐
│ ← │
│ ○───●───○───○───○ 1/5 │
│ │
│ 🏢 Votre entreprise │
│ │
│ Nom de l'entreprise │
│ ┌────────────────────────────┐ │
│ │ ALTARYS SARL │ │
│ └────────────────────────────┘ │
│ │
│ Forme juridique │
│ ┌────────────────────────────┐ │
│ │ SARL ▼ │ │
│ └────────────────────────────┘ │
│ Options: SARL, SAS, SA, EI, │
│ Autre │
│ │
│ Nombre d'employés │
│ ┌────────────────────────────┐ │
│ │ 2-12 (TPE) ▼ │ │
│ └────────────────────────────┘ │
│ Options: 2-12, 13-29, 30-49, │
│ 50-99, 100-199, 200-350 │
│ │
│ Pays │
│ ┌────────────────────────────┐ │
│ │ 🇨🇮 Côte d'Ivoire ✓ │ │
│ └────────────────────────────┘ │
│ Pre-filled. MVP = CI only. │
│ │
│ RCCM (optionnel) │
│ ┌────────────────────────────┐ │
│ │ │ │
│ └────────────────────────────┘ │
│ 💡 Vous avez 3 mois pour le │
│ renseigner. │
│ │
│ ┌────────────────────────────┐ │
│ │ Continuer → │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
Smart defaults: Country pre-filled from IP geolocation (CI for MVP). Phone prefix pre-filled from country. Currency auto-set (XOF).
Validation: Company name required (min 2 chars). Form juridique required. Employee count required. RCCM optional (FR-PV-110).
3.4 Wizard Step 2: Votre rôle + Statut gérant¶
Shaped by: D8 (checkbox fork + magic link delegation)
MOBILE (360px) — Initial state:
┌──────────────────────────────────┐
│ ← │
│ ○───○───●───○───○ 2/5 │
│ │
│ 👤 Votre rôle │
│ │
│ ☐ Je suis le Représentant │
│ Légal de l'entreprise │
│ (gérant, DG, président) │
│ │
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │
│ (content below depends on │
│ checkbox state) │
│ │
└──────────────────────────────────┘
IF CHECKED — user IS the Représentant Légal:
┌──────────────────────────────────┐
│ ← │
│ ○───○───●───○───○ 2/5 │
│ │
│ 👤 Votre rôle │
│ │
│ ☑ Je suis le Représentant │
│ Légal de l'entreprise │
│ │
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │
│ Recevez-vous un salaire de │
│ votre propre entreprise ? │
│ │
│ ┌────────────────────────────┐ │
│ │ 👔 Oui, je suis salarié │ │
│ │ │ │
│ │ Je reçois un salaire, │ │
│ │ j'ai un bulletin de paie, │ │
│ │ et des cotisations CNPS. │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 🏢 Non, indépendant │ │
│ │ │ │
│ │ Je gère l'entreprise │ │
│ │ sans bulletin de paie. │ │
│ │ Pas de CNPS ni de congés │ │
│ │ comptabilisés. │ │
│ └────────────────────────────┘ │
│ │
│ 💡 Modifiable à tout moment │
│ dans les paramètres. │
│ │
│ ┌────────────────────────────┐ │
│ │ Continuer → │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
IF UNCHECKED — user is NOT the Représentant Légal (typically HR Manager):
┌──────────────────────────────────┐
│ ← │
│ ○───○───●───○───○ 2/5 │
│ │
│ 👤 Votre rôle │
│ │
│ ☐ Je suis le Représentant │
│ Légal de l'entreprise │
│ │
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │
│ Le gérant de l'entreprise │
│ reçoit-il un salaire ? │
│ │
│ ┌────────────────────────────┐ │
│ │ 👔 Oui, il est salarié │ │
│ │ Il reçoit un bulletin de │ │
│ │ paie et des cotisations. │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 🏢 Non, il est indépendant │ │
│ │ Pas de bulletin de paie. │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 📩 Je ne sais pas │ │
│ │ Envoyer un lien au gérant │ │
│ │ pour qu'il réponde. │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ Continuer → │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
IF "Je ne sais pas" selected — magic link delegation form appears:
┌──────────────────────────────────┐
│ ← │
│ ○───○───●───○───○ 2/5 │
│ │
│ 📩 Envoyer un lien au gérant │
│ │
│ Nous enverrons un lien pour │
│ qu'il réponde lui-même. │
│ │
│ Nom du gérant │
│ ┌────────────────────────────┐ │
│ │ KOUASSI Jean-Pierre │ │
│ └────────────────────────────┘ │
│ │
│ Email ou téléphone │
│ ┌────────────────────────────┐ │
│ │ +225 07 89 12 34 56 │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ Envoyer le lien 📩 │ │
│ └────────────────────────────┘ │
│ │
│ 💡 En attendant sa réponse, │
│ le gérant sera configuré comme │
│ indépendant. Ce choix sera │
│ modifié dès qu'il répondra. │
│ │
│ ┌────────────────────────────┐ │
│ │ Continuer → │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
After "Envoyer le lien" success:
│ ┌────────────────────────────┐ │
│ │ ✓ Lien envoyé à │ │
│ │ KOUASSI Jean-Pierre │ │
│ │ (+225 07 89 12 34 56) │ │
│ │ │ │
│ │ En attente de sa réponse. │ │
│ └────────────────────────────┘ │
3.5 Wizard Step 3: Choix des modules¶
Shaped by: D3 (module upsell), D9 (pricing)
MOBILE (360px):
┌──────────────────────────────────┐
│ ← │
│ ○───○───○───●───○ 3/5 │
│ │
│ 📦 Choisissez vos modules │
│ │
│ Segment S1 (2-12 employés) │
│ Sélectionnez un ou plusieurs : │
│ │
│ ┌────────────────────────────┐ │
│ │ ☑ 🏖 Congés & Absences │ │
│ │ Demandes, soldes, │ │
│ │ approbations. │ │
│ │ 12 000 FCFA/mois │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ☑ 📱 Pointage QR │ │
│ │ Pointage par QR code, │ │
│ │ géolocalisation. │ │
│ │ 5 000 FCFA/mois │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ☐ 💰 Engagements & Budget │ │
│ │ Bons de commande, │ │
│ │ suivi budgétaire. │ │
│ │ 10 000 FCFA/mois │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ☐ 📊 Paie │ │
│ │ Bulletins de paie, │ │
│ │ cotisations CNPS. │ │
│ │ 30 000 FCFA/mois │ │
│ └────────────────────────────┘ │
│ │
│ 💡 Pack Contrôle (Congés + QR) │
│ 15 000 FCFA/mois au lieu de │
│ 17 000 — Économisez 12% ! │
│ [Appliquer le pack] │
│ │
│ ┌─ Récapitulatif ────────────┐ │
│ │ 2 modules sélectionnés │ │
│ │ Total : 17 000 FCFA/mois │ │
│ │ │ │
│ │ 💡 Essai gratuit 14 jours │ │
│ │ disponible ! │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ Continuer → │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
Pack detection: When the user's selection matches a pack (e.g., Absences + QR = Pack Contrôle), show a suggestion with savings. Uses smart pricing from the PRD §A.8 pricing grid.
Segment awareness: Module prices change based on the employee range selected in Step 1. The segment label (S1-S6) is displayed. For S4-S6, per-user pricing is shown with Platform Fee explanation.
3.6 Wizard Step 4: Paiement¶
MOBILE (360px):
┌──────────────────────────────────┐
│ ← │
│ ○───○───○───○───● 4/5 │
│ │
│ 💳 Paiement │
│ │
│ Récapitulatif │
│ ┌────────────────────────────┐ │
│ │ 🏖 Congés 12 000 │ │
│ │ 📱 Pointage QR 5 000 │ │
│ │ ──────────────────────── │ │
│ │ Total 17 000 FCFA/mois │ │
│ └────────────────────────────┘ │
│ │
│ Fréquence de facturation │
│ ┌────────────────────────────┐ │
│ │ ● Mensuel — 17 000 FCFA │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ ○ Annuel — 12 mois payés, │ │
│ │ 14 mois offerts ! 🎁 │ │
│ │ 204 000 FCFA/an │ │
│ └────────────────────────────┘ │
│ │
│ Moyen de paiement │
│ ┌────────────────────────────┐ │
│ │ 🟠 Orange Money │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ 🔵 Wave │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ 💳 Carte bancaire │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ 🏦 Virement bancaire │ │
│ └────────────────────────────┘ │
│ │
│ ── ou ── │
│ │
│ ┌────────────────────────────┐ │
│ │ 🆓 Essai gratuit 14 jours │ │
│ │ Accès complet, sans │ │
│ │ engagement. Pas de carte │ │
│ │ requise. │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ Payer → │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
CinetPay integration: Selecting Orange Money / Wave / Card opens the CinetPay payment widget (embedded or redirect). Bank transfer shows bank details + unique reference.
Free trial: No payment info required. 14 days full access. After trial, status → PAYMENT_REQUIRED (read-only).
3.7 Wizard Step 5: Import employés (optional)¶
Shaped by: D7 (mobile-capable + desktop nudge)
MOBILE (360px) — Initial state:
┌──────────────────────────────────┐
│ ← │
│ ○───○───○───○───● 5/5 │
│ │
│ 👥 Ajoutez vos employés │
│ │
│ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │
│ │ │ │
│ │ 📄 Glissez votre │ │
│ │ fichier Excel ici │ │
│ │ ou │ │
│ │ [Choisir un fichier] │ │
│ │ │ │
│ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │
│ │
│ 📥 Télécharger le modèle Excel │
│ │
│ ── ou ── │
│ │
│ ┌────────────────────────────┐ │
│ │ + Ajouter un employé │ │
│ │ manuellement │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ Passer cette étape → │ │
│ └────────────────────────────┘ │
│ Vous pourrez ajouter vos │
│ employés plus tard. │
│ │
└──────────────────────────────────┘
After Excel upload — mobile card list (D7):
MOBILE (360px):
┌──────────────────────────────────┐
│ ← Import employés │
│ 12 employés · 1 erreur 🔴 │
│ │
│ ┌────────────────────────────┐ │
│ │ KOUASSI Jean-Pierre ✏️ │ │
│ │ [email protected] │ │
│ │ Direction Générale │ │
│ │ Contact: [●Email] [SMS] │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ DIABATÉ Aminata 🔴 ✏️ │ │
│ │ Téléphone manquant │ │
│ │ Comptabilité │ │
│ │ Contact: [Email] [●SMS] │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ +225 │ │ │
│ │ └──────────────────────┘ │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ TRAORÉ Adama ✏️ │ │
│ │ [email protected] │ │
│ │ Production │ │
│ │ Contact: [●Email] [SMS] │ │
│ └────────────────────────────┘ │
│ │
│ ... (scroll for more) │
│ │
│ ┌────────────────────────────┐ │
│ │ Créer 12 employés │ │
│ └────────────────────────────┘ │
│ ⚠ 1 erreur à corriger │
│ │
└──────────────────────────────────┘
Desktop table (1024px+):
┌──────────────────────────────────────────────────────────────────┐
│ ← Import employés 12 employés · 1 erreur [Créer 12] │
│ │
│ Nom │ Prénom │ Email │ Dépt │ Contact │
│ ────────────┼───────────┼──────────────┼─────────┼──────────── │
│ KOUASSI │ Jean-P. │ [email protected]│ DG │ ● Email │
│ DIABATÉ 🔴 │ Aminata │ (vide) │ Compta │ ● SMS │
│ TRAORÉ │ Adama │ [email protected]│ Prod │ ● Email │
│ ... │
└──────────────────────────────────────────────────────────────────┘
30+ employees on mobile — desktop nudge:
┌──────────────────────────────────┐
│ 47 employés importés │
│ │
│ ┌────────────────────────────┐ │
│ │ 💡 Pour plus de confort, │ │
│ │ vous pouvez terminer │ │
│ │ l'import depuis un │ │
│ │ ordinateur. Votre fichier │ │
│ │ est sauvegardé. │ │
│ │ │ │
│ │ [Continuer ici] │ │
│ │ [Terminer plus tard] │ │
│ └────────────────────────────┘ │
│ │
│ (card list below if continue) │
└──────────────────────────────────┘
3.8 Owner Status Magic Link — DG Micro-Form (D8)¶
What the DG sees when they tap the link — no login required:
MOBILE (360px):
┌──────────────────────────────────┐
│ │
│ 🦋 Papillon │
│ │
│ Bonjour Jean-Pierre, │
│ │
│ Aminata configure Papillon │
│ HR Suite pour ALTARYS SARL. │
│ │
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │
│ Recevez-vous un salaire de │
│ votre entreprise ? │
│ │
│ ┌────────────────────────────┐ │
│ │ 👔 Oui, je suis salarié │ │
│ │ │ │
│ │ Je reçois un bulletin de │ │
│ │ paie et des cotisations │ │
│ │ CNPS. │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 🏢 Non, je suis │ │
│ │ indépendant │ │
│ │ │ │
│ │ Pas de bulletin de paie │ │
│ │ ni de cotisations. │ │
│ └────────────────────────────┘ │
│ │
│ 💡 Vous pourrez modifier ce │
│ choix à tout moment dans │
│ l'application. │
│ │
└──────────────────────────────────┘
After DG responds:
┌──────────────────────────────────┐
│ │
│ 🦋 Papillon │
│ │
│ ✓ │
│ │
│ Merci Jean-Pierre ! │
│ │
│ Votre statut a été mis à jour. │
│ │
│ ┌────────────────────────────┐ │
│ │ Accéder à Papillon → │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
3.9 Tenant Switcher (D2)¶
Shaped by: D2. See also host-shell-design.md §5 for top bar layout.
Top bar — single-tenant user (no switcher):
Top bar — multi-tenant user:
┌──────────────────────────────────┐
│ 🦋 [ALTARYS SARL ▼] 🔔 👤 │
└──────────────────────────────────┘
Bottom sheet (mobile) — on tap:
┌──────────────────────────────────┐
│ ─── (drag handle) ─── │
│ │
│ Changer d'entreprise │
│ │
│ ┌────────────────────────────┐ │
│ │ ● ALTARYS SARL │ │
│ │ Comptable · 12 employés │ │
│ │ ━━━━━━━━━━ (active) │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ○ DIALLO & Fils │ │
│ │ Comptable · 8 employés │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ○ Cabinet Médical Abidjan │ │
│ │ Comptable · 23 employés │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
Component: TenantSwitcher — see §8.1.
Interaction: Tapping a different tenant triggers JWT re-issue (online) or local context switch (offline). Transition: content area does a 200ms crossfade.
3.10 Module Upsell Preview (D3)¶
Bottom sheet (mobile):
┌──────────────────────────────────┐
│ ─── (drag handle) ─── │
│ ✕ Core RH │
│ │
│ ┌────────────────────────────┐ │
│ │ [warm geometric SVG │ │
│ │ illustration suggesting │ │
│ │ employee file management]│ │
│ └────────────────────────────┘ │
│ │
│ Le dossier complet de │
│ vos employés │
│ │
│ ✓ Fiches employé détaillées │
│ ✓ Import Excel en masse │
│ ✓ Documents et pièces jointes │
│ │
│ À partir de 12 000 FCFA/mois │
│ (votre segment : S1, 2-12 emp.)│
│ │
│ ┌────────────────────────────┐ │
│ │ Essayer gratuitement 14j 🆓│ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 🔔 Me notifier au lancement│ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
For unreleased modules — CTA changes:
│ Ce module sera bientôt │
│ disponible. │
│ │
│ ┌────────────────────────────┐ │
│ │ 🔔 Me notifier au lancement│ │
│ └────────────────────────────┘ │
3.11 Unified Approval Inbox (D4)¶
MOBILE (360px):
┌──────────────────────────────────┐
│ ← Approbations ⚡ 4 │
│ │
│ ┌─ Filtres ─────────────────┐ │
│ │ [●Tous] [Congés] [Engage.]│ │
│ └───────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 🏖 Congé annuel il y a 2h│
│ │ DIABATÉ Aminata │ │
│ │ 15/04 → 22/04 (5 jours) │ │
│ │ Solde après : 18 jours │ │
│ │ │ │
│ │ [Refuser] [✓ Approuver] │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 🏖 Congé maladie hier │ │
│ │ TRAORÉ Adama │ │
│ │ 10/04 → 12/04 (3 jours) │ │
│ │ 📎 Certificat médical │ │
│ │ │ │
│ │ [Refuser] [✓ Approuver] │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 💰 Engagement lun. │ │
│ │ Fournitures bureau │ │
│ │ 350 000 FCFA · Comptabilité│ │
│ │ │ │
│ │ [Refuser] [✓ Approuver] │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 💰 Engagement lun. │ │
│ │ Cartouches imprimante │ │
│ │ 85 000 FCFA · Production │ │
│ │ │ │
│ │ [Refuser] [✓ Approuver] │ │
│ └────────────────────────────┘ │
│ │
│ ← Swipe gauche/droite │
│ pour refuser/approuver │
│ │
└──────────────────────────────────┘
Refuse flow — mandatory comment:
┌──────────────────────────────────┐
│ Refuser la demande │
│ │
│ DIABATÉ Aminata │
│ Congé annuel · 15/04 → 22/04 │
│ │
│ Motif du refus (obligatoire) │
│ ┌────────────────────────────┐ │
│ │ Période déjà prise par │ │
│ │ un collègue. │ │
│ └────────────────────────────┘ │
│ │
│ [Annuler] [Confirmer refus] │
└──────────────────────────────────┘
Empty state (no pending approvals):
│ ✓ │
│ │
│ Aucune approbation en attente │
│ │
│ Vous êtes à jour ! Revenez │
│ quand de nouvelles demandes │
│ arriveront. │
3.12 Billing / Subscription Management (D9)¶
Shaped by: D9 (single scrollable page)
MOBILE (360px):
┌──────────────────────────────────┐
│ ← Abonnement │
│ │
│ ┌─ Votre plan ──────────────┐ │
│ │ S2 · 13-29 employés │ │
│ │ Statut : ● Actif │ │
│ │ │ │
│ │ 45 000 FCFA/mois │ │
│ │ Prochain paiement : │ │
│ │ 01/04/2026 │ │
│ │ │ │
│ │ Facturation : Mensuelle │ │
│ │ [Passer en annuel →] │ │
│ │ 🎁 12 mois = 14 offerts │ │
│ └────────────────────────────┘ │
│ │
│ Modules actifs │
│ ┌────────────────────────────┐ │
│ │ ✓ Congés & Absences │ │
│ │ 15 000 FCFA/mois │ │
│ ├────────────────────────────┤ │
│ │ ✓ Pointage QR │ │
│ │ 10 000 FCFA/mois │ │
│ ├────────────────────────────┤ │
│ │ ✓ Engagements │ │
│ │ 20 000 FCFA/mois │ │
│ │ (incl. Lignes budgétaires)│ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ + Ajouter un module │ │
│ └────────────────────────────┘ │
│ │
│ Moyen de paiement │
│ ┌────────────────────────────┐ │
│ │ 🟠 Orange Money ··7823 │ │
│ │ [Modifier] │ │
│ └────────────────────────────┘ │
│ │
│ Historique des factures │
│ ┌────────────────────────────┐ │
│ │ Mars 2026 45 000 ⏳ En │ │
│ │ cours │ │
│ ├────────────────────────────┤ │
│ │ Fév. 2026 45 000 ✓ Payé │ │
│ │ [📄] │ │
│ ├────────────────────────────┤ │
│ │ Jan. 2026 45 000 ✓ Payé │ │
│ │ [📄] │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
"Ajouter un module" flow: Opens the same module preview cards (D3) in a list view, with "Activer" CTA instead of "Essayer gratuitement."
3.13 Degradation Banners (D5)¶
Shaped by: D5 (persistent banner + functional overlay)
Four banner variants, ordered by severity:
TRIAL_EXPIRING (warm info — not urgent yet):
┌──────────────────────────────────┐
│ 💡 Essai gratuit : 3 jours │
│ restants. [Souscrire →] │
└──────────────────────────────────┘
Token: --color-info background. Dismissable (reappears daily).
PAYMENT_REQUIRED (amber warning):
┌──────────────────────────────────┐
│ ⚠️ Paiement requis │
│ Vos données sont en lecture │
│ seule. [Régulariser →] │
└──────────────────────────────────┘
Token: --color-warning background. Not dismissable.
ACTIVE_INCOMPLETE_READONLY (amber warning):
┌──────────────────────────────────┐
│ ⚠️ Informations manquantes │
│ Complétez votre RCCM pour │
│ retrouver l'accès. [Compléter →] │
└──────────────────────────────────┘
Token: --color-warning background. Not dismissable.
SUSPENDED (red — critical):
┌──────────────────────────────────┐
│ 🔴 Compte suspendu │
│ Régularisez votre abonnement │
│ sous 10 jours. [Régulariser →] │
└──────────────────────────────────┘
Token: --color-error background. Not dismissable. Shows countdown.
Write action overlay (shown when user taps a write action in degraded state):
┌──────────────────────────────────┐
│ │
│ ┌────────────────────────────┐ │
│ │ │ │
│ │ Action non disponible │ │
│ │ │ │
│ │ Régularisez votre │ │
│ │ abonnement pour │ │
│ │ continuer à utiliser │ │
│ │ Papillon. │ │
│ │ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ Régulariser → │ │ │
│ │ └──────────────────────┘ │ │
│ │ │ │
│ │ [Fermer] │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
3.14 Sync Conflict Resolution (D6)¶
Auto-resolved notification (95% of cases):
┌──────────────────────────────────┐
│ 🔄 Synchronisation terminée │
│ │
│ ✓ 3 actions synchronisées │
│ ⚠ 1 conflit résolu : │
│ │
│ ┌────────────────────────────┐ │
│ │ Approbation congé DIABATÉ │ │
│ │ Non appliquée : la demande │ │
│ │ a été annulée par │ │
│ │ l'employé. │ │
│ │ [OK] │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
Manual conflict resolution (5% edge cases):
┌──────────────────────────────────┐
│ ⚠ Conflit de données │
│ │
│ Note de frais : Taxi Plateau │
│ │
│ Votre version : │
│ ┌────────────────────────────┐ │
│ │ 2 500 FCFA · Transport │ │
│ │ Modifié hors-ligne │ │
│ └────────────────────────────┘ │
│ │
│ Version serveur : │
│ ┌────────────────────────────┐ │
│ │ 3 000 FCFA · Transport │ │
│ │ Modifié par vous │ │
│ │ sur ordinateur │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ Garder ma version │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ Garder la version serveur│ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
3.15 Employee Self-Service Profile (FR-PV-095/096)¶
Baseline profile (Control Plane — always available):
MOBILE (360px):
┌──────────────────────────────────┐
│ ← Mon profil │
│ │
│ ┌────────────────────────────┐ │
│ │ 👤 │ │
│ │ KOUASSI Jean-Pierre │ │
│ │ CDI · Direction Générale │ │
│ │ Agent de maîtrise │ │
│ └────────────────────────────┘ │
│ │
│ Informations │
│ ┌────────────────────────────┐ │
│ │ Email │ │
│ │ [email protected] │ │
│ ├────────────────────────────┤ │
│ │ Téléphone │ │
│ │ +225 07 89 12 34 56 │ │
│ ├────────────────────────────┤ │
│ │ Département │ │
│ │ Direction Générale │ │
│ ├────────────────────────────┤ │
│ │ Poste │ │
│ │ Directeur Adjoint │ │
│ ├────────────────────────────┤ │
│ │ Responsable │ │
│ │ DIALLO Mamadou (DG) │ │
│ ├────────────────────────────┤ │
│ │ Date d'embauche │ │
│ │ 15/03/2024 │ │
│ ├────────────────────────────┤ │
│ │ Matricule │ │
│ │ ALT-2024-03-001 │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ 📥 Exporter mes données │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
If HR Core is active — additional sections appear below (enriched fields): - Informations personnelles (date de naissance, nationalité, situation familiale) - Contacts d'urgence - Informations bancaires (RIB) - Documents joints - Historique des modifications
All fields read-only for the employee (FR-PV-095).
3.16 Data Export (FR-PV-092)¶
Shaped by: FR-PV-092 (employee self-export — privacy right)
MOBILE (360px):
┌──────────────────────────────────┐
│ ← Exporter mes données │
│ │
│ Téléchargez une copie de │
│ toutes vos données personnelles │
│ (droit à la portabilité, │
│ Loi n°2013-450). │
│ │
│ Contenu de l'export : │
│ ┌────────────────────────────┐ │
│ │ ✓ Mon profil │ │
│ │ ✓ Mes bulletins de paie │ │
│ │ ✓ Mon historique de congés │ │
│ │ ✓ Mes documents joints │ │
│ └────────────────────────────┘ │
│ │
│ Format : ZIP (PDF + CSV) │
│ │
│ ┌────────────────────────────┐ │
│ │ Générer l'export 📥 │ │
│ └────────────────────────────┘ │
│ │
│ 💡 La génération peut prendre │
│ quelques minutes. Vous serez │
│ notifié quand le fichier sera │
│ prêt. │
│ │
└──────────────────────────────────┘
After generation:
│ ┌────────────────────────────┐ │
│ │ ✓ Export prêt ! │ │
│ │ export-kouassi-2026.zip │ │
│ │ 2.3 Mo │ │
│ │ │ │
│ │ [Télécharger] │ │
│ └────────────────────────────┘ │
3.17 Settings Hierarchy¶
Shaped by: D8 (owner status in settings), D9 (billing access)
MOBILE (360px):
┌──────────────────────────────────┐
│ ← Paramètres │
│ │
│ Mon compte │
│ ┌────────────────────────────┐ │
│ │ 👤 Mon profil → │ │
│ ├────────────────────────────┤ │
│ │ 🔐 Mot de passe → │ │
│ ├────────────────────────────┤ │
│ │ 🌙 Mode sombre ○● │ │
│ ├────────────────────────────┤ │
│ │ 🔔 Notifications → │ │
│ └────────────────────────────┘ │
│ │
│ Entreprise (admin only) │
│ ┌────────────────────────────┐ │
│ │ 🏢 Infos entreprise → │ │
│ ├────────────────────────────┤ │
│ │ 👔 Statut du gérant → │ │
│ ├────────────────────────────┤ │
│ │ 🗓 Exercice fiscal → │ │
│ ├────────────────────────────┤ │
│ │ 🏗 Structure org. → │ │
│ ├────────────────────────────┤ │
│ │ 👥 Utilisateurs → │ │
│ ├────────────────────────────┤ │
│ │ 🔑 Rôles & permissions → │ │
│ └────────────────────────────┘ │
│ │
│ Abonnement (admin only) │
│ ┌────────────────────────────┐ │
│ │ 💳 Mon abonnement → │ │
│ └────────────────────────────┘ │
│ │
│ À propos │
│ ┌────────────────────────────┐ │
│ │ 📋 CGU → │ │
│ ├────────────────────────────┤ │
│ │ 🔒 Confidentialité → │ │
│ ├────────────────────────────┤ │
│ │ ℹ️ Version 1.0.0 │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ Se déconnecter │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘
"Statut du gérant" sub-screen (accessible from settings — D8 post-onboarding change):
┌──────────────────────────────────┐
│ ← Statut du gérant │
│ │
│ KOUASSI Jean-Pierre │
│ Représentant Légal │
│ │
│ Statut actuel : │
│ ┌────────────────────────────┐ │
│ │ ● Indépendant │ │
│ │ Pas de bulletin de paie │ │
│ │ ni de cotisations CNPS. │ │
│ └────────────────────────────┘ │
│ │
│ ┌────────────────────────────┐ │
│ │ ○ Salarié │ │
│ │ Bulletin de paie, │ │
│ │ cotisations CNPS, │ │
│ │ droits aux congés. │ │
│ └────────────────────────────┘ │
│ │
│ ⚠ Modifier ce statut affecte │
│ la paie et les déclarations │
│ CNPS. Le changement prend │
│ effet au prochain mois. │
│ │
│ ┌────────────────────────────┐ │
│ │ Enregistrer │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
4. Interaction Specifications¶
4.1 Global Interaction Rules¶
| Rule | Specification |
|---|---|
| Auto-save | All form fields auto-save on blur (text) or on change (toggles, selects). Visual: brief green check icon next to field. |
| Validation | Inline, on blur. French messages. Never blocks typing. Error text appears below field with slide-down animation (150ms). |
| Touch targets | 48×48px minimum for all interactive elements. |
| Swipe gestures | Approval cards: swipe right = approve (green reveal), swipe left = refuse (red reveal). Confirm with haptic feedback. |
| Loading | Skeleton shimmer for content areas. Button spinner for form submissions. Never bare spinners. |
| Transitions | Screen enter: slide up 12px + fade in (200ms). Modal/sheet: slide up from bottom (300ms). Never hard cuts. |
| Keyboard (desktop) | Enter = submit form. Escape = close modal/sheet. Tab = next field. |
4.2 Per-Screen State Table¶
| Screen | Loading | Empty | Error | Offline | Success |
|---|---|---|---|---|---|
| Onboarding wizard | Skeleton shimmer on step load | N/A (steps always have content) | Inline field errors in French | "Connexion requise" overlay (account creation is online-only) | Step transition with progress bar fill animation |
| Tenant switcher | Shimmer list (3 placeholder items) | N/A (user has ≥1 tenant) | "Impossible de charger vos entreprises. Réessayer." | Shows cached tenant list with "Données hors-ligne" label | Crossfade transition to new tenant dashboard |
| Module preview | Shimmer card | N/A | "Impossible de charger les détails. Réessayer." | Shows cached module info if available, else "Connectez-vous pour voir les détails." | Trial activation: check animation + nav item unlocks with color pop |
| Approval inbox | Shimmer cards (3 placeholders) | Illustration + "Aucune approbation en attente. Vous êtes à jour !" | "Impossible de charger les approbations. Réessayer." | "Connexion requise pour approuver. Vos approbations seront disponibles dès la reconnexion." | Approved card slides out right (green). Refused slides out left (red). Badge count decrements. |
| Employee import | Parsing skeleton (table rows shimmer) | Upload zone with template download | "Format non reconnu. Téléchargez le modèle." / per-row validation errors | Upload requires connectivity. Editing cached import data works offline. | "47 employés créés ! Invitations envoyées." with confetti burst |
| Billing page | Shimmer sections (plan card + module list + invoices) | N/A (always has plan info) | "Impossible de charger l'abonnement." | Shows cached billing info with "Dernière mise à jour : il y a 2h" | Payment success: green check + banner removal animation |
| Self-service profile | Shimmer card + shimmer rows | N/A (user always has a profile) | "Impossible de charger votre profil." | Shows cached profile with timestamp | N/A (read-only) |
| Data export | "Génération en cours..." progress indicator | N/A | "Impossible de générer l'export. Réessayer." | "Connexion requise pour générer un export." | "Export prêt !" with download button |
| Sync conflicts | N/A (appears after sync) | N/A (only shown when conflicts exist) | N/A | N/A (only appears on reconnection) | Resolved: card fades out. All resolved: "Tout est synchronisé ✓" toast |
| Degradation banners | N/A (instant) | N/A | N/A | Banner still shows (status is cached) | Payment success: banner slides up and disappears (300ms) |
4.3 Swipe Gesture Specification (Approval Inbox)¶
SWIPE RIGHT (Approve):
┌────────────────────────────────┐
│ ✓ APPROUVER │ 🏖 Congé annuel │
│ (green bg) │ DIABATÉ Aminata │
│ │ 15/04 → 22/04 │
└────────────────────────────────┘
← swipe reveals green ✓ action
SWIPE LEFT (Refuse):
┌────────────────────────────────┐
│ 🏖 Congé annuel │ ✗ REFUSER │
│ DIABATÉ Aminata │ (red bg) │
│ 15/04 → 22/04 │ │
└────────────────────────────────┘
swipe reveals red ✗ action →
Threshold: 40% of card width triggers action.
Below threshold: card snaps back.
Haptic: light vibration on threshold cross.
Refuse always opens comment modal (mandatory).
5. Responsive Behavior¶
5.1 Breakpoints¶
| Breakpoint | Width | Target |
|---|---|---|
| Phone | 360–767px | Primary design target |
| Tablet | 768–1023px | Enhanced layout |
| Desktop | 1024–1439px | Full experience |
| Wide desktop | 1440px+ | Maximum density |
5.2 Per-Screen Responsive Adaptations¶
| Screen | Phone (360px) | Tablet (768px) | Desktop (1024px+) |
|---|---|---|---|
| Onboarding wizard | Full-width, single column. CTA at bottom of viewport. | Centered card (560px max), branding illustration on sides. | Split layout: illustration left (40%), form right (60%). |
| Tenant switcher | Bottom sheet (full-width, swipe to dismiss). | Bottom sheet (centered, 480px max). | Dropdown below company badge (320px wide, max 5 items visible then scroll). |
| Module preview | Bottom sheet (full-width). | Bottom sheet (centered, 480px max). | Popover card anchored to nav item (400px wide). |
| Approval inbox | Stacked cards, full-width. Swipe gestures. | 2-column card grid. Swipe on cards. | List view with inline actions (no swipe needed). Filter sidebar on left (240px). |
| Employee import | Card list (one card per employee). | Card grid (2 columns). | Editable table with inline editing. |
| Billing page | Single column, stacked sections. | Single column, wider cards. | Two columns: plan + modules left (60%), invoices + payment right (40%). |
| Self-service profile | Single column. | Centered card (560px). | Card with sidebar navigation for enriched sections (if HR Core active). |
| Settings | Full-width grouped list. | Centered (560px). | Sidebar navigation (240px) + content area (right). |
6. Offline Behavior¶
6.1 Offline Capability Matrix¶
| Screen / Action | Offline Read | Offline Write | Sync Behavior |
|---|---|---|---|
| Onboarding wizard | ❌ | ❌ | Online-only. Account creation, payment, and email verification require connectivity. |
| Tenant switcher | ✅ Cached tenant list | N/A | Tenant list cached in IndexedDB. Offline switch uses cached data for selected tenant. |
| Module preview | ✅ Cached module info | ❌ Module activation = online-only | Module details cached after first view. Trial activation requires connectivity. |
| Approval inbox | ✅ Cached pending list | ❌ Approve/refuse = online-only | Approval list cached. "Connexion requise pour approuver" overlay on action buttons. |
| Employee import | ✅ Cached import data (mid-import) | ✅ Edits to import data saved locally | Upload = online-only. Editing parsed data = offline. Submit = online-only. Auto-save edits to IndexedDB. |
| Billing page | ✅ Cached billing info | ❌ Payment = online-only | Plan, modules, invoices cached. "Dernière mise à jour" timestamp shown. |
| Self-service profile | ✅ Cached profile | ❌ Read-only | Profile data cached. Works fully offline. |
| Data export | ❌ | ❌ | Export generation requires server. "Connexion requise." |
| Settings | ✅ Cached settings | ✅ Dark mode toggle only | Most settings changes require connectivity. Dark mode is local. |
| Dashboard | ✅ Cached KPIs + approvals count | N/A | Shows cached data with "Dernière mise à jour" timestamp. |
6.2 Sync Conflict Resolution Rules (D6)¶
| Data Type | Conflict Rule | Rationale |
|---|---|---|
| Approval actions | Server wins | If someone cancelled a request while you were offline, their action takes precedence. |
| Financial operations | Server wins | Budget state may have changed. Server has latest truth. |
| Draft leave requests | Client wins | User's latest edits are their intent. |
| Draft expense entries | Client wins | User's latest edits are their intent. |
| Clock-in/clock-out | Auto-merge (append) | Timestamps don't conflict — they stack. |
| Profile data (same field changed) | Manual resolution | Show both versions, user picks. |
| Settings changes | Last-write wins | Rare conflict. Most recent change applies. |
6.3 Offline Visual Indicators¶
See host-shell-design.md §8 for the sync status indicator. Additional patterns for this document:
Online-only action overlay (shown when user taps a blocked action):
┌────────────────────────────────┐
│ 📡 Connexion requise │
│ │
│ Cette action nécessite une │
│ connexion internet. │
│ │
│ Elle sera disponible dès la │
│ reconnexion. │
│ │
│ [OK] │
└────────────────────────────────┘
7. French Micro-copy¶
7.1 Onboarding Wizard¶
| Element | Text |
|---|---|
| Public signup title | Créez votre compte |
| Public signup CTA | Créer mon compte |
| Public signup — existing user | Déjà inscrit ? Se connecter |
| Public signup — CGU | En créant un compte, vous acceptez les CGU et la politique de confidentialité. |
| Email verification title | Vérifiez votre email |
| Email verification body | Un lien de vérification a été envoyé à {email}. Cliquez sur le lien dans l'email pour continuer. |
| Email verification — resend | Vous n'avez rien reçu ? Renvoyer l'email |
| Email verification — spam tip | 💡 Vérifiez aussi vos courriers indésirables. |
| Step 1 title | 🏢 Votre entreprise |
| Step 1 — RCCM helper | 💡 Vous avez 3 mois pour le renseigner. |
| Step 2 title | 👤 Votre rôle |
| Step 2 — RL checkbox | Je suis le Représentant Légal de l'entreprise (gérant, DG, président) |
| Step 2 — salarié card | 👔 Oui, je suis salarié — Je reçois un salaire, j'ai un bulletin de paie, et des cotisations CNPS. |
| Step 2 — indépendant card | 🏢 Non, indépendant — Je gère l'entreprise sans bulletin de paie. Pas de CNPS ni de congés comptabilisés. |
| Step 2 — don't know | 📩 Je ne sais pas — Envoyer un lien au gérant pour qu'il réponde lui-même. |
| Step 2 — changeable | 💡 Modifiable à tout moment dans les paramètres. |
| Step 2 — link sent | ✓ Lien envoyé à {name} ({contact}). En attente de sa réponse. |
| Step 2 — default while waiting | 💡 En attendant sa réponse, le gérant sera configuré comme indépendant. Ce choix sera modifié dès qu'il répondra. |
| Step 3 title | 📦 Choisissez vos modules |
| Step 3 — pack suggestion | 💡 Pack {name} : {price} FCFA/mois au lieu de {sum} — Économisez {percent}% ! |
| Step 3 — trial notice | 💡 Essai gratuit 14 jours disponible ! |
| Step 4 title | 💳 Paiement |
| Step 4 — annual upsell | 🎁 12 mois payés, 14 mois offerts ! |
| Step 4 — free trial | 🆓 Essai gratuit 14 jours — Accès complet, sans engagement. Pas de carte requise. |
| Step 5 title | 👥 Ajoutez vos employés |
| Step 5 — upload zone | 📄 Glissez votre fichier Excel ici ou Choisir un fichier |
| Step 5 — template | 📥 Télécharger le modèle Excel |
| Step 5 — manual add | + Ajouter un employé manuellement |
| Step 5 — skip | Passer cette étape → Vous pourrez ajouter vos employés plus tard. |
| Step 5 — summary | {n} employés · {e} erreurs à corriger |
| Step 5 — desktop nudge | 💡 Pour plus de confort, vous pouvez terminer l'import depuis un ordinateur. Votre fichier est sauvegardé. |
| Step 5 — submit | Créer {n} employés |
| Step 5 — success | {n} employés créés ! Invitations envoyées. 🎉 |
| Progress | Continuer → |
7.2 Magic Link (DG receives)¶
| Element | Text |
|---|---|
| Greeting | Bonjour {name}, |
| Context | {onboarder_name} configure Papillon HR Suite pour {company_name}. |
| Question | Recevez-vous un salaire de votre entreprise ? |
| Salarié | 👔 Oui, je suis salarié — Je reçois un bulletin de paie et des cotisations CNPS. |
| Indépendant | 🏢 Non, je suis indépendant — Pas de bulletin de paie ni de cotisations. |
| Changeable | 💡 Vous pourrez modifier ce choix à tout moment dans l'application. |
| Success | Merci {name} ! Votre statut a été mis à jour. |
| CTA after success | Accéder à Papillon → |
7.3 Tenant Switcher¶
| Element | Text |
|---|---|
| Sheet title | Changer d'entreprise |
| Active badge | (active) |
| Role display | {role} · {n} employés |
7.4 Module Upsell¶
| Module | One-liner | Benefit 1 | Benefit 2 | Benefit 3 |
|---|---|---|---|---|
| Congés & Absences | Gérez les congés simplement | Demandes et approbations en 2 taps | Soldes automatiques par type de congé | Export vers la paie |
| Pointage QR | Pointage par QR code | Scan QR depuis le téléphone | Géolocalisation optionnelle | Historique et exports CSV |
| Engagements & Budget | Maîtrisez vos dépenses | Bons de commande et validations | Suivi budgétaire en temps réel | Alertes de dépassement |
| Paie | Bulletins de paie conformes | Calcul automatique CNPS/ITS | Génération des bulletins | Historique et archivage |
| Core RH | Le dossier complet de vos employés | Fiches employé détaillées | Import Excel en masse | Documents et pièces jointes |
| CRM Interne | Suivez vos prospects | Pipeline de vente visuel | Suivi des commissions | Conversion prospect → client |
Common elements:
| Element | Text |
|---|---|
| Pricing | À partir de {price} FCFA/mois (votre segment : {segment}) |
| Trial CTA | Essayer gratuitement 14j 🆓 |
| Notify toggle | 🔔 Me notifier au lancement |
| Coming soon | Ce module sera bientôt disponible. |
| Admin required | Seul un administrateur peut activer un module. |
7.5 Approval Inbox¶
| Element | Text |
|---|---|
| Screen title | Approbations |
| Badge | ⚡ {n} |
| Filter: all | Tous |
| Filter: leave | Congés |
| Filter: commitment | Engagements |
| Leave card | 🏖 {leave_type} · {employee_name} · {start} → {end} ({days} jours) · Solde après : {balance} jours |
| Commitment card | 💰 {description} · {amount} FCFA · {department} |
| Approve button | ✓ Approuver |
| Refuse button | Refuser |
| Refuse modal title | Refuser la demande |
| Refuse comment label | Motif du refus (obligatoire) |
| Refuse confirm | Confirmer refus |
| Empty state | Aucune approbation en attente. Vous êtes à jour ! |
| Offline overlay | Connexion requise pour approuver. Vos approbations seront disponibles dès la reconnexion. |
| Swipe hint | ← Glissez pour refuser / approuver → |
7.6 Degradation Banners¶
| Status | Banner Text |
|---|---|
| TRIAL_EXPIRING | 💡 Essai gratuit : {n} jours restants. [Souscrire →] |
| TRIAL_EXPIRED | ⚠️ Votre essai gratuit est terminé. Souscrivez pour continuer. [Souscrire →] |
| PAYMENT_REQUIRED | ⚠️ Paiement requis — Vos données sont en lecture seule. [Régulariser →] |
| ACTIVE_INCOMPLETE_READONLY | ⚠️ Informations manquantes — Complétez votre RCCM pour retrouver l'accès. [Compléter →] |
| SUSPENDED | 🔴 Compte suspendu — Régularisez votre abonnement sous {n} jours. [Régulariser →] |
| Write overlay | Action non disponible. Régularisez votre abonnement pour continuer à utiliser Papillon. [Régulariser →] |
7.7 Sync & Conflicts¶
| Element | Text |
|---|---|
| Sync complete | 🔄 Synchronisation terminée |
| Actions synced | ✓ {n} actions synchronisées |
| Conflict resolved | ⚠ {n} conflit(s) résolu(s) |
| Approval conflict | Approbation congé {employee} — Non appliquée : la demande a été annulée par l'employé. |
| Financial conflict | Opération non appliquée : les données ont été modifiées entre-temps. |
| Manual conflict title | ⚠ Conflit de données |
| Your version | Votre version : |
| Server version | Version serveur : |
| Keep mine | Garder ma version |
| Keep server | Garder la version serveur |
| All synced toast | Tout est synchronisé ✓ |
7.8 Billing¶
| Element | Text |
|---|---|
| Screen title | Abonnement |
| Plan label | Votre plan |
| Status active | ● Actif |
| Status trial | ● Essai gratuit |
| Status overdue | ⚠ Impayé |
| Next payment | Prochain paiement : {date} |
| Billing frequency | Facturation : Mensuelle / Annuelle |
| Annual upsell | 🎁 Passez en annuel : 12 mois payés, 14 mois offerts ! |
| Modules section | Modules actifs |
| Add module CTA | + Ajouter un module |
| Payment section | Moyen de paiement |
| Modify payment | Modifier |
| Invoice section | Historique des factures |
| Invoice status paid | ✓ Payé |
| Invoice status pending | ⏳ En cours |
| Invoice download | 📄 (icon button — downloads PDF receipt) |
7.9 Employee Profile & Export¶
| Element | Text |
|---|---|
| Profile title | Mon profil |
| Export button | 📥 Exporter mes données |
| Export page title | Exporter mes données |
| Export description | Téléchargez une copie de toutes vos données personnelles (droit à la portabilité, Loi n°2013-450). |
| Export content label | Contenu de l'export : |
| Export items | ✓ Mon profil / ✓ Mes bulletins de paie / ✓ Mon historique de congés / ✓ Mes documents joints |
| Export format | Format : ZIP (PDF + CSV) |
| Export CTA | Générer l'export 📥 |
| Export pending | 💡 La génération peut prendre quelques minutes. Vous serez notifié quand le fichier sera prêt. |
| Export ready | ✓ Export prêt ! {filename} · {size} |
| Export download | Télécharger |
7.10 Validation Error Messages¶
| Field | Error |
|---|---|
| Email — empty | L'adresse email est obligatoire. |
| Email — invalid | Cette adresse email n'est pas valide. |
| Email — taken | Cette adresse email est déjà utilisée. |
| Phone — empty | Le numéro de téléphone est obligatoire. |
| Phone — invalid | Ce numéro n'est pas valide. Format : +225 XX XX XX XX XX |
| Password — too short | Le mot de passe doit contenir au moins 8 caractères. |
| Password — no uppercase | Le mot de passe doit contenir au moins une majuscule. |
| Password — no number | Le mot de passe doit contenir au moins un chiffre. |
| Company name — empty | Le nom de l'entreprise est obligatoire. |
| Company name — too short | Le nom doit contenir au moins 2 caractères. |
| Form juridique — empty | La forme juridique est obligatoire. |
| Employee count — empty | Le nombre d'employés est obligatoire. |
| Module selection — none | Sélectionnez au moins un module. |
| Refuse comment — empty | Le motif du refus est obligatoire. |
| Generic server error | Une erreur est survenue. Veuillez réessayer. |
| Network error | Impossible de se connecter au serveur. Vérifiez votre connexion internet. |
| Import — bad format | Format non reconnu. Téléchargez le modèle Excel. |
| Import — duplicate employee | Un employé avec cet email existe déjà. |
8. Component Specs¶
8.1 TenantSwitcher (NEW)¶
Purpose: Displays current tenant in top bar, opens tenant list for switching.
| Prop | Type | Description |
|---|---|---|
currentTenant |
Tenant |
Currently active tenant |
tenants |
Tenant[] |
All tenants the user belongs to |
onSwitch |
(tenantId: string) => void |
Callback on tenant selection |
isMultiTenant |
boolean |
If false, renders as static text (no chevron, no tap) |
Variants:
- Single-tenant: Static company name. No chevron. No interaction.
- Multi-tenant: Company name + ▼ chevron. Tappable. Opens BottomSheet (mobile) or dropdown (desktop).
States: Default, Loading (shimmer text), Error (last known name + retry)
Accessibility: aria-label="Entreprise active : {name}. Appuyez pour changer." role="button" (multi-tenant only). aria-expanded for dropdown state.
Touch target: Full top-bar badge area, minimum 48px tall.
8.2 ModulePreviewCard (NEW)¶
Purpose: Rich preview of a locked/unavailable module with upsell CTA.
| Prop | Type | Description |
|---|---|---|
module |
ModuleInfo |
Module code, name, description, benefits, illustration |
pricing |
ModulePricing |
Segment-aware price for current tenant |
isAvailable |
boolean |
True if module is released and purchasable |
onActivateTrial |
() => void |
Callback for trial activation |
onNotifyMe |
(enabled: boolean) => void |
Callback for notification toggle |
Variants: - Available: Shows pricing + "Essayer gratuitement 14j" CTA. - Coming soon: Shows "Bientôt disponible" + "Me notifier" toggle.
States: Default, Loading (shimmer), Trial activating (button spinner), Trial activated (success check)
Accessibility: aria-label="Module {name}. {description}." CTA: aria-label="Activer l'essai gratuit de {name} pendant 14 jours".
Container: Rendered inside BottomSheet (mobile, via design system) or popover (desktop).
8.3 ApprovalCard (NEW)¶
Purpose: Displays a pending approval with inline actions and swipe support.
| Prop | Type | Description |
|---|---|---|
type |
'leave' \| 'commitment' \| 'expense' |
Approval type — determines badge icon |
title |
string |
E.g., "Congé annuel" or "Fournitures bureau" |
employee |
string |
Employee name (for leave) |
details |
string |
Date range, amount, department, etc. |
timestamp |
string |
Relative time ("il y a 2h") |
attachments |
Attachment[] |
Optional supporting documents |
onApprove |
() => void |
Approve callback |
onRefuse |
(comment: string) => void |
Refuse callback (opens comment modal) |
isOnline |
boolean |
If false, action buttons disabled with overlay |
Type badges: 🏖 (leave), 💰 (commitment), 🧾 (expense)
States: Default, Swiping (reveal action background), Approved (slide out right, green), Refused (slide out left, red), Offline (buttons greyed + overlay)
Accessibility: role="article" aria-label="{type}: {title} de {employee}. {details}." Action buttons: aria-label="Approuver la demande de {employee}" / aria-label="Refuser la demande de {employee}".
Touch target: Full card is tappable for detail view. Approve/Refuse buttons 48px tall, 120px wide min.
8.4 DegradationBanner (NEW)¶
Purpose: Persistent banner shown when tenant is in degraded state.
| Prop | Type | Description |
|---|---|---|
status |
'trial_expiring' \| 'payment_required' \| 'incomplete_readonly' \| 'suspended' |
Tenant status |
daysRemaining |
number |
Days left (for trial/suspended countdown) |
ctaUrl |
string |
Where "Régulariser" navigates to |
onDismiss |
() => void \| undefined |
Only for trial_expiring (dismissable) |
Color mapping:
- trial_expiring → --color-info background
- payment_required → --color-warning background
- incomplete_readonly → --color-warning background
- suspended → --color-error background
States: Visible, Dismissed (trial_expiring only — reappears daily), Removed (payment successful — slide-up-and-fade-out 300ms)
Accessibility: role="alert" aria-live="polite". CTA: role="link".
Position: Fixed at top of content area, below top bar. Pushes content down (not overlay). Height: auto (1-2 lines of text + CTA).
8.5 SyncConflictDialog (NEW)¶
Purpose: Shows sync conflict for manual resolution.
| Prop | Type | Description |
|---|---|---|
entityType |
string |
"Note de frais", "Demande de congé", etc. |
entityLabel |
string |
E.g., "Taxi Plateau" |
localVersion |
ConflictVersion |
User's offline version (value + label) |
serverVersion |
ConflictVersion |
Server version (value + label + who modified) |
onKeepLocal |
() => void |
Keep user's version |
onKeepServer |
() => void |
Keep server version |
States: Open, Resolving (button spinner), Resolved (fade out)
Accessibility: role="alertdialog" aria-label="Conflit de données pour {entityLabel}". Focus trapped inside dialog.
8.6 EmployeeImportCard (NEW)¶
Purpose: Editable employee card for mobile import flow.
| Prop | Type | Description |
|---|---|---|
employee |
ImportEmployee |
Parsed employee data |
errors |
FieldError[] |
Validation errors for this employee |
onEdit |
(field, value) => void |
Field edit callback |
onDelete |
() => void |
Remove from import |
onContactMethodChange |
(method: 'EMAIL' \| 'SMS') => void |
Contact preference |
States: Valid (default), Has errors (red border + error messages), Editing (expanded with editable fields), Deleting (swipe-to-delete with red background)
Accessibility: role="article" aria-label="Employé {name}. {error_count} erreurs." Edit button: aria-label="Modifier les informations de {name}".
Touch target: Full card tappable for edit mode. Contact toggle buttons: 48×32px min.
8.7 OnboardingWizardStep (NEW)¶
Purpose: Container for each wizard step with progress bar and navigation.
| Prop | Type | Description |
|---|---|---|
currentStep |
number |
Current step (1-5) |
totalSteps |
number |
Total steps (5) |
title |
string |
Step title with emoji |
onNext |
() => void |
Continue callback |
onBack |
() => void |
Back navigation |
nextLabel |
string |
CTA text (default: "Continuer →") |
nextDisabled |
boolean |
Disable CTA until validation passes |
children |
ReactNode |
Step content |
Accessibility: Progress bar: role="progressbar" aria-valuenow={currentStep} aria-valuemax={totalSteps} aria-label="Étape {current} sur {total}". Back: aria-label="Retour à l'étape précédente".
8.8 MagicLinkMicroForm (NEW)¶
Purpose: Single-screen form the DG sees when tapping the magic link (no auth required).
| Prop | Type | Description |
|---|---|---|
dgName |
string |
DG's name (from token) |
onboarderName |
string |
Person who sent the link |
companyName |
string |
Tenant company name |
onSubmit |
(status: 'SALARIE' \| 'INDEPENDANT') => void |
Choice callback |
isExpired |
boolean |
If token expired, show "Lien expiré" |
States: Default, Submitted (success screen), Expired ("Ce lien a expiré. Demandez un nouveau lien à {onboarderName}.")
Accessibility: Full page, no login. aria-label="Formulaire de statut du gérant pour {companyName}".
8.9 BillingPlanCard (NEW)¶
Purpose: Summary card showing the tenant's current plan at top of billing page.
| Prop | Type | Description |
|---|---|---|
segment |
string |
"S1", "S2", etc. |
segmentLabel |
string |
"2-12 employés" |
status |
'active' \| 'trial' \| 'overdue' \| 'suspended' |
Plan status |
totalMonthly |
number |
Total monthly amount in FCFA |
nextPaymentDate |
string |
DD/MM/YYYY |
billingFrequency |
'monthly' \| 'annual' |
Current frequency |
onSwitchToAnnual |
() => void |
Upsell callback |
States: Active (green dot), Trial (blue dot + days remaining), Overdue (amber warning), Suspended (red)
Accessibility: role="region" aria-label="Résumé de votre abonnement : plan {segment}, {status}".
9. Motion Choreography¶
9.1 Per-Screen Entrance Animations¶
| Screen | Animation |
|---|---|
| Onboarding step transition | Current step slides out left (200ms). New step slides in from right (200ms). Progress bar fills smoothly (300ms ease-out). |
| Tenant switcher open | Bottom sheet: slide up (300ms ease-out). Dropdown: fade in + scale from 0.95 (150ms). |
| Module preview open | Bottom sheet: slide up (300ms). Items inside stagger: illustration (0ms), title (50ms), benefits (100ms), pricing (150ms), CTA (200ms). |
| Approval inbox load | Cards stagger in: 50ms between each card, slide up 12px + fade in (200ms each). |
| Approval — approved | Card slides right (200ms) with green background reveal. Badge count decrements with bounce (150ms). |
| Approval — refused | Card slides left (200ms) with red background reveal. |
| Employee import parse | Skeleton shimmer on rows → cards pop in with stagger (50ms each, scale from 0.95 + fade, 150ms). |
| Billing page load | Plan card: fade in (0ms). Modules list: stagger 50ms each. Invoices: stagger 30ms each. |
| Degradation banner appear | Slide down from top (300ms ease-out). Content pushes down smoothly. |
| Degradation banner remove | Slide up (200ms). Content slides up to fill space (200ms). |
| Sync conflict dialog | Modal backdrop fade in (200ms). Dialog slides up from bottom (300ms). |
9.2 Celebration Moments¶
| Event | Animation |
|---|---|
| Onboarding complete | Confetti burst (3s) + "Bienvenue sur Papillon ! 🦋" toast. See host-shell-design.md §Q9. |
| Employee import success | Brief confetti burst (1.5s) + success toast: "{n} employés créés !" |
| Trial activated | Check icon scale-bounce (150ms) + nav item color pop (amber glow, 300ms). |
| All approvals cleared | Green checkmark scale-in (150ms) + "Vous êtes à jour !" toast. |
| Payment success (from degraded) | Banner slides up (200ms) + brief green flash on top bar (300ms) + "Abonnement réactivé ✓" toast. |
9.3 Reduced Motion¶
All animations respect prefers-reduced-motion: reduce. When active:
- Slide/scale animations → instant opacity fade (100ms)
- Confetti → disabled
- Stagger → simultaneous appearance
- Progress bar → instant fill (no animation)
- Swipe gestures → still functional but no animated background reveal
10. Brand Compliance Checklist¶
Papillon HR Suite¶
| Criterion | Status | Notes |
|---|---|---|
| Primary color amber/gold | ✅ | All CTAs, active states, progress bars use --color-primary (#F59E0B) |
| Mobile-first 360px | ✅ | Every wireframe designed at 360px first |
| Offline states for all writes | ✅ | Every screen specifies offline behavior. Online-only actions show "Connexion requise" overlay. |
| 48px touch targets | ✅ | All buttons, toggles, cards meet minimum. Specified per component. |
| Warm French copy | ✅ | All UI text in §7. Tone: friendly, never technical. |
| Loading skeletons | ✅ | No bare spinners anywhere. All loading states use skeleton shimmer. |
| Generous whitespace | ✅ | Section spacing uses --space-6 to --space-8. Card padding --space-4. |
| Celebration animations | ✅ | 5 celebration moments defined (onboarding, import, trial, approvals, payment). |
| Warm gradients | ✅ | Onboarding wizard header, plan summary card use subtle warm gradients. |
| Card shadow hierarchy | ✅ | Resting (--shadow-sm), interactive (--shadow-md on hover/press), elevated (--shadow-lg for modals). |
| Dark mode support | ✅ | Deferred to host-shell-design.md §10 token system. All tokens support dark variant. |
| Auto-save on all forms | ✅ | Specified in §4.1. Auto-save on blur/change with green check indicator. |
| French error messages | ✅ | Complete validation message table in §7.10. Never technical jargon. |
| XOF formatting | ✅ | All prices: "15 000 FCFA" (space separator, zero decimals). |
| DD/MM/YYYY dates | ✅ | All dates in wireframes use DD/MM/YYYY format. |
| Phone +225 default | ✅ | Phone prefix pre-filled +225 (CI). |
Enterprise (ALTARYS ENTERPRISE HR Suite)¶
Not applicable for this document. Enterprise frontend design begins at Month 12-13. When it does, this document's patterns (approval inbox, tenant switcher, billing, import) will be re-specified with Enterprise design language (navy, dense, desktop-first, keyboard shortcuts, batch operations).
This design document was produced by the DESIGNER personality after a 9-question UX interview with the Product Owner. Every major design decision (D1–D9) is traceable to an interview response and referenced throughout the document.
All module-level design documents should reference this document for: onboarding flow, tenant switching, module gating UX, approval inbox pattern, degradation banner pattern, sync conflict resolution, and billing/subscription management.