Aller au contenu

PD-228 — Plan d'implémentation


📚 Navigation User Story | Document | | | ---------- | -- | | 📋 [Spécification](PD-228-specification.md) | | | 🛠️ **Plan d'implémentation** | *(ce document)* | | ✅ [Critères d'acceptation](PD-228-acceptability.md) | | | 📝 [Retour d'expérience](PD-228-rex.md) | | [← Retour à site-vitrine](../PD-225-epic.md) · [↑ Index User Story](index.md)

1. Découpage en composants

Structure Design System

src/
├── styles/
│   ├── tokens/
│   │   ├── colors.css        # Palette de couleurs
│   │   ├── typography.css    # Polices, tailles
│   │   ├── spacing.css       # Marges, paddings
│   │   ├── borders.css       # Radius, bordures
│   │   └── shadows.css       # Ombres
│   ├── base/
│   │   ├── reset.css         # CSS reset minimal
│   │   └── globals.css       # Styles globaux
│   ├── components/
│   │   ├── buttons.css       # Styles boutons
│   │   ├── cards.css         # Styles cartes
│   │   ├── forms.css         # Styles formulaires
│   │   └── navigation.css    # Styles navigation
│   └── index.css             # Import centralisé
└── components/
    ├── Button.astro
    ├── Card.astro
    └── ...

Composants clés

Composant Responsabilité
tokens/*.css Variables CSS (source de vérité)
base/reset.css Normalisation cross-browser
components/*.css Styles des composants UI
*.astro Composants utilisant les tokens

2. Flux techniques

Chargement CSS

BaseLayout.astro
    └── import '../styles/index.css'
            ├── @import 'tokens/colors.css'
            ├── @import 'tokens/typography.css'
            ├── @import 'tokens/spacing.css'
            ├── @import 'base/reset.css'
            └── @import 'components/*.css'

Utilisation dans composants

---
// Button.astro
interface Props {
  variant?: 'primary' | 'secondary';
  size?: 'sm' | 'md' | 'lg';
}
const { variant = 'primary', size = 'md' } = Astro.props;
---

<button class={`btn btn-${variant} btn-${size}`}>
  <slot />
</button>

3. Mapping invariants → mécanismes

Invariant Mécanisme technique
INV-1 : Couleurs via tokens Variables CSS dans :root
INV-2 : Espacements cohérents Échelle de spacing prédéfinie

Tokens couleurs

/* src/styles/tokens/colors.css */
:root {
  /* Couleurs principales */
  --color-bleu-profond: #0A2342;
  --color-bleu-securite: #185ADB;
  --color-bleu-clair: #E9F1FF;

  /* Texte */
  --color-graphite: #111827;
  --color-gris-neutre: #4B5563;
  --color-gris-clair: #D1D5DB;

  /* Sémantiques */
  --color-success: #10B981;
  --color-warning: #F59E0B;
  --color-error: #EF4444;

  /* Alias */
  --color-text-primary: var(--color-graphite);
  --color-text-secondary: var(--color-gris-neutre);
  --color-background: #FFFFFF;
  --color-surface: var(--color-bleu-clair);
}

Tokens typographie

/* src/styles/tokens/typography.css */
:root {
  /* Familles */
  --font-family-sans: 'Inter', system-ui, sans-serif;
  --font-family-display: 'Space Grotesk', var(--font-family-sans);

  /* Tailles */
  --font-size-xs: 0.75rem;    /* 12px */
  --font-size-sm: 0.875rem;   /* 14px */
  --font-size-base: 1rem;     /* 16px */
  --font-size-lg: 1.125rem;   /* 18px */
  --font-size-xl: 1.25rem;    /* 20px */
  --font-size-2xl: 1.5rem;    /* 24px */
  --font-size-3xl: 1.875rem;  /* 30px */
  --font-size-4xl: 2.25rem;   /* 36px */

  /* Poids */
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;

  /* Line heights */
  --line-height-tight: 1.2;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.6;
}

Tokens spacing

/* src/styles/tokens/spacing.css */
:root {
  --space-xs: 0.5rem;   /* 8px */
  --space-sm: 1rem;     /* 16px */
  --space-md: 1.5rem;   /* 24px */
  --space-lg: 2rem;     /* 32px */
  --space-xl: 3rem;     /* 48px */
  --space-2xl: 4rem;    /* 64px */
  --space-3xl: 6rem;    /* 96px */
}

Composant bouton

/* src/styles/components/buttons.css */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;              /* WCAG touch target */
  padding: var(--space-xs) var(--space-md);
  font-family: var(--font-family-sans);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--radius-md);
  transition: var(--transition-base);
  cursor: pointer;
  border: none;
}

.btn-primary {
  background: var(--color-bleu-securite);
  color: white;
}

.btn-primary:hover {
  background: #1248B5;
}

.btn-secondary {
  background: transparent;
  border: 2px solid var(--color-bleu-securite);
  color: var(--color-bleu-securite);
}

4. Gestion des erreurs

Erreur Cause Mitigation
Token non défini Variable CSS manquante Fallback explicite
Style inline Développeur contourne Lint CSS interdit inline
Couleur hardcodée Hex direct dans code Règle stylelint
Incohérence spacing Valeur arbitraire Règle stylelint

Configuration Stylelint

{
  "extends": ["stylelint-config-standard"],
  "rules": {
    "color-no-hex": true,
    "declaration-property-value-disallowed-list": {
      "margin": ["/^\\d+px$/"],
      "padding": ["/^\\d+px$/"]
    },
    "selector-class-pattern": "^[a-z][a-z0-9-]*$"
  }
}

5. Impacts sécurité

Aspect Mesure
CSS injection Pas de CSS dynamique
@import externe Interdit (lint)
Fonts externes @fontsource local uniquement

6. Hypothèses techniques

Hypothèse Justification
CSS custom properties supportées Navigateurs modernes (>95% support)
Pas de CSS-in-JS Astro préfère CSS natif
Polices Inter + Space Grotesk Charte graphique existante
Pas de préprocesseur CSS natif suffisant

7. Points de vigilance

Point Risque Action
Fallbacks Variable non définie Toujours définir fallback
Dark mode Non prévu initialement Préparer structure tokens
Print styles Oubli impression Ajouter @media print
Responsive Breakpoints incohérents Définir tokens breakpoints
Composants Styles dupliqués Factoriser dans CSS

Fichiers à créer

Fichier Description
src/styles/tokens/colors.css Palette couleurs
src/styles/tokens/typography.css Typographie
src/styles/tokens/spacing.css Espacements
src/styles/tokens/borders.css Bordures, radius
src/styles/tokens/shadows.css Ombres
src/styles/base/reset.css CSS reset
src/styles/components/buttons.css Boutons
src/styles/components/cards.css Cartes
src/styles/index.css Point d'entrée
.stylelintrc.json Configuration lint