soft-glass-ui
npx machina-cli add skill simonstrumse/vibelabs-skills/soft-glass-ui --openclawGlass UI Design System
A comprehensive design system for creating premium glass interfaces. Supports iOS 26+ native Liquid Glass (glassEffect) and provides fallback patterns for iOS 17-18.
Critical Insight: iOS 26 Liquid Glass
The "glass" effect in iOS 26 is NOT gradients and shadows. It's a physically-accurate lensing system that samples the background and creates real-time refraction effects.
What This Means:
-
Glass needs colorful/dark backgrounds - Unlike gradient-based glass that works on any background, native liquid glass samples what's behind it. On a plain white background, glass appears nearly invisible.
-
Use
.ultraThinMaterial+.glassEffect()- The material provides the frosted base, the glassEffect adds the liquid refraction. -
Interactive feedback is built-in -
.glassEffect(.regular.interactive())provides touch scaling/bouncing animations automatically.
iOS Version Strategy
| iOS Version | Approach |
|---|---|
| iOS 26+ | Native .glassEffect() modifier with .ultraThinMaterial |
| iOS 17-18 | Gradient-based fallback with .ultraThinMaterial or custom gradients |
iOS 26 Native Liquid Glass
The Core Pattern
// The iOS 26 glass pattern
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
Glass Effect Variants
| Variant | Usage |
|---|---|
.regular | Standard glass for cards, containers |
.regular.tint(color) | Adds color tint to the glass |
.regular.interactive() | Enables touch feedback animations |
.clear | More transparent, for media-rich backgrounds |
Example: Glass Button
Button(action: action) {
HStack {
Image(systemName: "play.fill")
Text("Start")
}
.padding()
.foregroundStyle(.white)
.background(LinearGradient.brandGradient)
.clipShape(RoundedRectangle(cornerRadius: 16))
.glassEffect(
.regular.tint(.brandPrimary).interactive(),
in: RoundedRectangle(cornerRadius: 16)
)
}
Background Requirements
Glass needs something to sample. Create rich backgrounds:
// Rich gradient background for glass to sample
struct BrandBackgroundModifier: ViewModifier {
func body(content: Content) -> some View {
content
.background {
ZStack {
// Deep base color
Color(hex: "0A0A1A")
// Animated gradient orbs
Circle()
.fill(RadialGradient(
colors: [.brandPrimary.opacity(0.4), .clear],
center: .center,
startRadius: 0,
endRadius: 200
))
.frame(width: 400, height: 400)
.offset(x: -100, y: -150)
Circle()
.fill(RadialGradient(
colors: [.brandSecondary.opacity(0.3), .clear],
center: .center,
startRadius: 0,
endRadius: 180
))
.frame(width: 360, height: 360)
.offset(x: 120, y: 200)
}
.ignoresSafeArea()
}
}
}
Fallback for iOS 17-18
When targeting older iOS versions, use gradient-based glass:
struct GlassCardFallback<Content: View>: View {
let content: Content
var body: some View {
content
.padding(24)
.background(
LinearGradient(
colors: [.white, Color.surfaceWarm.opacity(0.3)],
startPoint: .top,
endPoint: .bottom
)
)
.clipShape(RoundedRectangle(cornerRadius: 16))
.shadow(color: .black.opacity(0.08), radius: 10, y: 4)
}
}
Availability Check Pattern
struct GlassCard<Content: View>: View {
let content: Content
var body: some View {
if #available(iOS 26.0, *) {
content
.padding(24)
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
} else {
content
.padding(24)
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}
}
Design Tokens
Spacing Scale (8pt base)
xs: 4 s: 8 m: 16 l: 24 xl: 32 xxl: 48
Corner Radius Scale
small: 8 medium: 12 large: 16 xl: 24
Animation Timings
fast: 0.3s spring(response: 0.3, dampingFraction: 0.7)
standard: 0.5s spring
slow: 1.0s spring
stagger-delay: 0.05s per item
Typography
Use rounded font design throughout:
.font(.system(size: 16, weight: .medium, design: .rounded))
| Style | Size | Weight |
|---|---|---|
| hero | 48-56 | bold/heavy |
| title | 28 | bold |
| headline | 20 | semibold |
| body | 16 | medium |
| caption | 14 | medium |
| small | 12 | regular |
Color Strategy
For iOS 26 Liquid Glass
Use light text on dark backgrounds:
extension Color {
// Text (white-based for dark backgrounds)
static var brandText: Color { .white }
static var brandTextSecondary: Color { .white.opacity(0.7) }
static var brandTextMuted: Color { .white.opacity(0.5) }
// Accent colors (vibrant for glass tinting)
static var brandPrimary: Color { Color(hex: "6366F1") } // Indigo
static var brandAccent: Color { Color(hex: "10B981") } // Emerald
static var brandSecondary: Color { Color(hex: "8B5CF6") } // Purple
}
For Fallback (Light Mode)
Use dark text on light backgrounds:
extension Color {
static var brandText: Color { Color(hex: "1E293B") }
static var surfaceWarm: Color { Color(hex: "FDF8F3") } // Warm cream
}
Key Components
See references/components.md for detailed implementations:
- GlassButton - Primary actions with glass + gradient
- GlassCard - Container with glass background
- GlassSelectionCard - Selectable cards with tinted glass
- GlassProgressRing - Timer/progress with glass track
- GlassToast - Notification overlays
- GlassIconCircle - Icon badges with glass background
Common Mistakes to Avoid
1. Using glass on white/plain backgrounds
Glass needs something to refract. Plain backgrounds make glass invisible.
2. Forgetting the shape parameter
.glassEffect requires a shape:
// Wrong
.glassEffect(.regular)
// Correct
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
3. Using gradients instead of materials on iOS 26
The native glass effect looks better than any gradient approximation.
4. Not providing interactive feedback
Use .interactive() on buttons for native touch animations:
.glassEffect(.regular.interactive(), in: RoundedRectangle(cornerRadius: 16))
Quick Reference
iOS 26 Glass Card:
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
iOS 26 Tinted Glass:
.glassEffect(.regular.tint(.brandPrimary), in: RoundedRectangle(cornerRadius: 16))
iOS 26 Interactive Button:
.glassEffect(.regular.tint(.accent).interactive(), in: RoundedRectangle(cornerRadius: 16))
Deployment Target: Set to iOS 26.0 to use native .glassEffect() API.
Source
git clone https://github.com/simonstrumse/vibelabs-skills/blob/main/skills/soft-glass-ui/SKILL.mdView on GitHub Overview
Soft-glass-ui is a SwiftUI design system for building premium glass interfaces. It uses iOS 26+ native Liquid Glass via the glassEffect modifier and provides gradient-based fallbacks for older iOS versions, enabling glassmorphism, translucent cards, and modern Apple-style interfaces.
How This Skill Works
Core pattern uses .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16)) combined with .glassEffect(...) on iOS 26+ to create real-time refraction. For iOS 17-18, it switches to gradient-based fallbacks that emulate the glass look. The system exposes variants like .regular, .regular.tint(color), .regular.interactive(), and .clear to control depth, color, and interactivity.
When to Use It
- Building SwiftUI iOS apps that require glassmorphism or translucent cards.
- Targeting iOS 26+ to leverage native .glassEffect and real refraction.
- Creating premium, Apple-style interfaces with glass elements.
- Need graceful degradation on older iOS versions via gradient fallbacks.
- Requests for liquid glass, glassmorphism, iOS 26 design, premium UI, or translucent interfaces.
Quick Start
- Step 1: Determine target iOS version and plan to use native .glassEffect on iOS 26+ with a rich background.
- Step 2: Implement the core pattern: .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16)) and .glassEffect(...).
- Step 3: Add a gradient-based fallback (e.g., for iOS 17-18) and include tint/interactive variants as needed.
Best Practices
- Glass needs a rich background to sample; avoid plain white backdrops for best results.
- Use the core pattern: .background(.ultraThinMaterial, in: RoundedRectangle(...)) and .glassEffect(...).
- Leverage variants like .regular, .regular.tint(color), and .regular.interactive() for depth and feedback.
- Provide a gradient or dynamic background when targeting iOS 17-18 fallbacks to ensure believable glass.
- Test glass elements on real devices to verify contrast, legibility, and performance across backgrounds.
Example Use Cases
- Glass Button example using .glassEffect(.regular, in: RoundedRectangle(...)) with an icon and label.
- BrandBackgroundModifier demonstrating a rich gradient background with animated orbs to sample glass.
- Using .regular.tint(color) to add a color accent to the glass surface.
- Applying .regular.interactive() to enable built-in touch feedback and animations.
- Fallback gradient approach for iOS 17-18 when native glassEffect is unavailable.