liquid-glass-design
affaan-m/ECC
Mettre en œuvre le système de conception « Liquid Glass » d'Apple pour iOS 26 et versions ultérieures, avec des matériaux en verre dynamiques, des effets de flou, des reflets et des transitions interactives dans SwiftUI, UIKit et WidgetKit.
...Développer toutSystème de conception « Liquid Glass » (iOS 26)
Modèles permettant de mettre en œuvre le Liquid Glass d’Apple — un matériau dynamique qui rend flou le contenu situé derrière lui, reflète les couleurs et la lumière du contenu environnant, et réagit aux interactions tactiles et au pointeur. Couvre l’intégration avec SwiftUI, UIKit et WidgetKit.
Quand l’activer
- Lors de la création ou de la mise à jour d’applications pour iOS 26 et versions ultérieures avec le nouveau langage de conception
- Mise en œuvre de boutons, cartes, barres d’outils ou conteneurs de style « verre »
- Création de transitions fluides entre des éléments en verre
- Application d’effets Liquid Glass aux widgets
- Migration des effets de flou/matériaux existants vers la nouvelle API Liquid Glass
Modèle de base — SwiftUI
Effet « verre » de base
La manière la plus simple d’ajouter Liquid Glass à n’importe quelle vue :
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect() // Par défaut : variante standard, forme en capsule
Personnalisation de la forme et de la teinte
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))
Principales options de personnalisation :
.regular— effet de verre standard.tint(Couleur)— ajoute une teinte de couleur pour plus de visibilité.interactive()— réagit aux interactions tactiles et au pointeur- Forme :
.capsule(par défaut),.rect(cornerRadius:),.circle
Styles de boutons « verre »
Button("Cliquez ici") { /* action */ }
.buttonStyle(.glass)
Button("Important") { /* action */ }
.buttonStyle(.glassProminent)
GlassEffectContainer pour plusieurs éléments
Enveloppez toujours plusieurs vues « verre » dans un conteneur pour des raisons de performances et de morphing :
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 40.0) {
Image(systemName: "scribble.variable")
.frame(width: 80.0, height: 80.0)
.font(.system(size: 36))
.glassEffect()
Image(systemName: "eraser.fill")
.frame(width: 80.0, height: 80.0)
.font(.system(size: 36))
.glassEffect()
}
}
Le paramètre « spacing » contrôle la distance de fusion : plus les éléments sont proches, plus leurs formes de verre se fondent les unes dans les autres.
Fusionner des effets de verre
Combinez plusieurs vues en une seule forme de verre à l’aide de ` glassEffectUnion` :
@Namespace private var namespace
GlassEffectContainer(spacing: 20.0) {
HStack(spacing: 20.0) {
ForEach(symbolSet.indices, id: \.self) { item in
Image(systemName: symbolSet[item])
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectUnion(id: item < 2 ? "group1" : "group2", namespace: namespace)
}
}
}
Transitions de morphing
Créer un morphing fluide lorsque les éléments en verre apparaissent ou disparaissent :
@State private var isExpanded = false
@Namespace private var namespace
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 40.0) {
Image(systemName: "scribble.variable")
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectID("pencil", in: namespace)
if isExpanded {
Image(systemName: "eraser.fill")
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectID("eraser", in: namespace)
}
}
}
Button("Toggle") {
withAnimation { isExpanded.toggle() }
}
.buttonStyle(.glass)
Extension du défilement horizontal sous la barre latérale
Pour permettre au contenu défilant horizontalement de s’étendre sous une barre latérale ou un inspecteur, assurez-vous que le contenu de la `ScrollView` atteigne les bords avant et arrière du conteneur. Le système gère automatiquement le comportement de défilement sous la barre latérale lorsque la mise en page s’étend jusqu’aux bords — aucun modificateur supplémentaire n’est nécessaire.
Modèle de base — UIKit
UIGlassEffect de base
let glassEffect = UIGlassEffect()
glassEffect.tintColor = UIColor.systemBlue.withAlphaComponent(0.3)
glassEffect.isInteractive = true
let visualEffectView = UIVisualEffectView(effect: glassEffect)
visualEffectView.translatesAutoresizingMaskIntoConstraints = false
visualEffectView.layer.cornerRadius = 20
visualEffectView.clipsToBounds = true
view.addSubview(visualEffectView)
NSLayoutConstraint.activate([
visualEffectView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
visualEffectView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
visualEffectView.widthAnchor.constraint(equalToConstant: 200),
visualEffectView.heightAnchor.constraint(equalToConstant: 120)
])
// Ajouter du contenu à contentView
let label = UILabel()
label.text = "Liquid Glass"
label.translatesAutoresizingMaskIntoConstraints = false
visualEffectView.contentView.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: visualEffectView.contentView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: visualEffectView.contentView.centerYAnchor)
])
UIGlassContainerEffect pour plusieurs éléments
let containerEffect = UIGlassContainerEffect()
containerEffect.spacing = 40.0
let containerView = UIVisualEffectView(effect: containerEffect)
let firstGlass = UIVisualEffectView(effect: UIGlassEffect())
let secondGlass = UIVisualEffectView(effect: UIGlassEffect())
containerView.contentView.addSubview(firstGlass)
containerView.contentView.addSubview(secondGlass)
Effets de défilement sur les bords
scrollView.topEdgeEffect.style = .automatic
scrollView.bottomEdgeEffect.style = .hard
scrollView.leftEdgeEffect.isHidden = true
Intégration de l’effet « verre » dans la barre d’outils
let favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction))
favoriteButton.hidesSharedBackground = true // Désactiver l'arrière-plan Glass partagé
Modèle de base — WidgetKit
Détection du mode de rendu
struct MyWidgetView: View {
@Environment(\.widgetRenderingMode) var renderingMode
var body: some View {
if renderingMode == .accented {
// Mode teinté : arrière-plan en verre teinté de blanc, adapté au thème
} else {
// Mode couleur : apparence standard
}
}
}
Groupes d’accentuation pour la hiérarchie visuelle
HStack {
VStack(alignment: .leading) {
Text("Titre")
.widgetAccentable() // Groupe d'accentuation
Text("Sous-titre")
// Groupe principal (par défaut)
}
Image(systemName: "star.fill")
.widgetAccentable() // Groupe d'accentuation
}
Rendu d’une image en mode accentué
Image("myImage")
.widgetAccentedRenderingMode(.monochrome)
Arrière-plan du conteneur
VStack { /* contenu */ }
.containerBackground(for: .widget) {
Color.blue.opacity(0.2)
}
Principales décisions de conception
| Décision | Justification |
|---|---|
| Enveloppement par GlassEffectContainer | Optimisation des performances, permet la transition entre les éléments en verre |
Paramètred’espacement |
Contrôle la distance de fusion — permet d’ajuster avec précision la proximité nécessaire entre les éléments pour qu’ils se fondent |
@Namespace + glassEffectID |
Permet des transitions fluides lors des changements de hiérarchie de vue |
Modificateurinteractive() |
Activation explicite des réactions au toucher ou au pointeur — tous les éléments « glass » ne doivent pas nécessairement réagir |
| UIGlassContainerEffect dans UIKit | Même modèle de conteneur que SwiftUI pour plus de cohérence |
| Mode de rendu accentué dans les widgets | Le système applique un effet de verre teinté lorsque l’utilisateur sélectionne un écran d’accueil teinté |
Bonnes pratiques
- Utilisez toujours GlassEffectContainer lorsque vous appliquez un effet de verre à plusieurs vues sœurs : cela permet le morphing et améliore les performances de rendu
- Appliquez
.glassEffect()après les autres modificateurs d’apparence (cadre, police, espacement) - N’utilisez
.interactive()que sur les éléments qui réagissent aux interactions de l’utilisateur (boutons, éléments à bascule) - Choisissez soigneusement l’espacement dans les conteneurs pour contrôler le moment où les effets de verre se fondent
- Utilisez
withAnimationlorsque vous modifiez les hiérarchies de vues afin de permettre des transitions de morphing fluides - Testez les différents modes d’apparence: mode clair, mode sombre et modes accentués/teintés
- Assurez-vous du contraste d’accessibilité: le texte sur le verre doit rester lisible
Anti-modèles à éviter
- Utilisation de plusieurs vues
.glassEffect()indépendantes sans GlassEffectContainer - Imbrication d’un trop grand nombre d’effets de verre — cela nuit aux performances et à la clarté visuelle
- Appliquer l’effet « verre » à toutes les vues — le réserver aux éléments interactifs, aux barres d’outils et aux cartes
- Oublier de définir
clipsToBounds = truedans UIKit lors de l’utilisation de rayons de coin - Ignorer le mode de rendu accentué dans les widgets — cela perturbe l’apparence teintée de l’écran d’accueil
- Utiliser des arrière-plans opaques derrière l’effet « verre » — annule l’effet de translucidité
Quand les utiliser
- Barres de navigation, barres d’outils et barres d’onglets avec le nouveau design d’iOS 26
- Boutons d’action flottants et conteneurs de type « carte »
- Commandes interactives nécessitant une profondeur visuelle et un retour tactile
- Widgets devant s’intégrer à l’apparence « Liquid Glass » du système
- Transitions fluides entre les états connexes de l’interface utilisateur
---
name: liquid-glass-design
description: Implement Apple's Liquid Glass design system for iOS 26+ with dynamic glass materials, blur, reflection, and interactive morphing in SwiftUI, UIKit, and WidgetKit.
---
# Liquid Glass Design System (iOS 26)
Patterns for implementing Apple's Liquid Glass — a dynamic material that blurs content behind it, reflects color and light from surrounding content, and reacts to touch and pointer interactions. Covers SwiftUI, UIKit, and WidgetKit integration.
## When to Activate
- Building or updating apps for iOS 26+ with the new design language
- Implementing glass-style buttons, cards, toolbars, or containers
- Creating morphing transitions between glass elements
- Applying Liquid Glass effects to widgets
- Migrating existing blur/material effects to the new Liquid Glass API
## Core Pattern — SwiftUI
### Basic Glass Effect
The simplest way to add Liquid Glass to any view:
```swift
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect() // Default: regular variant, capsule shape
```
### Customizing Shape and Tint
```swift
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))
```
Key customization options:
- `.regular` — standard glass effect
- `.tint(Color)` — add color tint for prominence
- `.interactive()` — react to touch and pointer interactions
- Shape: `.capsule` (default), `.rect(cornerRadius:)`, `.circle`
### Glass Button Styles
```swift
Button("Click Me") { /* action */ }
.buttonStyle(.glass)
Button("Important") { /* action */ }
.buttonStyle(.glassProminent)
```
### GlassEffectContainer for Multiple Elements
Always wrap multiple glass views in a container for performance and morphing:
```swift
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 40.0) {
Image(systemName: "scribble.variable")
.frame(width: 80.0, height: 80.0)
.font(.system(size: 36))
.glassEffect()
Image(systemName: "eraser.fill")
.frame(width: 80.0, height: 80.0)
.font(.system(size: 36))
.glassEffect()
}
}
```
The `spacing` parameter controls merge distance — closer elements blend their glass shapes together.
### Uniting Glass Effects
Combine multiple views into a single glass shape with `glassEffectUnion`:
```swift
@Namespace private var namespace
GlassEffectContainer(spacing: 20.0) {
HStack(spacing: 20.0) {
ForEach(symbolSet.indices, id: \.self) { item in
Image(systemName: symbolSet[item])
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectUnion(id: item < 2 ? "group1" : "group2", namespace: namespace)
}
}
}
```
### Morphing Transitions
Create smooth morphing when glass elements appear/disappear:
```swift
@State private var isExpanded = false
@Namespace private var namespace
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 40.0) {
Image(systemName: "scribble.variable")
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectID("pencil", in: namespace)
if isExpanded {
Image(systemName: "eraser.fill")
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectID("eraser", in: namespace)
}
}
}
Button("Toggle") {
withAnimation { isExpanded.toggle() }
}
.buttonStyle(.glass)
```
### Extending Horizontal Scrolling Under Sidebar
To allow horizontal scroll content to extend under a sidebar or inspector, ensure the `ScrollView` content reaches the leading/trailing edges of the container. The system automatically handles the under-sidebar scrolling behavior when the layout extends to the edges — no additional modifier is needed.
## Core Pattern — UIKit
### Basic UIGlassEffect
```swift
let glassEffect = UIGlassEffect()
glassEffect.tintColor = UIColor.systemBlue.withAlphaComponent(0.3)
glassEffect.isInteractive = true
let visualEffectView = UIVisualEffectView(effect: glassEffect)
visualEffectView.translatesAutoresizingMaskIntoConstraints = false
visualEffectView.layer.cornerRadius = 20
visualEffectView.clipsToBounds = true
view.addSubview(visualEffectView)
NSLayoutConstraint.activate([
visualEffectView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
visualEffectView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
visualEffectView.widthAnchor.constraint(equalToConstant: 200),
visualEffectView.heightAnchor.constraint(equalToConstant: 120)
])
// Add content to contentView
let label = UILabel()
label.text = "Liquid Glass"
label.translatesAutoresizingMaskIntoConstraints = false
visualEffectView.contentView.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: visualEffectView.contentView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: visualEffectView.contentView.centerYAnchor)
])
```
### UIGlassContainerEffect for Multiple Elements
```swift
let containerEffect = UIGlassContainerEffect()
containerEffect.spacing = 40.0
let containerView = UIVisualEffectView(effect: containerEffect)
let firstGlass = UIVisualEffectView(effect: UIGlassEffect())
let secondGlass = UIVisualEffectView(effect: UIGlassEffect())
containerView.contentView.addSubview(firstGlass)
containerView.contentView.addSubview(secondGlass)
```
### Scroll Edge Effects
```swift
scrollView.topEdgeEffect.style = .automatic
scrollView.bottomEdgeEffect.style = .hard
scrollView.leftEdgeEffect.isHidden = true
```
### Toolbar Glass Integration
```swift
let favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction))
favoriteButton.hidesSharedBackground = true // Opt out of shared glass background
```
## Core Pattern — WidgetKit
### Rendering Mode Detection
```swift
struct MyWidgetView: View {
@Environment(\.widgetRenderingMode) var renderingMode
var body: some View {
if renderingMode == .accented {
// Tinted mode: white-tinted, themed glass background
} else {
// Full color mode: standard appearance
}
}
}
```
### Accent Groups for Visual Hierarchy
```swift
HStack {
VStack(alignment: .leading) {
Text("Title")
.widgetAccentable() // Accent group
Text("Subtitle")
// Primary group (default)
}
Image(systemName: "star.fill")
.widgetAccentable() // Accent group
}
```
### Image Rendering in Accented Mode
```swift
Image("myImage")
.widgetAccentedRenderingMode(.monochrome)
```
### Container Background
```swift
VStack { /* content */ }
.containerBackground(for: .widget) {
Color.blue.opacity(0.2)
}
```
## Key Design Decisions
| Decision | Rationale |
|----------|-----------|
| GlassEffectContainer wrapping | Performance optimization, enables morphing between glass elements |
| `spacing` parameter | Controls merge distance — fine-tune how close elements must be to blend |
| `@Namespace` + `glassEffectID` | Enables smooth morphing transitions on view hierarchy changes |
| `interactive()` modifier | Explicit opt-in for touch/pointer reactions — not all glass should respond |
| UIGlassContainerEffect in UIKit | Same container pattern as SwiftUI for consistency |
| Accented rendering mode in widgets | System applies tinted glass when user selects tinted Home Screen |
## Best Practices
- **Always use GlassEffectContainer** when applying glass to multiple sibling views — it enables morphing and improves rendering performance
- **Apply `.glassEffect()` after** other appearance modifiers (frame, font, padding)
- **Use `.interactive()`** only on elements that respond to user interaction (buttons, toggleable items)
- **Choose spacing carefully** in containers to control when glass effects merge
- **Use `withAnimation`** when changing view hierarchies to enable smooth morphing transitions
- **Test across appearances** — light mode, dark mode, and accented/tinted modes
- **Ensure accessibility contrast** — text on glass must remain readable
## Anti-Patterns to Avoid
- Using multiple standalone `.glassEffect()` views without a GlassEffectContainer
- Nesting too many glass effects — degrades performance and visual clarity
- Applying glass to every view — reserve for interactive elements, toolbars, and cards
- Forgetting `clipsToBounds = true` in UIKit when using corner radii
- Ignoring accented rendering mode in widgets — breaks tinted Home Screen appearance
- Using opaque backgrounds behind glass — defeats the translucency effect
## When to Use
- Navigation bars, toolbars, and tab bars with the new iOS 26 design
- Floating action buttons and card-style containers
- Interactive controls that need visual depth and touch feedback
- Widgets that should integrate with the system's Liquid Glass appearance
- Morphing transitions between related UI states
Tous les fichiers
1 fichiersInstaller liquid-glass-design
Téléchargez et décompressez les fichiers de compétences dans votre répertoire .claude/skills/.
Télécharger le ZIPClonez le dépôt et copiez les fichiers de compétence dans votre projet.
git clone https://github.com/affaan-m/ECC/tree/main/skills/liquid-glass-design # Copy SKILL.md to your .claude/skills/ directory
Copier





Maison
