flowritescode/fwc-swiftui-skills/swiftui-liquid-glass

Claude Code and agent skill by flowritescode/fwc-swiftui-skills

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Implement, review, and refactor SwiftUI features using the iOS 26+ Liquid Glass API. Use when adopting Liquid Glass in new UI, converting existing surfaces to glass, reviewing glass usage for correctness, or fixing common Liquid Glass pitfalls (custom blur stacks, scroll views, button shapes, bottom bars, pre-enclosed symbols).

Install

npx vskill@latest install flowritescode/fwc-swiftui-skills/swiftui-liquid-glass

SKILL.md

SwiftUI Liquid Glass

Use native Liquid Glass APIs on iOS 26+. Do not recreate the effect with materials, blurs, or shadows.

Core rules

  1. Don't build custom Liquid Glass through adding backgrounds, outlines, blurs and shadows.
  2. Buttons — style: use .buttonStyle(.glass) for non-colored buttons, and .buttonStyle(.glassProminent) for tinted buttons. .glassProminent supports .tint(), but this can only be a color (not a gradient).
  3. Buttons — shape: use .buttonBorderShape() instead of applying a shape to the button label by hand.
  4. Buttons — padding: using this button setup adds roughly 13pt of padding inside the liquid glass shape; keep this in mind when adapting designs.
  5. Custom views: use .glassEffect(.regular, in: ...) to embed custom Views inside liquid glass containers.
  6. Grouped glass: use GlassEffectContainer when multiple liquid glass elements are next to each other. this View / Container adds a liquid merge effect when the elements grow / touch each other.
  7. Scrolling: avoid using liquid glass inside ScrollView and List (anything that scrolls).
  8. Bottom bars: when anchoring a liquid glass View to the bottom of the screen, prefer embedding it in .safeAreaBar(.bottom) instead of a VStack or .overlay(). safeAreaBar adds a subtle blur effect behind its content.
  9. Toolbar items — no glass: on iOS 26+, navigation bar and window toolbar items get a shared Liquid Glass background by default. For items that should not show the glass capsule (plain icons, custom labels, status text, logos), apply .sharedBackgroundVisibility(.hidden) on the `ToolbarItem`, not on the inner view.
  10. SF Symbols — no pre-enclosed symbols: do not use pre-enclosed SF Symbol variants (such as plus.circle, xmark.circle.fill, or trash.circle) inside Liquid Glass buttons or containers. The glass shape already acts as the container; pre-enclosed symbols create an awkward "double enclosure" (a circle inside a circle). Use base/unenclosed symbols (plus, xmark, trash) and let .buttonBorderShape() or the glass container define the enclosing shape.

Decision tree

Need a button?
├─ Neutral / secondary → .buttonStyle(.glass)
└─ Tinted / primary → .buttonStyle(.glassProminent).tint(someColor)
Icon in a glass button / surface?
└─ Plain unenclosed symbol (e.g. "plus", not "plus.circle") — glass provides enclosure
Need a custom non-button surface (chip, badge, card)?
└─ .glassEffect(.regular, in: shape) on the view content
Multiple glass elements nearby?
└─ Wrap in GlassEffectContainer(spacing: ...) { ... }
Fixed bottom toolbar / action bar?
└─ .safeAreaBar(.bottom) { ... } — not VStack + overlay
Toolbar item without glass background?
└─ ToolbarItem { ... }.sharedBackgroundVisibility(.hidden)
Inside ScrollView, List, or Form rows?
└─ Do not use Liquid Glass — use solid/material fallback

Workflow

1) Review existing UI
  • Flag custom blur/material stacks masquerading as glass.
  • Check buttons use .glass / .glassProminent, not hand-built capsules.
  • Confirm .buttonBorderShape() is used instead of clipping the label.
  • Verify grouped elements sit in GlassEffectContainer.
  • Flag glass inside scrollable containers.
  • Check bottom-anchored bars use .safeAreaBar(.bottom).
  • Check toolbar items that should appear without glass use .sharedBackgroundVisibility(.hidden) on the ToolbarItem.
  • Flag pre-enclosed SF Symbols (e.g. circle/square variants) inside glass buttons or surfaces.
  • Gate with #available(iOS 26, *) and provide fallbacks.
2) Implement or refactor
  1. Pick the right primitive (button style vs glassEffect vs safeAreaBar).
  2. Apply layout and typography first; add glass modifiers last.
  3. Wrap adjacent glass elements in GlassEffectContainer.
  4. Account for ~13pt internal button padding when matching designs.
  5. Use unenclosed SF Symbols so the glass shape provides the enclosing geometry.
  6. Add iOS 26 availability checks and pre-26 fallbacks.

Patterns

Glass buttons
swift
// Secondary / neutral
Button("Cancel") { dismiss() }
.buttonStyle(.glass)
.buttonBorderShape(.capsule)
// Primary / tinted — color only, not gradient
Button("Save") { save() }
.buttonStyle(.glassProminent)
.tint(.blue)
.buttonBorderShape(.roundedRectangle(radius: 12))

Do not clip the label yourself:

swift
// ❌ Wrong — shape on label, not the glass button
Button { action() } label: {
Text("Save")
.padding()
.background(.ultraThinMaterial, in: Capsule())
}
// ✅ Right — native glass handles shape and padding
Button("Save") { action() }
.buttonStyle(.glassProminent)
.buttonBorderShape(.capsule)

Do not use pre-enclosed SF Symbols inside glass buttons:

