Skip to main content

liquid-glass

Implement Liquid Glass design using .glassEffect() API for iOS/macOS 26+. Covers SwiftUI, AppKit, UIKit, and WidgetKit. Use when creating modern glass-based UI effects.

Ir para a instalação

Informações da origem

Repositório
rshankras/claude-code-apple-skills
Última atividade na origem
16 de julho de 2026 às 14:28
Idioma detectado do SKILL.md
inglês
Estrelas
753
Forks
71

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
liquid-glass
description
Implement Liquid Glass design using .glassEffect() API for iOS/macOS 26+. Covers SwiftUI, AppKit, UIKit, and WidgetKit. Use when creating modern glass-based UI effects.
allowed-tools
["Read","Write","Edit","Glob","Grep","AskUserQuestion"]
last_verified
2026-07-16T00:00:00.000Z
review_by
2027-06-22T00:00:00.000Z
os_version
iOS 27 / macOS 27
# Liquid Glass Design Implement Apple's Liquid Glass design language across all Apple UI frameworks. Covers SwiftUI (`.glassEffect()`), AppKit (`NSGlassEffectView`), UIKit (`UIGlassEffect` + `UIVisualEffectView`), and WidgetKit (rendering modes, accented content, glass elements in widgets). ## When This Skill Activates - User wants glass/blur effects on views - User asks about Liquid Glass or modern Apple design - User needs transparent, interactive UI elements - User wants morphing transitions between views - User is implementing glass effects in UIKit with `UIVisualEffectView` - User needs `UIGlassEffect` or `UIGlassContainerEffect` - User asks about scroll view edge effects in UIKit - User wants Liquid Glass in widgets (WidgetKit) - User needs to support accented rendering mode in widgets - User asks about widget textures or mounting styles on visionOS ## Design Rules (WWDC25) Liquid Glass is the material of the **navigation layer** — bars, toolbars, floating controls — never the content layer (tables, lists, rows in a scroll view). | Rule | Detail | |------|--------| | **Never glass on glass** | Don't stack glass. Elements sitting ON glass don't get the material again — style them with fills and vibrancy. | | **Two variants — never mix them** | **Regular** (default): works at any size, over anything, with adaptive legibility. **Clear**: only when ALL three hold — media-rich content underneath, a dimming layer is acceptable, and bold bright content sits above. Clear has no adaptive behaviors. One variant per interface. | | **Tint only primary actions** | "When every element is tinted, nothing stands out." | | **No steady-state intersections** | In resting layouts, content shouldn't sit half-under a glass element — reposition or scale the content instead. | | **Strip decorated bars** | Remove customized bar backgrounds and borders; build hierarchy through layout and grouping, not decoration. Never group a symbol with a text label in one toolbar group. Action sheets spring from their source element. | **Scroll edge effects** keep floating elements separated from scrolling content: soft (gradual fade — the iOS default) vs hard (denser, with a dividing line — mostly macOS). One per view edge, and they're not decorative — don't add one where no floating UI elements exist. **Shape system** — let containers do the math: | Shape | Radius | Use | |-------|--------|-----| | Fixed | Constant | Standalone elements | | Capsule | Half the element height | Phone-scale controls — add extra margin from the screen edge | | Concentric | Parent radius minus padding | Nested containers (inner radii auto-calculate); iPad/Mac elements concentric with the window edge | **Accessibility comes free at the system level**: Reduced Motion decreases lensing and elastic effects; Increased Contrast renders glass elements black/white with a contrasting border. (Lensing is how glass appears — it materializes by modulating how it bends light, and adaptive shadows flip small elements light/dark for legibility over any content.) ## Quick Start (SwiftUI) ### Basic Glass Effect ```swift import SwiftUI Text("Hello, World!") .font(.title) .padding() .glassEffect() // Capsule shape by default ``` ### Custom Shape ```swift Text("Hello") .padding() .glassEffect(in: .rect(cornerRadius: 16)) // Available shapes: // .capsule (default) // .rect(cornerRadius: CGFloat) // .rect(corner: .containerConcentric) — radius derived from the container, keeps nested shapes concentric // .circle ``` ### Interactive Glass ```swift Button("Tap Me") { // action } .padding() .glassEffect(.regular.interactive()) ``` ### Tinted Glass ```swift Text("Important") .padding() .glassEffect(.regular.tint(.blue)) ``` ## Glass Configuration Options | Option | Description | Example | |--------|-------------|---------| | `.regular` | Standard glass effect | `.glassEffect(.regular)` | | `.tint(Color)` | Add color tint | `.glassEffect(.regular.tint(.orange))` | | `.interactive()` | Scale, bounce, and shimmer on touch/hover | `.glassEffect(.regular.interactive())` | ## Multiple Glass Effects ### GlassEffectContainer When using multiple glass elements, wrap them in `GlassEffectContainer` for: - Better rendering performance - Proper blending between effects - Morphing transitions This is correctness, not just performance: glass can not sample other glass, so nearby glass elements must share ONE container to render and blend correctly. ```swift GlassEffectContainer(spacing: 40.0) { HStack(spacing: 40.0) { Image(systemName: "star.fill") .frame(width: 80, height: 80) .font(.system(size: 36)) .glassEffect() Image(systemName: "heart.fill") .frame(width: 80, height: 80) .font(.system(size: 36)) .glassEffect() } } ``` **Spacing Parameter:** - Controls when effects merge - Smaller spacing = views must be closer to merge - Larger spacing = effects merge at greater distances ### Uniting Glass Effects Combine views into a single glass effect using `glassEffectUnion`: ```swift @Namespace private var namespace GlassEffectContainer(spacing: 20.0) { HStack(spacing: 20.0) { ForEach(items.indices, id: \.self) { index in Image(systemName: items[index]) .frame(width: 60, height: 60) .glassEffect() .glassEffectUnion( id: index < 2 ? "group1" : "group2", namespace: namespace ) } } } ``` ## Morphing Transitions Create fluid morphing effects when views appear/disappear. ### Setup 1. Create a namespace 2. Assign glass effect IDs 3. Use animations on state changes ```swift struct MorphingToolbar: View { @State private var isExpanded = false @Namespace private var namespace var body: some View { GlassEffectContainer(spacing: 40.0) { HStack(spacing: 40.0) { // Always visible Image(systemName: "pencil") .frame(width: 60, height: 60) .glassEffect() .glassEffectID("pencil", in: namespace) // Conditionally visible - will morph in/out if isExpanded { Image(systemName: "eraser") .frame(width: 60, height: 60) .glassEffect() .glassEffectID("eraser", in: namespace) Image(systemName: "ruler") .frame(width: 60, height: 60) .glassEffect() .glassEffectID("ruler", in: namespace) } } } Button("Toggle") { withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) { isExpanded.toggle() } } .buttonStyle(.glass) } } ``` ## Button Styles ### Glass Button ```swift Button("Standard") { // action } .buttonStyle(.glass) ``` ### Glass Prominent Button ```swift Button("Primary Action") { // action } .buttonStyle(.glassProminent) ``` ## Advanced Techniques ### Background Extension Extend a hero image beyond the safe area — the system mirrors and blurs it under bars and sidebars: ```swift Image("hero") .backgroundExtensionEffect() ``` Or stretch content under sidebar or inspector: ```swift NavigationSplitView { SidebarView() } detail: { DetailView() .background { Image("wallpaper") .resizable() .ignoresSafeArea() } } ``` ### Horizontal Scroll Under Sidebar ```swift ScrollView(.horizontal) { HStack { ForEach(items) { item in ItemView(item: item) } } } .scrollExtensionMode(.underSidebar) ``` ### Tab Bar Behaviors ```swift TabView { // tabs } .tabBarMinimizeBehavior(.onScrollDown) // Tab bar recedes while scrolling content .tabViewBottomAccessory { // Persistent control docked above the tab bar MiniPlayerView() } ``` ### Toolbar Spacers Split toolbar items into separate glass groups instead of customizing bar backgrounds: ```swift .toolbar { ToolbarItem { editButton } ToolbarSpacer(.fixed) // Visual break — starts a new glass group ToolbarItem { shareButton } ToolbarSpacer(.flexible) // Pushes the following group apart ToolbarItem { doneButton } } ``` ### Scroll Edge Effect Style ```swift ScrollView { content } .scrollEdgeEffectStyle(.hard, for: .top) // Hard style for dense UI, mostly macOS ``` ### Sheets Remove custom `presentationBackground` modifiers — they interfere with the sheet's glass material and its morphing behavior. ## AppKit Implementation ### NSGlassEffectView ```swift import AppKit // Create glass effect view let glassView = NSGlassEffectView(frame: NSRect(x: 20, y: 20, width: 200, height: 100)) glassView.cornerRadius = 16.0 glassView.tintColor = NSColor.systemBlue.withAlphaComponent(0.3) // Create content let label = NSTextField(labelWithString: "Glass Content") label.translatesAutoresizingMaskIntoConstraints = false // Set content view glassView.contentView = label // Add constraints if let contentView = glassView.contentView { NSLayoutConstraint.activate([ label.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) ]) } ``` ### NSGlassEffectContainerView ```swift // Create container let container = NSGlassEffectContainerView(frame: bounds) container.spacing = 40.0 // Create content view let contentView = NSView(frame: container.bounds) container.contentView = contentView // Add glass views to content let glass1 = NSGlassEffectView(frame: NSRect(x: 20, y: 50, width: 150, height: 100)) let glass2 = NSGlassEffectView(frame: NSRect(x: 190, y: 50, width: 150, height: 100)) contentView.addSubview(glass1) contentView.addSubview(glass2) ``` ### Interactive AppKit Glass ```swift class InteractiveGlassView: NSGlassEffectView { override init(frame: NSRect) { super.init(frame: frame) setupTracking() } required init?(coder: NSCoder) { super.init(coder: coder) setupTracking() } private func setupTracking() { let options: NSTrackingArea.Options = [ .mouseEnteredAndExited, .activeInActiveApp ] let trackingArea = NSTrackingArea( rect: bounds, options: options, owner: self, userInfo: nil ) addTrackingArea(trackingArea) } override func mouseEntered(with event: NSEvent) { super.mouseEntered(with: event) NSAnimationContext.runAnimationGroup { context in context.duration = 0.2 animator().tintColor = NSColor.systemBlue.withAlphaComponent(0.2) } } override func mouseExited(with event: NSEvent) { super.mouseExited(with: event) NSAnimationContext.runAnimationGroup { context in context.duration = 0.2 animator().tintColor = nil } } } ``` ## Common Patterns ### Floating Action Bar ```swift struct FloatingActionBar: View { @Namespace private var namespace var body: some View { GlassEffectContainer(spacing: 20) { HStack(spacing: 16) { ForEach(actions) { action in Button { action.perform() } label: { Image(systemName: action.icon) .font(.title2) } .frame(width: 44, height: 44) .glassEffect(.regular.interactive()) .glassEffectID(action.id, in: namespace) } } .padding(.horizontal, 8) .padding(.vertical, 4) } } } ``` ### Card with Glass Effect For a card floating above content (e.g. overlaid on a map). Cards inside a scrolling list are content-layer — don't use glass there. Note the icon uses a fill, not a second `glassEffect`: elements on glass never get glass again. ```swift struct GlassCard: View { let title: String let subtitle: String let icon: String var body: some View { HStack(spacing: 16) { Image(systemName: icon) .font(.title) .frame(width: 50, height: 50) .background(.blue.opacity(0.15), in: .rect(cornerRadius: 12)) VStack(alignment: .leading) { Text(title) .font(.headline) Text(subtitle) .font(.subheadline) .foregroundStyle(.secondary) } Spacer() } .padding() .glassEffect(in: .rect(cornerRadius: 16)) } } ``` ### Tab Bar with Morphing ```swift struct GlassTabBar: View { @Binding var selection: Int @Namespace private var namespace let tabs = [ ("house", "Home"), ("magnifyingglass", "Search"), ("person", "Profile") ] var body: some View { GlassEffectContainer(spacing: 30) { HStack(spacing: 30) { ForEach(tabs.indices, id: \.self) { index in Button { withAnimation(.spring(response: 0.35, dampingFraction: 0.8)) { selection = index } } label: { VStack(spacing: 4) { Image(systemName: tabs[index].0) .font(.title2) Text(tabs[index].1) .font(.caption) } .frame(width: 70, height: 60) } .glassEffect( selection == index ? .regular.tint(.blue).interactive() : .regular.interactive() ) .glassEffectID("tab\(index)", in: namespace) } } } } } ``` ## Migration from Old API
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub