Skip to content

Surface

The universal themed container. All higher-level components (Card, SettingsGroup, etc.) use Surface internally — switching themes requires zero component changes because Surface adapts automatically.

On the Quartz theme with blurIntensity > 0, Surface renders a BlurView. On Slate and Obsidian, it renders a plain themed View. You never need to handle this conditional — Surface does it.

When to use: Custom containers that need background color, elevation, radius, or border from the active theme. Prefer Card for content cards (it’s Surface with opinionated defaults).

When not to use: When you don’t need a themed background — use a bare View for layout-only containers.

import { Surface } from '@/components';
<Surface elevation="md" padding="md" radius="lg" border>
<Text>Content</Text>
</Surface>
PropTypeDefaultDescription
elevation'none' | 'sm' | 'md' | 'lg''none'Shadow depth
padding'none' | 'sm' | 'md' | 'lg''none'Internal padding from spacing scale
radius'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full''none'Corner radius from theme scale
borderbooleanfalseAdds theme.border.thin in theme.colors.border
childrenReactNodeContent
testIDstringFor testing

Do: Use Surface for themed containers that should update when the theme changes.

<Surface elevation="sm" padding="md" radius="md" border>
<Text variant="label">Account tier</Text>
<Badge label="Pro" variant="accent" />
</Surface>

Don’t: Use a bare <View> with backgroundColor: theme.colors.surface. Surface handles this, including BlurView on Quartz.

// ✗
<View style={{ backgroundColor: theme.colors.surface, padding: 16, borderRadius: 8 }}>
{content}
</View>
// ✓
<Surface padding="md" radius="md">{content}</Surface>
  • Slate / Obsidian: Renders a plain View with backgroundColor: theme.colors.surface
  • Quartz: Renders BlurView when theme.effects.blurIntensity > 0, creating the glass effect
  • Card — Surface with content-card defaults (minimum sm padding, optional press)