swift
// ❌ Wrong — pre-enclosed symbol creates redundant double enclosure
Button { add() } label: {
Image(systemName: "plus.circle.fill")
}
.buttonStyle(.glass)
.buttonBorderShape(.circle)
// ✅ Right — plain symbol, glass shape provides the enclosure
Button { add() } label: {
Image(systemName: "plus")
}
.buttonStyle(.glass)
.buttonBorderShape(.circle)
Custom glass surfaces
swift
Label("3 items", systemImage: "tray")
.padding(.horizontal, 16)
.padding(.vertical, 10)
.glassEffect(.regular, in: .capsule)

Add .interactive() when the surface responds to touch:

swift
Text("Tap me")
.padding()
.glassEffect(.regular.interactive(), in: .rect(cornerRadius: 16))
Grouped glass (merge effect)
swift
GlassEffectContainer(spacing: 24) {
HStack(spacing: 24) {
ToolButton(icon: "pencil")
ToolButton(icon: "eraser")
ToolButton(icon: "lasso")
}
}
private struct ToolButton: View {
let icon: String
var body: some View {
Image(systemName: icon)
.frame(width: 56, height: 56)
.font(.title2)
.glassEffect(.regular, in: .circle)
}
}

Tune spacing to control how close elements must be before the liquid merge kicks in.

Bottom action bar
swift
ContentView()
.safeAreaBar(.bottom) {
HStack {
Button("Share") { share() }
.buttonStyle(.glass)
Button("Done") { done() }
.buttonStyle(.glassProminent)
}
}

Prefer this over pinning with VStack { Spacer(); ... } or .overlay(alignment: .bottom).

Toolbar items without glass

On iOS 26+, toolbar items in the same logical grouping share a Liquid Glass background. Hide it when the item should look bare:

swift
.toolbar {
ToolbarItem(placement: .principal) {
Text("Draft")
.font(.headline)
}
.sharedBackgroundVisibility(.hidden)
ToolbarItem(placement: .topBarTrailing) {
Button { add() } label: {
Image(systemName: "plus")
}
}
.sharedBackgroundVisibility(.hidden)
ToolbarItem(placement: .topBarTrailing) {
Button("Save") { save() }
.buttonStyle(.glassProminent)
}
}

Apply .sharedBackgroundVisibility(.hidden) on the `ToolbarItem`, not on the Button or label inside. Hiding the effect places the item in its own grouping, which can change spacing relative to glass-backed neighbors.

Do not put the modifier on the inner view:

swift
// ❌ Wrong — modifier on Button, glass background remains
ToolbarItem(placement: .topBarTrailing) {
Button { add() } label: {
Image(systemName: "plus")
}
.sharedBackgroundVisibility(.hidden)
}
// ✅ Right — modifier on ToolbarItem
ToolbarItem(placement: .topBarTrailing) {
Button { add() } label: {
Image(systemName: "plus")
}
}
.sharedBackgroundVisibility(.hidden)
Availability fallback
swift
if #available(iOS 26, *) {
content.glassEffect(.regular, in: .rect(cornerRadius: 16))
} else {
content.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
}

Anti-patterns

Anti-patternWhy it failsDo instead
.background(.ultraThinMaterial) + blur + stroke + shadowNot Liquid Glass; wrong optics and no merge/morph.glassEffect(...) or button styles
Gradient .tint() on .glassProminentAPI accepts color onlySolid Color tint, or custom label without glassProminent tint
Glass on List/ScrollView rowsScroll + glass = visual glitches, perf costOpaque/material rows; glass only on fixed chrome
Shape applied to button labelMisses native padding (~13pt) and border rendering.buttonBorderShape()
Bottom bar via .overlayNo system blur bar treatment.safeAreaBar(.bottom)
Multiple glass views without containerNo merge effect, worse renderingGlassEffectContainer
Glass capsule on toolbar items that should be bareiOS 26 adds shared glass to toolbar groupings by default.sharedBackgroundVisibility(.hidden) on the ToolbarItem
.sharedBackgroundVisibility on inner viewDoes not remove toolbar glass backgroundApply on ToolbarItem (or other ToolbarContent)
Pre-enclosed SF Symbols in glass buttons (plus.circle, xmark.circle.fill)Redundant double enclosure ("circle in circle"); clashes with glass shapeUse unenclosed symbol (plus, xmark) and let .buttonBorderShape provide the container

Review checklist

  • [ ] No hand-rolled blur/material glass imitations
  • [ ] Buttons use .glass or .glassProminent with .buttonBorderShape()
  • [ ] Design spacing accounts for ~13pt internal button padding
  • [ ] Custom surfaces use .glassEffect(.regular, in: ...)
  • [ ] Adjacent glass wrapped in GlassEffectContainer
  • [ ] No glass inside scroll views
  • [ ] Bottom chrome uses .safeAreaBar(.bottom)
  • [ ] Toolbar items without glass use .sharedBackgroundVisibility(.hidden) on ToolbarItem
  • [ ] No pre-enclosed SF Symbols in glass buttons (e.g. "plus" instead of "plus.circle")
  • [ ] #available(iOS 26, *) with fallback on older OS

Additional resources

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
349
Repository forks
16
7-day trend score
29

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/flowritescode/fwc-swiftui-skills/swiftui-liquid-glass/badge)](https://verified-skill.com/skills/flowritescode/fwc-swiftui-skills/swiftui-liquid-glass)

Something wrong with this skill or its page? Tell us.