FORK

Visual Direction

Liquid Glass, frosted fallbacks, and the PlanarKit dot pattern

Liquid Glass / Frosted Fallback

iOS 26 Liquid Glass
Refraction, lensing, specular highlights
Content behind the glass refracts and distorts. Specular highlights shift with device motion. Surfaces morph and merge like water droplets when they overlap. Color is light that bleeds through material.
UIGlassEffect · .glassEffect() · GlassEffectContainer · real-time lensing
iOS 16–25 Frosted Fallback
Static blur + vibrancy. No refraction or morphing, but still translucent and context-aware. Same visual hierarchy, simpler material.
UIVisualEffectView · .systemThinMaterial · backdrop-filter: blur()
Tinted glass
Both tiers support tint. Liquid Glass auto-vibrates the color. Frosted uses a color overlay on the blur layer. Tint = brand accent bleeding through the surface.
UIGlassEffect.tintColor · UIVibrancyEffect
Liquid Glass iOS
iOS 26+ / UIGlassEffect
  • RefractionContent bends through the surface like real glass
  • SpecularHighlights shift with device tilt and motion
  • MorphingGlass elements merge when they overlap (GlassEffectContainer)
  • Adaptive sizeLarger = more opaque, smaller = clearer with auto light/dark
  • Corners.containerRelative auto-adapts radius to parent
  • TinttintColor auto-vibrated to match surface
Frosted Fallback iOS
iOS 16–25 / UIVisualEffectView
  • Blur.systemUltraThinMaterial / .systemThinMaterial / .systemMaterial
  • VibrancyUIVibrancyEffect for labels and icons on blur
  • LayeringMax 3 levels before blur compounds and kills performance
  • CornersCALayer.cornerCurve = .continuous for smooth rounding
  • Borders1px separator-color to define edges without shadow
  • TintColor overlay on blur layer, manual vibrancy adjustment
