Apple HIG Designer
Concevez de superbes applications iOS natives en suivant les Règles d'Interface Humaine (HIG) d'Apple. Créez des interfaces accessibles et intuitives avec des composants natifs, une typographie appropriée, des couleurs sémantiques et les principes de conception d'Apple.
Ce Que Fait Cette Compétence
Vous aide à concevoir et à créer des applications iOS qui semblent natives et respectent les directives d'Apple :
- Générer des Composants iOS - Créez des composants SwiftUI et UIKit
- Valider les Conceptions - Vérifiez la conformité avec les HIG d'Apple
- Assurer l'Accessibilité - VoiceOver, Dynamic Type, contraste des couleurs
- Appliquer les Principes de Conception - Clarté, Déférence, Profondeur
- Utiliser les Couleurs Sémantiques - Prise en charge automatique du mode sombre
- Implémenter la Typographie - Système de police San Francisco
- Suivre l'Espacement - Grille de 8 points et zones de sécurité
Principes de Conception d'Apple
1. Clarté
Rendez le contenu clair et ciblé.
Le texte est lisible à toutes les tailles, les icônes sont précises et limpides, les ornements sont subtils et appropriés, et l'accent mis sur la fonctionnalité guide la conception.
// ✅ Contenu clair et ciblé
Text("Bon retour, Sarah")
.font(.title)
.foregroundColor(.primary)
// ❌ Flou et encombré
Text("Bon retour, Sarah !!!")
.font(.title)
.foregroundColor(.red)
.background(.yellow)
.overlay(Image(systemName: "star.fill"))
2. Déférence
L'interface aide les utilisateurs à comprendre et interagir avec le contenu, mais ne rivalise jamais avec lui.
L'interface s'efface devant le contenu, utilisant un traitement visuel léger qui garde l'accent sur le contenu et lui donne de l'espace pour respirer.
// ✅ Centré sur le contenu
VStack(alignment: .leading, spacing: 8) {
Text("Titre de l'Article")
.font(.headline)
Text("Le contenu de l'article va ici...")
.font(.body)
.foregroundColor(.secondary)
}
.padding()
// ❌ Interface distrayante
VStack(spacing: 8) {
Text("Titre de l'Article")
.font(.headline)
.foregroundColor(.white)
.background(.blue)
.border(.red, width: 3)
}
3. Profondeur
Des couches visuelles et un mouvement réaliste transmettent la hiérarchie et aident les utilisateurs à comprendre les relations.
Des couches visuelles distinctes et un mouvement réaliste donnent de la vitalité et facilitent la compréhension. Le toucher et la découvrabilité augmentent le plaisir et permettent d'accéder aux fonctionnalités sans perdre le contexte.
// ✅ Hiérarchie de profondeur claire
ZStack {
Color(.systemBackground)
VStack {
// Carte avec élévation
CardView()
.shadow(radius: 8)
}
}
// Utilisation du flou pour la profondeur
Text("Contenu")
.background(.ultraThinMaterial)
Composants d'Interface iOS
Modèles de Navigation
1. Barre de Navigation
Barre supérieure pour la navigation et les actions.
NavigationStack {
List {
Text("Élément 1")
Text("Élément 2")
}
.navigationTitle("Titre")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Ajouter") {
// Action
}
}
}
}
Directives :
- Utilisez les grands titres pour les vues de premier niveau
- Utilisez les titres en ligne pour les vues de détail
- Gardez les actions pertinentes pour le contexte actuel
- Maximum 2-3 éléments de barre d'outils
2. Barre d'Onglets
Navigation inférieure pour les destinations de premier niveau.
TabView {
HomeView()
.tabItem {
Label("Accueil", systemImage: "house")
}
SearchView()
.tabItem {
Label("Recherche", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("Profil", systemImage: "person")
}
}
Directives :
- Maximum 3 à 5 onglets
- Utilisez les SF Symbols pour les icônes
- Les libellés doivent être concis (un mot)
- Ne masquez ni ne désactivez jamais les onglets
- N'utilisez pas la barre d'onglets avec la barre d'outils dans la même vue
3. Liste
Liste déroulante d'éléments.
List {
Section("Aujourd'hui") {
ForEach(items) { item in
NavigationLink {
DetailView(item: item)
} label: {
HStack {
Image(systemName: item.icon)
.foregroundColor(.accentColor)
Text(item.title)
}
}
}
}
}
.listStyle(.insetGrouped)
Styles de Liste :
.plain- Lignes bord à bord.insetGrouped- Sections arrondies et en retrait (défaut iOS).sidebar- Pour les barres latérales de navigation
4. Feuille (Modale)
Présenter le contenu de manière modale.
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Afficher les Détails") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
DetailView()
.presentationDetents([.medium, .large])
}
}
}
Détends de Feuille :
.medium- Demi-écran.large- Plein écran- Hauteurs personnalisées disponibles
Contrôles de Formulaire
1. Bouton
Contrôle d'action principale.
// Bouton rempli (action principale)
Button("Continuer") {
// Action
}
.buttonStyle(.borderedProminent)
// Bouton bordé (action secondaire)
Button("Annuler") {
// Action
}
.buttonStyle(.bordered)
// Bouton simple (action tertiaire)
Button("En Savoir Plus") {
// Action
}
.buttonStyle(.plain)
Hiérarchie des Boutons :
- Prominent - Action principale (un par écran)
- Bordé - Actions secondaires
- Simple - Actions tertiaires, liens
Directives :
- Cible tactile minimale : 44x44 points
- Utilisez des verbes pour les libellés des boutons
- Les actions destructrices doivent nécessiter une confirmation
2. Champ de Texte
Contrôle de saisie de texte.
@State private var username = ""
@State private var password = ""
VStack(alignment: .leading, spacing: 16) {
// Champ de texte standard
TextField("Nom d'utilisateur", text: $username)
.textFieldStyle(.roundedBorder)
.textContentType(.username)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
// Champ sécurisé
SecureField("Mot de passe", text: $password)
.textFieldStyle(.roundedBorder)
.textContentType(.password)
}
Types de Contenu de Texte :
.username- Champ de nom d'utilisateur.password- Champ de mot de passe.emailAddress- Champ d'email.telephoneNumber- Numéro de téléphone.creditCardNumber- Carte de crédit
3. Interrupteur
Contrôle booléen (commutateur).
@State private var isEnabled = false
Toggle("Activer les notifications", isOn: $isEnabled)
.toggleStyle(.switch)
Directives :
- Le libellé décrit ce que l'interrupteur contrôle
- L'effet doit être immédiat
- Utilisez uniquement pour les choix binaires
4. Sélecteur
Contrôle de sélection.
@State private var selectedSize = "Moyen"
let sizes = ["Petit", "Moyen", "Grand"]
// Style de menu
Picker("Taille", selection: $selectedSize) {
ForEach(sizes, id: \.self) { size in
Text(size).tag(size)
}
}
.pickerStyle(.menu)
// Style segmenté (pour 2 à 5 options)
Picker("Taille", selection: $selectedSize) {
ForEach(sizes, id: \.self) { size in
Text(size).tag(size)
}
}
.pickerStyle(.segmented)
Styles de Sélecteur :
.menu- Menu déroulant (défaut).segmented- Contrôle segmenté (2 à 5 options).wheel- Roue déroulante.inline- Liste en ligne (dans les formulaires)
Cartes et Conteneurs
Vue Carte
struct CardView: View {
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Titre")
.font(.headline)
Text("La description va ici avec quelques détails sur le contenu.")
.font(.subheadline)
.foregroundColor(.secondary)
.lineLimit(2)
Spacer()
Button("Action") {
// Action
}
.buttonStyle(.borderedProminent)
}
.padding()
.frame(width: 300, height: 200)
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
}
}
Typographie
Système de Police San Francisco
Police système d'Apple conçue pour une lisibilité optimale.
// Styles de texte Dynamic Type
Text("Grand Titre").font(.largeTitle) // 34pt
Text("Titre").font(.title) // 28pt
Text("Titre 2").font(.title2) // 22pt
Text("Titre 3").font(.title3) // 20pt
Text("Titre").font(.headline) // 17pt semi-gras
Text("Corps").font(.body) // 17pt régulier
Text("Ajout").font(.callout) // 16pt
Text("Sous-titre").font(.subheadline) // 15pt
Text("Note de bas de page").font(.footnote) // 13pt
Text("Légende").font(.caption) // 12pt
Text("Légende 2").font(.caption2) // 11pt
Polices Personnalisées avec Dynamic Type
// Police personnalisée qui s'adapte avec Dynamic Type
Text("Texte personnalisé")
.font(.custom("YourFont-Regular", size: 17, relativeTo: .body))
Graisses de Police
Text("Léger").fontWeight(.light)
Text("Régulier").fontWeight(.regular)
Text("Moyen").fontWeight(.medium)
Text("Semi-gras").fontWeight(.semibold)
Text("Gras").fontWeight(.bold)
Text("Lourd").fontWeight(.heavy)
Directives de Typographie
À faire :
- ✅ Utilisez la police système (San Francisco) pour la cohérence
- ✅ Prenez en charge Dynamic Type pour l'accessibilité
- ✅ Utilisez des styles de texte sémantiques (.headline, .body, etc.)
- ✅ Texte du corps minimum : 17pt
- ✅ Interlignage : 120 à 145 % de la taille de la police
À ne pas faire :
- ❌ N'utilisez pas trop de tailles de police (tenez-vous en aux styles système)
- ❌ Ne rendez pas le texte plus petit que 11pt
- ❌ N'utilisez pas de majuscules pour les textes longs
- ❌ Ne désactivez pas Dynamic Type
Couleurs
Couleurs Sémantiques
Couleurs qui s'adaptent automatiquement au mode clair/foncé.
// Couleurs des éléments d'interface
Color(.label) // Texte principal
Color(.secondaryLabel) // Texte secondaire
Color(.tertiaryLabel) // Texte tertiaire
Color(.quaternaryLabel) // Texte de filigrane
Color(.systemBackground) // Arrière-plan principal
Color(.secondarySystemBackground) // Arrière-plan secondaire
Color(.tertiarySystemBackground) // Arrière-plan tertiaire
Color(.systemFill) // Couleurs de remplissage
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)
Color(.separator) // Lignes de séparation
Color(.opaqueSeparator) // Séparateur non transparent
Couleurs Système
// Couleurs système standard (s'adaptent au mode sombre)
Color(.systemRed)
Color(.systemOrange)
Color(.systemYellow)
Color(.systemGreen)
Color(.systemMint)
Color(.systemTeal)
Color(.systemCyan)
Color(.systemBlue)
Color(.systemIndigo)
Color(.systemPurple)
Color(.systemPink)
Color(.systemBrown)
Color(.systemGray)
Couleurs Personnalisées avec Mode Sombre
// Définir une couleur adaptative
extension Color {
static let customBackground = Color("CustomBackground")
}
// Dans Assets.xcassets, créez un jeu de couleurs avec :
// - Toute Apparence : #FFFFFF
// - Apparence Sombre : #000000
Directives de Contraste des Couleurs
Conformité WCAG AA :
- Texte normal : rapport de contraste minimum de 4,5:1
- Grand texte (24pt+) : rapport de contraste minimum de 3:1
- Composants d'interface : rapport de contraste de 3:1
Couleurs personnalisées :
- Testez avec le Contraste Augmenté activé
- Visez 7:1 pour le texte critique
- Fournissez un contraste suffisant dans les deux modes
Espacement et Disposition
Système de Grille de 8 Points
Tout espacement doit être un multiple de 8.
// Valeurs d'espacement
.padding(8) // 8pt
.padding(16) // 16pt (standard)
.padding(24) // 24pt
.padding(32) // 32pt
.padding(40) // 40pt
.padding(48) // 48pt
// Remplissage spécifique au bord
.padding(.horizontal, 16)
.padding(.vertical, 24)
.padding(.top, 16)
.padding(.bottom, 16)
Zones de Sécurité
Respectez les zones de sécurité de l'appareil.
// Contenu dans la zone de sécurité (par défaut)
VStack {
Text("Contenu")
}
// S'étendre au-delà de la zone de sécurité
VStack {
Color.blue
}
.ignoresSafeArea()
// Étendre uniquement le haut
VStack {
Color.blue
}
.ignoresSafeArea(edges: .top)
Cibles Tactiles
Taille interactive minimale : 44x44 points.
Button("Appuyer") {
// Action
}
.frame(minWidth: 44, minHeight: 44)
Directives d'Espacement
// Espacement des composants
VStack(spacing: 8) { // Espacement serré
Text("Ligne 1")
Text("Ligne 2")
}
VStack(spacing: 16) { // Espacement standard
Text("Section 1")
Text("Section 2")
}
VStack(spacing: 24) { // Espacement lâche
SectionView()
SectionView()
}
Accessibilité
Prise en Charge de VoiceOver
Lecteur d'écran pour les utilisateurs aveugles et malvoyants.
// Étiquette accessible
Image(systemName: "heart.fill")
.accessibilityLabel("Favori")
// Valeur accessible
Slider(value: $volume)
.accessibilityLabel("Volume")
.accessibilityValue("\(Int(volume * 100))%")
// Indice accessible
Button("Partager") {
share()
}
.accessibilityHint("Partage cet élément avec d'autres")
// Regrouper les éléments
HStack {
Image(systemName: "person")
Text("Jean Dupont")
}
.accessibilityElement(children: .combine)
// Masqué pour VoiceOver
Image("decorative")
.accessibilityHidden(true)
Dynamic Type
Prend en charge la taille de texte préférée de l'utilisateur.
// Prise en charge automatique avec les polices système
Text("Ce texte se redimensionne")
.font(.body)
// Limiter la mise à l'échelle (si nécessaire)
Text("Ce texte a des limites")
.font(.body)
.dynamicTypeSize(...DynamicTypeSize.xxxLarge)
// Police personnalisée avec Dynamic Type
Text("Police personnalisée")
.font(.custom("YourFont", size: 17, relativeTo: .body))
Daltonisme
Concevez pour les utilisateurs daltoniens.
// Ne vous fiez pas uniquement à la couleur
HStack {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
Text("Succès")
}
// Pas seulement la couleur
Circle()
.fill(.green)
// ❌ Couleur uniquement
// Mieux avec forme/icône
HStack {
Image(systemName: "checkmark.circle.fill")
Circle().fill(.green)
}
// ✅ Couleur + forme
Réduire le Mouvement
Respectez les préférences de mouvement de l'utilisateur.
@Environment(\.accessibilityReduceMotion) var reduceMotion
var animation: Animation {
reduceMotion ? .none : .spring()
}
Button("Animer") {
withAnimation(animation) {
// Animer
}
}
Contraste Augmenté
Prend en charge le mode de contraste élevé.
@Environment(\.accessibilityContrast) var contrast
VStack {
Text("Texte")
.foregroundColor(contrast == .high ? .primary : .secondary)
}
Validation et Conformité
Liste de Vérification HIG
Validez votre conception par rapport aux directives essentielles :
- Les cibles tactiles font au moins 44x44 points
- Le texte du corps est à 17pt minimum
- L'espacement suit la grille de 8 points
- Les couleurs sémantiques sont utilisées
- Dynamic Type est pris en charge
- VoiceOver est implémenté
- Les contrastes respectent WCAG AA
- Les zones de sécurité sont respectées
- Les animations respectent Réduire le Mouvement
- Les polices système sont utilisées sauf indication contraire
Règle du Bouton Unique
Un bouton visuellement prominent par écran.
// ✅ Correct : une action principale par vue
VStack(spacing: 16) {
Button("Continuer") { }
.buttonStyle(.borderedProminent)
Button("Plus tard") { }
.buttonStyle(.bordered)
}
Validation du Contraste des Couleurs
// Fonction utilitaire de base pour vérifier le contraste
func calculateContrastRatio(color1: UIColor, color2: UIColor) -> CGFloat {
// Implémentez le calcul du rapport de contraste
// Utilisez la formule WCAG 2.1
return ratio
}
Ressources
Documentation Officielle
- Règles d'Interface Humaine d'Apple - iOS
- Design de l'Accessibilité
- Conseils de Conception d'Applications
Ressources de Conception
Exemple : Application Complète
Structure de Base
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
TabView {
HomeView()
.tabItem {
Label("Accueil", systemImage: "house")
}
SettingsView()
.tabItem {
Label("Paramètres", systemImage: "gear")
}
}
}
}
Conçu avec ❤️ en suivant les directives de conception d'Apple.