visual-design-foundations

Par wshobson · agents

Appliquer les principes de typographie, de théorie des couleurs, de systèmes d'espacement et d'iconographie pour créer des designs visuels cohérents. À utiliser lors de l'établissement de design tokens, de la création de guides de style, ou de l'amélioration de la hiérarchie visuelle et de la cohérence.

npx skills add https://github.com/wshobson/agents --skill visual-design-foundations

Fondamentaux de la Conception Visuelle

Construisez des systèmes visuels cohérents et accessibles en utilisant les fondamentaux de la typographie, des couleurs, de l'espacement et de l'iconographie.

Quand Utiliser Cette Skill

  • Établir des design tokens pour un nouveau projet
  • Créer ou affiner un système d'espacement et de dimensionnement
  • Sélectionner et associer des polices de caractères
  • Construire des palettes de couleurs accessibles
  • Concevoir des systèmes d'icônes et des ressources visuelles
  • Améliorer la hiérarchie visuelle et la lisibilité
  • Auditer les designs pour la cohérence visuelle
  • Implémenter le mode sombre ou le thème

Systèmes Essentiels

1. Échelle Typographique

Échelle Modulaire (dimensionnement basé sur des ratios) :

:root {
  --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 */
  --font-size-5xl: 3rem; /* 48px */
}

Directives de Hauteur de Ligne : | Type de Texte | Hauteur de Ligne | |-----------|-------------| | Titres | 1,1 - 1,3 | | Texte courant | 1,5 - 1,7 | | Libellés UI | 1,2 - 1,4 |

2. Système d'Espacement

Grille de 8 points (standard de l'industrie) :

:root {
  --space-1: 0.25rem; /* 4px */
  --space-2: 0.5rem; /* 8px */
  --space-3: 0.75rem; /* 12px */
  --space-4: 1rem; /* 16px */
  --space-5: 1.25rem; /* 20px */
  --space-6: 1.5rem; /* 24px */
  --space-8: 2rem; /* 32px */
  --space-10: 2.5rem; /* 40px */
  --space-12: 3rem; /* 48px */
  --space-16: 4rem; /* 64px */
}

3. Système de Couleurs

Tokens de couleurs sémantiques :

:root {
  /* Marque */
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-primary-active: #1e40af;

  /* Sémantique */
  --color-success: #16a34a;
  --color-warning: #ca8a04;
  --color-error: #dc2626;
  --color-info: #0891b2;

  /* Neutral */
  --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;
}

Démarrage Rapide : Design Tokens dans Tailwind

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ["Inter", "system-ui", "sans-serif"],
        mono: ["JetBrains Mono", "monospace"],
      },
      fontSize: {
        xs: ["0.75rem", { lineHeight: "1rem" }],
        sm: ["0.875rem", { lineHeight: "1.25rem" }],
        base: ["1rem", { lineHeight: "1.5rem" }],
        lg: ["1.125rem", { lineHeight: "1.75rem" }],
        xl: ["1.25rem", { lineHeight: "1.75rem" }],
        "2xl": ["1.5rem", { lineHeight: "2rem" }],
      },
      colors: {
        brand: {
          50: "#eff6ff",
          500: "#3b82f6",
          600: "#2563eb",
          700: "#1d4ed8",
        },
      },
      spacing: {
        // Étend les valeurs par défaut avec des valeurs personnalisées
        18: "4.5rem",
        88: "22rem",
      },
    },
  },
};

Bonnes Pratiques Typographiques

Association de Polices

Combinaisons sûres :

  • Titre : Inter / Corps : Inter (famille unique)
  • Titre : Playfair Display / Corps : Source Sans Pro (contraste)
  • Titre : Space Grotesk / Corps : IBM Plex Sans (géométrique)

Typographie Responsive

/* Typographie fluide avec clamp() */
h1 {
  font-size: clamp(2rem, 5vw + 1rem, 3.5rem);
  line-height: 1.1;
}

p {
  font-size: clamp(1rem, 2vw + 0.5rem, 1.125rem);
  line-height: 1.6;
  max-width: 65ch; /* Largeur de lecture optimale */
}

