
Liquid Glass
- 297 installs
- 11 repo stars
- Updated August 4, 2026
- casper-studios/casper-marketplace
liquid-glass is a mobile development agent skill that implements Apple's Liquid Glass design language and Human Interface Guidelines in SwiftUI for developers building native iOS 26+ and macOS Tahoe interfaces.
About
Guides building native macOS/iOS SwiftUI interfaces with Apple's Liquid Glass design, translucent materials, SF Symbols, and HIG spacing and typography. A developer uses it to produce interfaces that feel native to Apple platforms.
- Three-layer model restricting glass to navigation/control layers
- Follows Apple HIG for spacing, typography, color, and SF Symbols
Liquid Glass by the numbers
- 297 all-time installs (skills.sh)
- Ranked #836 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/casper-studios/casper-marketplace --skill liquid-glassAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 297 |
|---|---|
| repo stars | ★ 11 |
| Last updated | August 4, 2026 |
| Repository | casper-studios/casper-marketplace ↗ |
How do you implement Liquid Glass in SwiftUI?
Builds native macOS and iOS apps using Apple's Liquid Glass design language and Human Interface Guidelines in SwiftUI.
Who is it for?
iOS and macOS developers targeting iOS 26+ or macOS Tahoe who want SwiftUI code that follows Apple's Liquid Glass navigation-layer rules and HIG spacing.
Skip if: Web or React frontends, Android Compose UIs, or teams not shipping native SwiftUI apps on current Apple platform releases.
When should I use this skill?
The user builds SwiftUI macOS or iOS apps, asks for Liquid Glass effects, glassEffect modifiers, or Apple HIG-native navigation UI.
What you get
SwiftUI views with glassEffect modifiers, GlassEffectContainer layouts, HIG-compliant spacing, and native glass button styles.
- SwiftUI glassEffect view code
- GlassEffectContainer layouts
- HIG-compliant navigation UI
By the numbers
- Targets Liquid Glass API on iOS 26+ and macOS Tahoe
- Documents 3 glassEffect variants: .regular, .clear, and .identity
Files
Liquid Glass Design
Build native macOS/iOS applications with Apple's Liquid Glass design and HIG.
Core Rules
Three-Layer Model
┌─────────────────────────────────────────┐
│ GLASS LAYER (Navigation/Controls) │ ← Glass here ONLY
├─────────────────────────────────────────┤
│ CONTENT LAYER (Your App) │ ← Never glass here
└─────────────────────────────────────────┘Glass is ONLY for navigation floating above content. Never on content itself.
Five Principles
1. Content First - Glass floats above, content shines through 2. Depth Through Light - Lensing creates hierarchy, not opacity 3. Adaptive Tinting - Colors respond to background dynamically 4. Semantic Emphasis - Tint primary actions only 5. Accessibility Built-In - System handles adaptations automatically
Materials (macOS 14+ / Pre-iOS 26)
// Card with material
.padding(24)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
// Material options (lightest → heaviest):
// .ultraThinMaterial, .thinMaterial, .regularMaterial (default), .thickMaterial, .ultraThickMaterialLiquid Glass API (iOS 26+ / macOS Tahoe)
// Basic
Button("Action") { }.glassEffect()
// Variants
.glassEffect(.regular) // Standard UI
.glassEffect(.clear) // Media backgrounds only
.glassEffect(.identity) // Disabled
// Interactive (adds bounce/shimmer)
Button("Tap") { }.glassEffect(.regular.interactive())
// Multiple glass elements - MUST wrap in container
GlassEffectContainer(spacing: 30) {
HStack {
Button("A") { }.glassEffect()
Button("B") { }.glassEffect()
}
}
// Button styles
Button("Cancel") { }.buttonStyle(.glass) // Secondary
Button("Save") { }.buttonStyle(.glassProminent).tint(.blue) // PrimaryEssential Patterns
Card
VStack(alignment: .leading, spacing: 12) {
HStack {
ZStack {
Circle().fill(color.opacity(0.15)).frame(width: 36, height: 36)
Image(systemName: icon).foregroundStyle(color)
}
Spacer()
}
Text(value).font(.system(size: 28, weight: .bold, design: .rounded))
Text(label).font(.caption).foregroundStyle(.secondary)
}
.padding(20)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))Row with Hover
HStack { content }
.padding(16)
.background(isHovering ? Color.primary.opacity(0.04) : .clear)
.background(.quaternary.opacity(0.5), in: RoundedRectangle(cornerRadius: 12, style: .continuous))
.onHover { withAnimation(.easeInOut(duration: 0.15)) { isHovering = $0 } }Badge
HStack(spacing: 8) {
Circle().fill(isActive ? .green : .orange).frame(width: 8, height: 8)
Text(status).font(.caption).fontWeight(.medium)
}
.padding(.horizontal, 12).padding(.vertical, 8)
.background(.regularMaterial, in: Capsule())Icon with Tinted Background
ZStack {
Circle().fill(color.opacity(0.15)).frame(width: 32, height: 32)
Image(systemName: icon).font(.system(size: 14, weight: .semibold)).foregroundStyle(color)
}Shapes
// Always use .continuous
RoundedRectangle(cornerRadius: 16, style: .continuous) // Cards
RoundedRectangle(cornerRadius: 12, style: .continuous) // Rows
RoundedRectangle(cornerRadius: 8, style: .continuous) // Small elements
Capsule() // Pills, badges
Circle() // IconsColors
// Semantic foreground
.foregroundStyle(.primary) // Main content
.foregroundStyle(.secondary) // Subtitles
.foregroundStyle(.tertiary) // Timestamps
// Backgrounds
.background(.quaternary)
.background(.quaternary.opacity(0.5))
// Accent meanings
Color.blue // Primary actions, selection
Color.green // Success, active
Color.orange // Warning, loading
Color.red // Destructive, error
Color.purple // Premium, AI
Color.cyan // Security
// Tinted backgrounds: always 15% opacity
.fill(color.opacity(0.15))Typography
.font(.largeTitle).fontWeight(.bold) // Page titles
.font(.headline).fontWeight(.semibold) // Section headers
.font(.subheadline).fontWeight(.medium) // Row titles
.font(.body) // Content (17pt default)
.font(.caption) // Metadata
.font(.caption2) // Timestamps
.font(.system(size: 28, weight: .bold, design: .rounded)) // StatsRules: Min 11pt. Avoid Ultralight/Thin/Light. Use system fonts for Dynamic Type.
Spacing (8pt Grid)
// Standard values: 4, 8, 12, 16, 20, 24, 32, 40, 48
.padding(24) // Cards
.padding(16) // Rows
.padding(.horizontal, 12).padding(.vertical, 8) // Badges
// Rule: external spacing ≥ internal spacing
VStack(spacing: 24) { CardView().padding(20) } // CorrectSF Symbols
// Preferred: hierarchical for depth
Image(systemName: icon).symbolRenderingMode(.hierarchical).foregroundStyle(color)
// Match weight to nearby text
Image(systemName: "gear").font(.system(size: 14, weight: .semibold))Hit Targets
// MINIMUM: 44pt × 44pt
Button { } label: { Image(systemName: "gear") }
.frame(minWidth: 44, minHeight: 44)Animations
// Hover
.onHover { withAnimation(.easeInOut(duration: 0.15)) { isHovering = $0 } }
// Spring
withAnimation(.spring(response: 0.3)) { }
withAnimation(.bouncy) { }
// Entry
.opacity(appeared ? 1 : 0).offset(y: appeared ? 0 : 10)
.onAppear { withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { appeared = true } }Do's and Don'ts
DO:
- Use
.regularMaterialfor cards/toolbars - Use
.continuouson ALL rounded rectangles - Use 15% opacity for icon backgrounds
- Wrap multiple glass in
GlassEffectContainer - Use 44pt minimum hit targets
- Use 8pt grid spacing
- Use SF Symbols with
.hierarchical
DON'T:
- Apply glass to content (lists, tables)
- Stack glass on glass without container
- Use sharp corners
- Go below 11pt text
- Create touch targets < 44pt
- Use full-color images on glass
Accessibility
System handles automatically:
- Reduce Transparency → opaquer glass
- Increase Contrast → visible borders
- Reduce Motion → no bouncy effects
- Dynamic Type → text scales
Manual override if needed:
@Environment(\.accessibilityReduceTransparency) var reduceTransparency
.glassEffect(reduceTransparency ? .identity : .regular)References
For detailed patterns and examples, see:
- references/components.md - Full component implementations
- references/apple-hig.md - Complete Apple HIG guidelines
Apple Human Interface Guidelines Reference
Complete HIG guidelines for Liquid Glass design.
Table of Contents
---
Core Principles
Apple HIG establishes four pillars:
Clarity
- Interfaces must be legible, precise, easy to understand
- Every element has a purpose
- Users know what to do without instructions
Deference
- UI helps users focus on content
- Minimize visual clutter
- Controls don't distract from content
Depth
- Visual layers convey hierarchy
- Shadows, blur, translucency show relationships
- Spatial metaphors aid understanding
Consistency
- Standard UI elements feel familiar
- System components adapt to Dark Mode, Dynamic Type
- Leverage proven interaction patterns
---
Typography
San Francisco is the system font optimized for Apple platforms.
Font Hierarchy
| Style | Usage | SwiftUI |
|---|---|---|
| Large Title | Page titles | .font(.largeTitle).fontWeight(.bold) |
| Headline | Section headers | .font(.headline).fontWeight(.semibold) |
| Subheadline | Row/card titles | .font(.subheadline).fontWeight(.medium) |
| Body | Content (17pt) | .font(.body) |
| Callout | Secondary content | .font(.callout) |
| Caption | Metadata | .font(.caption) |
| Caption 2 | Timestamps | .font(.caption2) |
Stats/Numbers
.font(.system(size: 28, weight: .bold, design: .rounded))
.font(.system(size: 48, weight: .bold, design: .rounded))Rules
- Minimum size: 11pt (except legal disclaimers)
- Default body: 17pt
- Avoid: Ultralight, Thin, Light weights
- Always: Use system fonts for Dynamic Type support
- Contrast: Use
.primary,.secondary,.tertiary
---
Spacing System
Apple uses an 8-point grid for consistent layouts.
Standard Values
| Points | Usage |
|---|---|
| 4 | Fine adjustments (icons, small text) |
| 8 | Minimum standard spacing |
| 12 | Tight spacing |
| 16 | Standard spacing (most common) |
| 20 | Comfortable spacing |
| 24 | Section spacing, card padding |
| 32 | Large section gaps |
| 40 | Major section separation |
| 48 | Page-level separation |
Padding Patterns
// Cards
.padding(24)
.padding(20)
// Rows
.padding(16)
.padding(.horizontal, 16)
.padding(.vertical, 12)
// Badges/buttons
.padding(.horizontal, 12)
.padding(.vertical, 8)
// Tight elements
.padding(8)Internal ≤ External Rule
External spacing (margins) should equal or exceed internal spacing (padding):
// CORRECT
VStack(spacing: 24) { // External: 24pt
CardView().padding(20) // Internal: 20pt
}
// WRONG
VStack(spacing: 12) { // External: 12pt
CardView().padding(24) // Internal: 24pt - cramped
}Line Height
Line heights should be multiples of 8 for grid alignment:
Text("Content")
.font(.system(size: 15))
.lineSpacing(9) // 15 + 9 = 24pt (multiple of 8)---
SF Symbols
6,900+ icons that integrate with San Francisco font.
Rendering Modes
| Mode | Description | Use Case |
|---|---|---|
| Monochrome | Single color, all layers | Default |
| Hierarchical | Single color with opacity depth | Recommended |
| Palette | Up to 3 explicit colors | Branded icons |
| Multicolor | Apple-defined colors | Realistic icons |
// Hierarchical (preferred)
Image(systemName: icon)
.symbolRenderingMode(.hierarchical)
.foregroundStyle(color)
// Palette
Image(systemName: "person.3.sequence.fill")
.symbolRenderingMode(.palette)
.foregroundStyle(.red, .green, .blue)
// Multicolor
Image(systemName: "externaldrive.badge.plus")
.symbolRenderingMode(.multicolor)Variants
Image(systemName: "heart.fill") // Fill - selection states
Image(systemName: "mic.slash") // Slash - unavailable
Image(systemName: "plus.circle.fill") // Circle - buttons
// Programmatic
Image(systemName: "bell")
.symbolVariant(.fill)
.symbolVariant(.slash)Best Practices
- Match symbol weight to nearby text weight
- Use symbols (not images) on glass backgrounds
- Don't mix rendering modes in same view
- Check SF Symbols app for mode support
---
Hit Targets
Minimum Size
44pt × 44pt is the absolute minimum for all interactive elements.
// Icon button with proper target
Button { } label: {
Image(systemName: "gear")
.font(.system(size: 16))
}
.frame(minWidth: 44, minHeight: 44)
// Small visual, large target
Image(systemName: "info.circle")
.font(.caption)
.frame(width: 44, height: 44)
.contentShape(Rectangle()) // Expand hit areaInteractive Feedback
// Hover (macOS)
.onHover { isHovering in
withAnimation(.easeInOut(duration: 0.15)) {
self.isHovering = isHovering
}
}
// Press scale
.scaleEffect(isPressed ? 0.95 : 1.0)
// Glass interactive (iOS 26+)
.glassEffect(.regular.interactive())---
Accessibility
Automatic Adaptations
| Setting | Effect |
|---|---|
| Reduce Transparency | Opaquer glass |
| Increase Contrast | Visible borders |
| Reduce Motion | No elastic effects |
| Dynamic Type | Text scales |
| VoiceOver | System announces |
Required Practices
1. 44pt minimum hit targets 2. 11pt minimum text size 3. Sufficient contrast - use semantic colors 4. Don't rely on color alone - combine with icons/text 5. Support Dynamic Type - use system font styles
Manual Control
@Environment(\.accessibilityReduceTransparency) var reduceTransparency
@Environment(\.accessibilityReduceMotion) var reduceMotion
var body: some View {
Content()
.glassEffect(reduceTransparency ? .identity : .regular)
.animation(reduceMotion ? nil : .spring(), value: state)
}Testing Checklist
- [ ] VoiceOver enabled
- [ ] Dynamic Type at largest size
- [ ] Reduce Transparency on
- [ ] Increase Contrast on
- [ ] Reduce Motion on
- [ ] Light and Dark modes
- [ ] 44pt touch targets verified
- [ ] Text never below 11pt
---
Resources
Apple Official
- Human Interface Guidelines
- Design Tips
- Designing for macOS
- Materials
- Typography
- SF Symbols
- Design Resources
WWDC Sessions
- WWDC 2025: Meet Liquid Glass
- WWDC 2025: Build a SwiftUI app with the new design
- WWDC 2025: Get to know the new design system
- WWDC 2021: SF Symbols in SwiftUI
Tools
Semantic Colors
Color.blue // Primary actions, links, selection
Color.green // Success, active, confirmed
Color.orange // Warning, loading, attention
Color.red // Destructive, error
Color.purple // Premium, AI features
Color.cyan // Security, privacy
Color.yellow // Highlights, cautionComponent Patterns
Full SwiftUI implementations for Liquid Glass design.
Table of Contents
---
StatCard
Dashboard stat card with icon, value, and label.
struct StatCard: View {
let value: String
let label: String
let icon: String
let color: Color
var body: some View {
VStack(alignment: .leading, spacing: 12) {
HStack {
ZStack {
Circle()
.fill(color.opacity(0.15))
.frame(width: 36, height: 36)
Image(systemName: icon)
.font(.system(size: 16, weight: .semibold))
.foregroundStyle(color)
}
Spacer()
}
VStack(alignment: .leading, spacing: 4) {
Text(value)
.font(.system(size: 28, weight: .bold, design: .rounded))
Text(label)
.font(.caption)
.foregroundStyle(.secondary)
}
}
.padding(20)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
}
}
// Usage
StatCard(value: "1,234", label: "Total Items", icon: "doc.fill", color: .blue)---
SettingsSection
Grouped settings section with icon header.
struct SettingsSection<Content: View>: View {
let title: String
let icon: String
let iconColor: Color
@ViewBuilder let content: Content
var body: some View {
VStack(alignment: .leading, spacing: 16) {
HStack(spacing: 12) {
ZStack {
RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(iconColor.opacity(0.15))
.frame(width: 32, height: 32)
Image(systemName: icon)
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(iconColor)
}
Text(title)
.font(.headline)
}
content
}
.padding(24)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
}
}
// Usage
SettingsSection(title: "Privacy", icon: "lock.shield", iconColor: .cyan) {
Toggle("Enable Feature", isOn: $isEnabled)
Text("Description").font(.caption).foregroundStyle(.secondary)
}---
InteractiveRow
Row with hover-revealed actions.
struct InteractiveRow: View {
let title: String
let subtitle: String
let onCopy: () -> Void
let onDelete: () -> Void
@State private var isHovering = false
var body: some View {
HStack(spacing: 16) {
VStack(alignment: .leading, spacing: 6) {
Text(title)
.font(.body)
.lineLimit(2)
Text(subtitle)
.font(.caption2)
.foregroundStyle(.tertiary)
}
Spacer()
if isHovering {
HStack(spacing: 8) {
Button(action: onCopy) {
Image(systemName: "doc.on.doc").font(.caption)
}
.buttonStyle(.bordered)
Button(action: onDelete) {
Image(systemName: "trash").font(.caption)
}
.buttonStyle(.bordered)
.tint(.red)
}
.transition(.opacity.combined(with: .move(edge: .trailing)))
}
}
.padding(16)
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(isHovering ? Color.primary.opacity(0.04) : Color.clear)
)
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(.quaternary.opacity(0.5))
)
.onHover { hovering in
withAnimation(.easeInOut(duration: 0.15)) {
isHovering = hovering
}
}
}
}---
EmptyStateView
Placeholder for empty content states.
struct EmptyStateView: View {
let icon: String
let title: String
let message: String
var body: some View {
VStack(spacing: 16) {
ZStack {
Circle()
.fill(.quaternary)
.frame(width: 64, height: 64)
Image(systemName: icon)
.font(.title)
.foregroundStyle(.secondary)
}
VStack(spacing: 4) {
Text(title)
.font(.headline)
.foregroundStyle(.secondary)
Text(message)
.font(.subheadline)
.foregroundStyle(.tertiary)
.multilineTextAlignment(.center)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
// Usage
EmptyStateView(
icon: "doc.text",
title: "No Documents",
message: "Create your first document to get started"
)---
OptionRow
Selectable option with checkmark indicator.
struct OptionRow: View {
let title: String
let subtitle: String
let isSelected: Bool
let action: () -> Void
var body: some View {
Button(action: action) {
HStack(spacing: 12) {
VStack(alignment: .leading, spacing: 4) {
Text(title)
.font(.subheadline)
.fontWeight(.medium)
Text(subtitle)
.font(.caption)
.foregroundStyle(.secondary)
}
Spacer()
if isSelected {
Image(systemName: "checkmark.circle.fill")
.font(.title3)
.foregroundStyle(.blue)
}
}
.padding(14)
.background(isSelected ? Color.blue.opacity(0.08) : Color.clear)
.background(.quaternary.opacity(0.5))
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.overlay(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.strokeBorder(isSelected ? Color.blue.opacity(0.3) : Color.clear, lineWidth: 1)
)
}
.buttonStyle(.plain)
}
}---
ExpandableToolbar
Morphing toolbar with animated expansion (iOS 26+).
struct ExpandableToolbar: View {
@State private var isExpanded = false
@Namespace private var namespace
var body: some View {
GlassEffectContainer(spacing: 20) {
HStack(spacing: 16) {
if isExpanded {
Button("Camera", systemImage: "camera") { }
.glassEffect(.regular.interactive())
.glassEffectID("camera", in: namespace)
Button("Photos", systemImage: "photo") { }
.glassEffect(.regular.interactive())
.glassEffectID("photos", in: namespace)
}
Button {
withAnimation(.bouncy) { isExpanded.toggle() }
} label: {
Image(systemName: isExpanded ? "xmark" : "plus")
.frame(width: 44, height: 44)
}
.buttonStyle(.glassProminent)
.buttonBorderShape(.circle)
.glassEffectID("toggle", in: namespace)
}
}
}
}---
Badge Variants
// Status badge
HStack(spacing: 8) {
Circle()
.fill(isActive ? Color.green : Color.orange)
.frame(width: 8, height: 8)
Text(isActive ? "Active" : "Loading...")
.font(.caption)
.fontWeight(.medium)
}
.padding(.horizontal, 12)
.padding(.vertical, 8)
.background(.regularMaterial, in: Capsule())
// Count badge
Text("\(count)")
.font(.caption2)
.fontWeight(.medium)
.foregroundStyle(.secondary)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(.quaternary, in: Capsule())Related skills
How it compares
Pick liquid-glass for native SwiftUI Liquid Glass on Apple platforms rather than CSS glassmorphism skills aimed at web frontends.
FAQ
What platforms does liquid-glass target?
liquid-glass targets native SwiftUI apps on iOS 26+ and macOS Tahoe for the Liquid Glass API, with materials guidance for macOS 14+ and pre-iOS 26 fallbacks documented in the SKILL.md.
Where should Liquid Glass effects go in SwiftUI?
liquid-glass enforces Apple's rule that glass belongs on navigation and controls floating above content, never on content itself. Multiple glass elements must share a GlassEffectContainer to avoid stacked-glass clutter.
How do I install liquid-glass for coding agents?
Run npx skills add casper-studios/casper-marketplace --skill liquid-glass. Agents load HIG patterns for glassEffect modifiers, button styles, spacing, and accessibility when building SwiftUI interfaces.