Claude Code Plugins

Community-maintained marketplace

Feedback

ios26-liquid-glass

@praveenperera/dotfiles
4
5

iOS 26 Liquid Glass API reference for SwiftUI and UIKit. Use this skill when working with glassEffect, GlassEffectContainer, glassEffectID, glassEffectUnion, or any Liquid Glass related code on iOS 26+.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name ios26-liquid-glass
description iOS 26 Liquid Glass API reference for SwiftUI and UIKit. Use this skill when working with glassEffect, GlassEffectContainer, glassEffectID, glassEffectUnion, or any Liquid Glass related code on iOS 26+.

iOS 26 Liquid Glass Reference

Liquid Glass is Apple's design language introduced at WWDC 2025. Glass elements float above content with translucent, depth-aware surfaces that reflect and refract surrounding content.

SwiftUI - glassEffect Modifier

func glassEffect<S: Shape>(
    _ glass: Glass = .regular,
    in shape: S = DefaultGlassEffectShape,
    isEnabled: Bool = true
) -> some View

Apply .glassEffect() last in your modifier chain for correct rendering.

Glass Variants

Variant Description Use Case
.regular Default, balanced transparency Most UI elements (buttons, controls, overlays)
.clear High transparency, limited adaptivity Media-rich backgrounds (needs dimming layer)
.identity No effect applied Conditional glass application

Glass Modifiers

// semantic color tinting - use only for meaning (success, warning, destructive)
.glassEffect(.regular.tint(.blue))

// iOS-only: enables scaling, bounce, shimmer on interaction
.glassEffect(.regular.interactive())

// combined
.glassEffect(.regular.tint(.blue).interactive())

Shapes

// default shape (capsule)
.glassEffect()
.glassEffect(.regular, in: DefaultGlassEffectShape())

// built-in shapes
.glassEffect(.regular, in: .capsule)
.glassEffect(.regular, in: .circle)
.glassEffect(.regular, in: .ellipse)
.glassEffect(.regular, in: .rect(cornerRadius: 12))
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))

// adapts corner radius to parent container (for buttons in cards/sheets)
.glassEffect(.regular, in: .rect(cornerRadius: .containerConcentric))

GlassEffectContainer

Groups multiple glass elements for seamless blending and morphing. Glass cannot sample other glass, so use this when elements are positioned closely.

GlassEffectContainer(spacing: 8) {  // spacing = merge threshold in points
    Button("One") { }
        .glassEffect()

    Button("Two") { }
        .glassEffect()
}

When elements are closer than spacing, they visually blend and morph together like water droplets.

Rules

  • Don't nest GlassEffectContainer inside another
  • Don't place Menu inside GlassEffectContainer (breaks morphing in iOS 26.1)
  • Don't use .clipShape() on glassEffect views

glassEffectID - Morphing Transitions

Associates glass elements across states for fluid morphing animations. Requires @Namespace and GlassEffectContainer.

@Namespace var namespace
@State var expanded = false

GlassEffectContainer {
    if expanded {
        HStack {
            Button("Home") { }
                .glassEffect(.regular.interactive())
                .glassEffectID("home", in: namespace)

            Button("Settings") { }
                .glassEffect(.regular.interactive())
                .glassEffectID("settings", in: namespace)
        }
    } else {
        Button("Menu") { expanded = true }
            .glassEffect(.regular.interactive())
            .glassEffectID("menu", in: namespace)
    }
}
.animation(.easeInOut, value: expanded)

Requirements for Morphing

  1. Elements must be within the same GlassEffectContainer
  2. Each view needs glassEffectID with shared namespace
  3. Views must be conditionally shown/hidden
  4. Animation must be applied to the state change
  5. All morphing elements should use same Glass style and tint

glassEffectUnion - Grouping Elements

Makes multiple elements appear as a single glass shape (like Apple Maps zoom controls).

@Namespace var ns

