Components
Surface
Padded, colored panel that stacks its content and remaps text tokens so muted copy stays legible on dark backgrounds.
Install
npx shadcn@latest add @alix/surfacePreview
Default
Muted body text.
Primary
Muted body text.
Sand
Muted body text.
Grey gradient
Muted body text.
Usage
<Surface>
<p>Default</p>
</Surface>
<Surface bgColor="primary">
<p>Primary</p>
</Surface>
<Surface bgColor="sand">
<p>Sand</p>
</Surface>
<Surface bgColor="greyGradient">
<p>Grey gradient</p>
</Surface>Examples
01
Secondary service panel
Use secondary when the surface should hold supporting content without becoming a dark feature panel.
Active engagement
Working capital review
Weekly cash actions, supplier terms, and ownership are tracked in one client workspace.
<Surface bgColor="secondary" className="p-6">
<div className="flex flex-col gap-2">
<Badge variant="primary">Active engagement</Badge>
<h3 className="text-sm font-medium text-foreground">Working capital review</h3>
<p className="text-sm text-muted-foreground text-pretty">
Weekly cash actions, supplier terms, and ownership are tracked in one client workspace.
</p>
</div>
</Surface>02
Primary decision panel
A primary surface can carry a focused section title and one action when the content needs emphasis.
Prepare the next steering update
Summarise risks, owners, and decisions before the client meeting.
<Surface bgColor="primary">
<div className="flex flex-col items-start gap-4">
<SectionTitle
align="start"
headingSize="sm"
title="Prepare the next steering update"
description="Summarise risks, owners, and decisions before the client meeting."
/>
<Button variant="secondary">Open workspace</Button>
</div>
</Surface>03
Form panel
Surface owns the panel treatment while Field, Input, Select, and Button keep the form contract intact.
<Surface className="max-w-xl p-6">
<div className="grid gap-4 md:grid-cols-2">
<Field label="Engagement name">
<Input defaultValue="Project Atlas" />
</Field>
<Field label="Owner">
<Select
defaultValue="jp"
items={[
{ value: "jp", label: "J. Patel" },
{ value: "rs", label: "R. Silva" },
]}
/>
</Field>
</div>
<div className="pt-2">
<Button>Save details</Button>
</div>
</Surface>When to use it
Use it for
- Contained service, insight, or form panels where the background treatment is part of the content hierarchy.
- Dark primary panels that need token remapping so muted copy stays legible.
- Small composed regions where the child components should keep their own APIs.
Reach for something else
- Page-wide section spacing and max-width rules — use SectionWrapper and Container instead.
- Dashboard cards with built-in headers, actions, or footers — use Panel instead.
- Gold section surfaces — use Surface with bgColor="primary" or bgColor="secondary" instead.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| bgColor | "default" | "primary" | "secondary" | "sand" | "greyGradient" | "goldGradient" | "default" | Full surface treatment — background plus, on dark surfaces, a text and muted-foreground remap that keeps content legible. |
| children | ReactNode | — | Composition slot for whatever sits on the surface (a SectionTitle, Text, form, etc.). Surface owns the surface, not its contents. |