Chargement des Polices

/* Prévenir le décalage de mise en page */
@font-face {
  font-family: "Inter";
  src: url("/fonts/Inter.woff2") format("woff2");
  font-display: swap;
  font-weight: 400 700;
}

Théorie des Couleurs

Exigences de Contraste (WCAG)

Élément Ratio Minimum
Texte courant 4,5:1 (AA)
Texte large (18px+) 3:1 (AA)
Composants UI 3:1 (AA)
Amélioré 7:1 (AAA)

Stratégie de Mode Sombre

:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f9fafb;
  --text-primary: #111827;
  --text-secondary: #6b7280;
  --border: #e5e7eb;
}

[data-theme="dark"] {
  --bg-primary: #111827;
  --bg-secondary: #1f2937;
  --text-primary: #f9fafb;
  --text-secondary: #9ca3af;
  --border: #374151;
}

Accessibilité des Couleurs

// Vérifier le contraste programmatiquement
function getContrastRatio(foreground: string, background: string): number {
  const getLuminance = (hex: string) => {
    const rgb = hexToRgb(hex);
    const [r, g, b] = rgb.map((c) => {
      c = c / 255;
      return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
    });
    return 0.2126 * r + 0.7152 * g + 0.0722 * b;
  };

  const l1 = getLuminance(foreground);
  const l2 = getLuminance(background);
  const lighter = Math.max(l1, l2);
  const darker = Math.min(l1, l2);

  return (lighter + 0.05) / (darker + 0.05);
}

Directives d'Espacement

Espacement des Composants

Padding de carte :      16-24px (--space-4 à --space-6)
Écart de section :       32-64px (--space-8 à --space-16)
Écart de champ de formulaire :    16-24px (--space-4 à --space-6)
Padding de bouton :    8-16px vertical, 16-24px horizontal
Écart icône-texte :     8px (--space-2)

Rythme Visuel

/* Rythme vertical cohérent */
.prose > * + * {
  margin-top: var(--space-4);
}

.prose > h2 + * {
  margin-top: var(--space-2);
}

.prose > * + h2 {
  margin-top: var(--space-8);
}

Iconographie

Système de Dimensionnement des Icônes

:root {
  --icon-xs: 12px;
  --icon-sm: 16px;
  --icon-md: 20px;
  --icon-lg: 24px;
  --icon-xl: 32px;
}

Composant Icône

interface IconProps {
  name: string;
  size?: "xs" | "sm" | "md" | "lg" | "xl";
  className?: string;
}

const sizeMap = {
  xs: 12,
  sm: 16,
  md: 20,
  lg: 24,
  xl: 32,
};

export function Icon({ name, size = "md", className }: IconProps) {
  return (
    <svg
      width={sizeMap[size]}
      height={sizeMap[size]}
      className={cn("inline-block flex-shrink-0", className)}
      aria-hidden="true"
    >
      <use href={`/icons.svg#${name}`} />
    </svg>
  );
}

Bonnes Pratiques

  1. Établir des Contraintes : Limiter les choix pour maintenir la cohérence
  2. Documenter les Décisions : Créer un guide de style vivant
  3. Tester l'Accessibilité : Vérifier le contraste, le dimensionnement, les zones tactiles
  4. Utiliser des Tokens Sémantiques : Nommer par intention, pas par apparence
  5. Concevoir Mobile-First : Commencer par les contraintes, ajouter la complexité
  6. Maintenir un Rythme Vertical : Un espacement cohérent crée l'harmonie
  7. Limiter les Graisses de Police : 2-3 graisses par famille suffisent

Problèmes Courants

  • Espacement Incohérent : Ne pas utiliser une échelle définie
  • Mauvais Contraste : Ne pas respecter les exigences WCAG
  • Surcharge de Polices : Trop de familles ou de graisses
  • Nombres Magiques : Des valeurs arbitraires au lieu de tokens
  • États Manquants : Oublier hover, focus, disabled
  • Pas de Plan Mode Sombre : Rétroadapter est plus difficile que planifier

Skills similaires