VStack(spacing: 0) {
    Button(action: { /* zoom in */ }) {
        Image(systemName: "plus")
    }
    .glassEffect(.regular.tint(.white.opacity(0.8)))
    .glassEffectUnion(id: "zoom", namespace: ns)

    Divider()

    Button(action: { /* zoom out */ }) {
        Image(systemName: "minus")
    }
    .glassEffect(.regular.tint(.white.opacity(0.8)))
    .glassEffectUnion(id: "zoom", namespace: ns)
}

Requirements

All elements in a union must have:

  • Same union id
  • Same glass effect variant
  • Same tint (color and opacity)

UIKit Support

UIGlassEffect

if #available(iOS 26.0, *) {
    let glassEffect = UIGlassEffect()
    let effectView = UIVisualEffectView(effect: glassEffect)
    effectView.frame = CGRect(x: 20, y: 100, width: 200, height: 50)
    view.addSubview(effectView)

    // add content to contentView
    let label = UILabel()
    label.text = "Glass Effect"
    effectView.contentView.addSubview(label)
}

UIGlassContainerEffect - Merging Glass Views

if #available(iOS 26.0, *) {
    let containerEffect = UIGlassContainerEffect()
    containerEffect.spacing = 12  // merge distance threshold

    let containerView = UIVisualEffectView(effect: containerEffect)

    let glass1 = UIVisualEffectView(effect: UIGlassEffect())
    let glass2 = UIVisualEffectView(effect: UIGlassEffect())

    containerView.contentView.addSubview(glass1)
    containerView.contentView.addSubview(glass2)
}

Corner Configuration

if #available(iOS 26.0, *) {
    let effectView = UIVisualEffectView(effect: UIGlassEffect())
    effectView.cornerConfiguration = UIViewCornerConfiguration(
        corners: .allCorners,
        cornerRadius: 16
    )
}

UIHostingController Integration

When embedding SwiftUI glass in UIKit:

  • Place in navigationItem.titleView (not leftBarButtonItem/rightBarButtonItem)
  • Set sizingOptions = [.intrinsicContentSize]

Backward Compatibility

The Glass type only exists on iOS 26+. Create wrappers with #available:

extension View {
    @ViewBuilder
    func applyGlassEffect() -> some View {
        if #available(iOS 26.0, *) {
            self.glassEffect()
        } else {
            self  // no-op on older iOS
        }
    }

    // with parameters - requires @available at call site
    @available(iOS 26.0, *)
    @ViewBuilder
    func applyGlassEffect(
        _ glass: Glass,
        in shape: some Shape = DefaultGlassEffectShape()
    ) -> some View {
        self.glassEffect(glass, in: shape)
    }
}

Fallback for older iOS

if #available(iOS 26.0, *) {
    content.glassEffect()
} else {
    content.background(.ultraThinMaterial, in: .capsule)
}

Design Guidelines

When to Use

  • Navigation elements (tab bars, toolbars, nav bars)
  • Floating action buttons
  • Control panels and overlays
  • Search bars and input fields
  • Modal/sheet presentations
  • Interactive elements that sit "above" content

When NOT to Use

  • Core content (list rows, table cells)
  • Card backgrounds with primary information
  • Media-rich content areas
  • Text-heavy sections
  • Decorative elements with no function

Best Practices

  • Use .interactive() for buttons/controls on iOS
  • Use .tint() only for semantic meaning
  • Test in light mode, dark mode, and with "Reduce Transparency"
  • Maintain 4.5:1 contrast ratio (WCAG AA)
  • Use .containerConcentric corner radius for elements in containers
  • Monitor performance in scrollable lists on older iPhones

Known Issues

Issue Workaround
Menu in GlassEffectContainer breaks morphing (iOS 26.1) Don't nest Menu in container
Morphing circle ↔ rectangle has glitches Avoid drastically different shape transitions
glassEffectID inconsistent Consider .matchedGeometryEffect as alternative
UIHostingController in bar items causes side effects Use titleView instead

Button Styles

// translucent glass button
Button("Glass") { }
    .buttonStyle(.glass)

// opaque prominent glass button
Button("Prominent") { }
    .buttonStyle(.glassProminent)

Tab Bar Behavior

// tab bar minimizes when scrolling down
.tabBarMinimizeBehavior(.onScrollDown)

Resources