--- name: spatial-design description: Web and App implementation guide for Spatial Design. Trigger when user wants environment-aware layouts, Apple Vision Pro inspiration, and mixed reality aesthetics. date_added: "2026-06-17" risk: safe source: self source_type: self --- # Spatial Design > "UI that belongs in the room with you. Transparent, glass-like panels that react to the lighting of the physical space." ## When to Use Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the `design-it` skill and is not meant to be triggered directly. ## Core Principles 1. **Environmental Transparency**: The UI acts like a glass pane. It is deeply reliant on background blur, but specifically aims to let the environment (or a simulated environment image) dictate the mood. 2. **Dynamic Lighting**: Elements respond to cursor position as if a flashlight is shining on them. 3. **Subtle Volume**: Not flat, but not extremely 3D. Elements have a very thin rim of light around the edge (specular highlight). ## Visual DNA - **Colors**: Almost exclusively uses `rgba()` white or black. The actual color comes entirely from the background environment. - **Typography**: Extremely sharp, high legibility. Often uses varying font weights to establish hierarchy without relying on color. Apple's `SF Pro` is the gold standard here. - **Icons**: Outlined, high-legibility glyphs. ## Web Implementation - **CSS Example**: ```css body { /* Needs a complex background to look right */ background: url('room-environment.jpg') cover; } .spatial-panel { /* The core material */ background: rgba(255, 255, 255, 0.2); /* Very sheer */ backdrop-filter: blur(40px) saturate(150%); -webkit-backdrop-filter: blur(40px) saturate(150%); border-radius: 32px; padding: 40px; /* The specular rim light */ box-shadow: inset 0 1px 1px rgba(255,255,255,0.6), inset 0 0 1px 1px rgba(255,255,255,0.2), 0 24px 48px rgba(0,0,0,0.1); } .spatial-btn { background: rgba(0,0,0,0.1); color: white; border-radius: 20px; padding: 12px 24px; backdrop-filter: blur(10px); transition: all 0.2s; } .spatial-btn:hover { background: rgba(255,255,255,0.2); /* Highlight effect */ box-shadow: inset 0 0 20px rgba(255,255,255,0.4); } ``` ## App Implementation ### SwiftUI ```swift struct SpatialDesignView: View { var body: some View { ZStack { // Environment background Image("room-environment") .resizable() .aspectRatio(contentMode: .fill) .ignoresSafeArea() // Spatial Panel VStack(spacing: 24) { Text("Environmental UI") .font(.title).fontWeight(.bold) .foregroundColor(.white) Button(action: {}) { Text("Interact") .foregroundColor(.white) .padding(.horizontal, 32) .padding(.vertical, 16) } .background(.ultraThinMaterial) .clipShape(Capsule()) .overlay(Capsule().stroke(Color.white.opacity(0.3), lineWidth: 1)) } .padding(40) .background(.ultraThinMaterial) // The core spatial material .cornerRadius(32) // Specular rim light .overlay( RoundedRectangle(cornerRadius: 32) .stroke( LinearGradient( colors: [.white.opacity(0.6), .white.opacity(0.1)], startPoint: .topLeading, endPoint: .bottomTrailing ), lineWidth: 1 ) ) // Very soft, diffuse shadow .shadow(color: .black.opacity(0.1), radius: 40, y: 20) } } } ``` - `.background(.ultraThinMaterial)` is exactly what Apple uses for this aesthetic. - The specular highlight is critical. Use an `.overlay` with a `LinearGradient` stroke to simulate a light source hitting the top-left edge of the glass. ### Flutter ```dart import 'dart:ui'; class SpatialDesignScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Stack( fit: StackFit.expand, children: [ Image.asset('assets/room-environment.jpg', fit: BoxFit.cover), Center( child: ClipRRect( borderRadius: BorderRadius.circular(32), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 30.0, sigmaY: 30.0), child: Container( width: 350, padding: const EdgeInsets.all(40), decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(32), // Specular rim light border: Border.all(color: Colors.white.withOpacity(0.4), width: 1), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Environmental UI', style: TextStyle(color: Colors.white, fontSize: 28, fontWeight: FontWeight.bold)), const SizedBox(height: 32), // Spatial Button ClipRRect( borderRadius: BorderRadius.circular(50), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: Container( padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16), decoration: BoxDecoration( color: Colors.black.withOpacity(0.1), border: Border.all(color: Colors.white.withOpacity(0.2)), borderRadius: BorderRadius.circular(50), ), child: const Text('Interact', style: TextStyle(color: Colors.white)), ), ), ) ], ), ), ), ), ), ], ), ); } } ``` - `BackdropFilter` is required to blur the background. - Notice the button *inside* the panel also has a `BackdropFilter`. This creates nested glass, which is a hallmark of Spatial Design. ### React Native ```jsx // REQUIRES: @react-native-community/blur import { BlurView } from '@react-native-community/blur'; const SpatialDesignScreen = () => { return ( Environmental UI Interact ); }; ``` - `BlurView` from `@react-native-community/blur` is the only way to achieve this. - Use `blurType="light"` for the main panel and `blurType="dark"` for the buttons to create contrast between the glass layers. ### Jetpack Compose ```kotlin @Composable fun SpatialDesignScreen() { Box(modifier = Modifier.fillMaxSize()) { Image(painterResource(R.drawable.room_environment), null, contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize()) Box( modifier = Modifier .align(Alignment.Center) .width(350.dp) // Shadow goes on the outside .shadow(20.dp, RoundedCornerShape(32.dp), spotColor = Color.Black.copy(alpha = 0.1f)) // Android 12+ Blur .graphicsLayer { renderEffect = RenderEffect.createBlurEffect(30f, 30f, Shader.TileMode.DECAL).asComposeRenderEffect() clip = true shape = RoundedCornerShape(32.dp) } .background(Color.White.copy(alpha = 0.1f)) .border(1.dp, Brush.linearGradient(listOf(Color.White.copy(alpha = 0.6f), Color.Transparent)), RoundedCornerShape(32.dp)) .padding(40.dp), contentAlignment = Alignment.Center ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Text("Environmental UI", color = Color.White, fontSize = 28.sp, fontWeight = FontWeight.Bold) Spacer(Modifier.height(32.dp)) // Button Box( modifier = Modifier .background(Color.Black.copy(alpha = 0.1f), CircleShape) .border(1.dp, Color.White.copy(alpha = 0.2f), CircleShape) .padding(horizontal = 32.dp, vertical = 16.dp) ) { Text("Interact", color = Color.White) } } } } } ``` - The `Brush.linearGradient` applied to the `Modifier.border` perfectly simulates the top-down rim light hitting a thick pane of glass. ## Do's and Don'ts - **DO**: Crank up the `saturate()` filter on the backdrop blur to make the background colors pop through the glass. - **DON'T**: Use dark, opaque drop shadows. The UI should look like glass, which doesn't cast harsh shadows. ## Limitations - This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review. - Ensure appropriate contrast ratios and responsive behaviors are verified separately.