backdrop-filter Web
CSS / All modern browsers
  • Blurbackdrop-filter: blur(20px) saturate(1.4)
  • SafariRequires -webkit-backdrop-filter prefix
  • Backgroundrgba(255,255,255,0.45) light / rgba(255,255,255,0.06) dark
  • Border1px rgba(255,255,255,0.35) for edge definition
  • SpecularCSS pseudo-element gradient (see this page's glass cards)
  • No refractionWeb cannot distort content through the surface. Blur only.
01
Material over shadow
Depth through translucency and light, not drop shadows. The surface IS the elevation.
02
Color is light
Accent colors glow through glass like LEDs behind frosted plastic. Tint bleeds, never paints.
03
Grid stays rigid
Soft material, hard alignment. Monospace labels and utilitarian grid anchor the fluidity.
04
Serif warmth on glass
Besley on refractive surface. Human warmth meets optical precision.
When to use
  • Liquid Glass/iOS 26+ primary surfaces — navigation bars, tab bars, sidebars, floating panels. The default material for elevated UI.
  • Frosted Fallback/iOS 16–25 or Reduce Transparency. Same hierarchy, simpler material. Also the Web approximation via backdrop-filter.
  • Tinted Glass/Brand moments — onboarding, feature highlights, premium surfaces. Tint bleeds through the material.
Platform notes
  • #available(iOS 26, *)/Use UIGlassEffect + .glassEffect() for full Liquid Glass
  • Fallback/UIVisualEffectView with .systemThinMaterial for iOS 16–25
  • GlassEffectContainer/Group nearby glass elements to enable morphing when frames overlap
  • isInteractive/Set true on UIGlassEffect for buttons, controls — adds scale/bounce/shimmer
  • cornerConfiguration/.containerRelative for auto-adapting corner radius near parent edges
  • Reduce Transparency/Must replace glass with opaque systemBackground — use our token palette
  • Performance/Max 3 glass layers. Glass cannot sample other glass — keep hierarchy flat
  • Android No equivalent to iOS Liquid Glass (UIGlassEffect). Use frosted fallback: RenderEffect.createBlurEffect() (API 31+) or Compose Modifier.blur(). For older APIs, use a semi-transparent surface with no blur.
  • Android Android glass tier matches the "Frosted" tier — blur + overlay, no refraction or lensing. Treat this as the Android glass tier across all surfaces.

Glass + Dot Pattern Interaction

Layering
Glass refracts the grid
When a glass surface sits above the dot pattern, the dots blur and shift through the material. The grid becomes an ambient texture that reinforces the translucency of the surface above.
Liquid Glass over Dots
iOS 26+
  • RefractionDots distort through the lens — position shifts create depth perception
  • SpecularDot opacity modulates under highlight bands as device tilts
  • InteractionTouch ripple passes through glass to the grid beneath. Both layers respond.
  • Z-orderPlaneView → glass surface → content. Grid is always the deepest layer.
Frosted Glass over Dots
iOS 16–25
  • BlurDots dissolve into a soft luminance texture under .systemThinMaterial
  • VibrancyLabels on glass gain subtle contrast from dot pattern density beneath
  • Glow haloAmbient colors from PlaneScene bleed through blur, tinting the frosted surface
  • PerformancePlaneView renders at 60fps under blur — no extra GPU cost for the composition
When to use
  • Glass over dots/Main app background with elevated glass surfaces. The dot grid provides ambient texture beneath translucent chrome.
  • Layering order/PlaneView (bottom) → glass surface (middle) → content (top). Never reverse this order.
Platform notes
  • PlaneView as background/Add PlaneView as the bottom-most subview. Glass surfaces overlay it naturally.
  • Don't double-blur/Glass already blurs PlaneView content. Never add a separate UIVisualEffectView between them.
  • Ambient color bleed/PlaneScene.ambientColors (5 hues at 0.3 alpha) create color waves that tint glass surfaces from below.
  • Touch passthrough/PlaneGestureCoordinator registers at the window level — touch events reach the dot grid through any glass surface.
  • Reduce Transparency/When enabled: replace glass with opaque systemBackground, keep dot grid visible at idle opacity.
  • Android No PlaneView equivalent. Implement the dot grid with Canvas/CustomPainter in Compose or a custom View. Layer the frosted surface (RenderEffect.createBlurEffect()) above the dot canvas.
  • Android Touch passthrough: use Modifier.pointerInput in Compose or override onTouchEvent to forward events from the glass surface to the dot canvas beneath.

Dot Pattern / PlanarKit

Tap · Hold 0.3s · Drag
radialGravity
outline
repulsion
vortex
magnetic
fieldAttachment
Idle — dotIdle
Barely visible. The pattern is felt more than seen — a subtle texture that gives the surface tactility without visual noise.
Light: label @ 5% · Dark: label @ 2%
Tap / Ripple — dotTap
Expanding ring displacement pushes dots outward while color brightens and tints within the ripple band. Spring return pulls dots home.
Light: label @ 17% · Dark: label @ 10%
Drag / Field — dotField
Sustained interaction. Dots within field radius are displaced and tinted toward field color. Force and color fall off with distance (quadratic).
Light: label @ 30% · Dark: label @ 18%
Grid
Dot size3pt diameter
Spacing21pt (PlaneScene.dotSpacing)
ShapeCircle · Metal point sprite
BackgroundsystemGroupedBackground
Frame rate30fps idle · 60fps interaction
Overflowmax(spacing × 3, 100)
PhysicsWorld
spring0.03
damping0.88
relaxation0.02
falloff2.0
Effects
ripple (tap)str 1 · spd 13 · w 10 · 3s
ringspd 2 · w 80 · 4s
shockwavestr 4 · spd 25 · w 6 · 1.2s
bloomspd 1.5 · w 100 · 5s
noiseTintspd 2 · w 300 · 8s
Wave typesring · bloom · noise
Fields & Interaction
radialGravitystr 0.5 · r 200 · falloff 1
outlineattract to ring perimeter
repulsion / vortexpush away / tangential swirl
dragField defaultstr 0.01 · r 390 · iF 0.3
Long press0.3s min · activates dragField
Ambientrandom color waves 5–12s interval
When to use
  • Hover/Field follows cursor at 50% strength. Dots displace and tint toward the active field color. Leaves on mouse exit.
  • Tap/Ripple expands from touch point (str 1 · spd 13 · ring width 10 · 3s). No field activation — displacement only.
  • Hold (0.3s)/Activates drag field at full strength. Matches native PlaneGestureCoordinator long-press threshold.
  • Drag/Field follows pointer. Trail rings spawn every 25px of movement. Field type set by mode selector.
  • Release/Field fades out over 0.6s. Dots spring back to home positions (spring 0.03 · damping 0.88).
  • Ambient/Random color waves (bloom/ring) fire every 5–12s using tint palette. Continuous while canvas is visible.
  • Presence, not decoration/The dot grid should be felt as surface texture. If you notice it at rest, the opacity is too high.
  • Interaction reveals/Touch makes the pattern come alive — dots brighten, displace, return. The grid is dormant until the user engages.
  • Color from fields/Dots near UI elements pick up field tint via PlaneFieldAttachment. Color propagates spatially, not globally.
  • Always background/PlaneView is the deepest layer. Glass, content, and controls all sit above it.
  • Token-derived/All dot colors derive from the label token at varying alpha. No custom palette — same warmth as the design language.
Platform notes
  • iOS Metal compute shader (GPU physics) + point sprite rendering. Double-buffered dot buffers. PlaneGestureCoordinator handles window-level tap/long-press/pan. Adaptive frame rate: 30fps idle, 60fps on interaction.
  • iOS PlaneFieldAttachment binds any UIView to a named PlaneScene — invisible rounded-rect nodes track view bounds, creating gravity fields that attract dots toward UI elements.
  • Web Canvas 2D reference implementation shown above — same physics model (spring + damping + relaxation), same grid parameters (3px dots, 21px spacing), same field types. Adapted force strengths for Canvas scale.
  • Web CSS radial-gradient fallback for static/decorative use (landing page, backgrounds). Use --dotIdle / --dotTap / --dotField tokens.
  • Android Implement with Canvas/CustomPainter in Compose or custom View. For Metal-equivalent particle performance, use Vulkan compute or a Canvas drawCircle loop at 60fps. Same physics model (spring + damping + relaxation) and grid parameters (3px dots, 21px spacing).
  • Android Dot states (idle/tap/field): same opacity tokens apply. Use Animatable in Compose for smooth state transitions between --dotIdle, --dotTap, and --dotField values.