Surface
Themed container — color ramp, radius, border sides, and padding on one host.
Surface is the primary panel host in ViraUI. Use it wherever a region needs a distinct background plane instead of bare page chrome.
color maps onto the theme base ramp (1–3 or named tokens), radius reads radius steps, and border picks which sides get a contrast edge. Horizontal and vertical padding use the spacing scale; nested surfaces can set radius="auto" so inner corners stay concentric with the parent's padding and rounding. Surface also publishes radius context that menus, nested cards, and glow shells consume.
Surface has no gap prop: nest a Stack for child spacing, or pass render={<Surface … />} on Stack so chrome and layout share one DOM node. Pair with Elevator when the panel needs animated shadow lift; Surface itself has no elevation prop.
When to use
- A region needs a themed background, border, radius, or token padding
- Nested panels should step through the color ramp or keep concentric corners
- Chrome and flex layout should share one node via Stack
render
When not to use
- You only need direction, gap, and alignment → Stack
- The job is resting / hover shadow without a Surface elevation prop → Elevator
- Content should break out of parent padding → Bleed
Related
- Stack — flex gaps and alignment inside or as the Surface host
- Elevator — elevation hooks on the Surface root
- Bleed — pull media or rules past Surface padding
- Separator — inline dividers inside stacked content
Common examples
Color ramp
color picks a base ramp layer so stacked panels read as separate planes. A short workspace board shows layers 1–3 on the theme ramp.
Border sides
border accepts one side or a list: a right edge on a rail, bottom edges between rows, instead of drawing every edge. Omit the prop when the panel should stay borderless.
Nested concentric
Set a large token radius on the outer host and radius="auto" on nested planes so each inset corner stays concentric with the parent's padding. A third nested Surface makes the step-down easier to see; reusing the same token on every layer leaves a flat double-radius look.
Token padding
hPadding / vPadding inset the Surface on the spacing scale; Stack owns gaps between children. Compose with render={<Surface … />} when flex layout and chrome should share one node. A tinted footer strip can still be a nested Surface.
Axis padding tuples
Pass a [start, end] tuple when start and end should use different tokens; never invent paddingBlock* / paddingInline* CSS for those cases. Use 0 on one side only when that edge is intentionally flush (media, shared seam); keep a token when text must clear a border.
Ask your agent
Build three stacked workspace panels that step through lighter and deeper background layers — Overview, Active sprint, and Needs attention — each with a short status line.Last updated on