Surface
Navigation & layoutBrick 0.1.12

Surface

Surface paints a semantic region with a controlled tone and background level, optional border, elevation, radius, and inset. Ordinary Surface renders one native element. Optional Media, Scrim, and Content parts layer decorative authored media behind foreground content without adding interaction or runtime color context.

Live example

Built from the published package

Interactive
Base
Subtle
Raised
Choose with confidence

Know when Surface is the right part

Use it when

Use Surface for generic painted regions such as application sections, workspaces, specimen panels, and nested background layers. Combine it with Container for page measure and Stack or Grid for child layout.

Choose another path when

Use Card for a self-contained content object, modal components for interactive overlays, and application CSS for product-specific decoration. Surface is not a Box, layout primitive, theme provider, or substitute for semantic HTML.

Installation and imports

tsx
import { Surface } from "@flowstack-ui/brick";
// or
import { Surface } from "@flowstack-ui/brick/surface";

import "@flowstack-ui/brick/styles.css";

The complete stylesheet above is the recommended default. For a measured route-aware build, replace it with the shared foundation and this component's stylesheet:

tsx
import "@flowstack-ui/brick/styles/core.css"; // once at the application root
import "@flowstack-ui/brick/styles/surface.css";

Add the modular stylesheet for every other Brick component the route renders. Do not combine modular styles with styles.css or tokens.css.

Public exports are Surface, SurfaceRoot, SurfaceMedia, SurfaceScrim, SurfaceContent, their prop types, SurfaceScrimStrength, SurfaceScrimDirection, SurfaceProps, SurfaceElement, SurfaceLevel, SurfaceElevation, SurfaceRadius, SurfaceInset, and SurfaceTone.

Quick start

tsx
<Surface as="section" bordered inset="md" level="subtle">
  <VStack gap="3">
    <Text as="h2" variant="title-md">Release readiness</Text>
    <Text>All required evidence is available.</Text>
  </VStack>
</Surface>

Visual recipes and states

tone="neutral" lets level select a semantic background layer. tone="accent" selects the paired accent-solid background and foreground for branded or conversion planes, not status messaging. Border, elevation, radius, and inset remain independent so consumers can change only the visual dimension they intend to demonstrate. Surface has no hover, focus, selected, disabled, loading, validation, typography, or motion state.

Elevations are deliberately restrained: low separates nearby content, medium separates a stronger floating region, and high is reserved for the strongest non-modal separation. In forced colors, elevated or bordered surfaces use a system border instead of relying on shadow alone.

Examples

Full-width paint with measured content

tsx
<Surface as="section" level="subtle">
  <Container>
    <VStack gap="4">Measured section content</VStack>
  </Container>
</Surface>

Nested semantic levels

tsx
<Surface inset="lg" level="canvas">
  <Surface bordered inset="md" level="raised" elevation="low">
    Focused workspace
  </Surface>
</Surface>

Decorative media behind content

tsx
<Surface as="section" radius="none">
  <Surface.Media>
    <ImageRoot src="/workspace.jpg" fill fit="cover">
      <ImageContent alt="" width={1200} height={675} />
    </ImageRoot>
  </Surface.Media>
  <Surface.Scrim direction="inline-start" strength="strong" />
  <Surface.Content>
    <Container>
      <VStack gap="3">Foreground content</VStack>
    </Container>
  </Surface.Content>
</Surface>

Background media is decorative. Keep meaningful images and controlled video in normal document content. The media owner retains loading, fitting, playback, poster, caption, and reduced-motion policy. Scrim improves contrast but does not replace contrast verification across every media state. When layered parts are used, place all foreground children inside Content.

Public contract

API

Start with the public parts and root options below. Components with multiple parts separate each area into its own named subsection.

PropValuesDefault
asdiv, section, article, aside, nav, main, header, footer, form, lidiv
asChildbooleanfalse
levelcanvas, base, subtle, raisedbase
toneneutral, accentneutral
borderedbooleanfalse
elevationnone, low, medium, highnone
radiusnone, subtle, surfacesurface
insetnone, sm, md, lg, xl, 2xl, or a responsive valuenone
slotstringsurface
childrenReactNodeoptional

Scrim

PropValuesDefault
strengthsoft, medium, strongmedium
directionuniform, inline-start, inline-end, block-start, block-enduniform
slotstringsurface-scrim

Media and Content accept authored children, native div attributes, class, style, slot, and refs. Media and Scrim are always aria-hidden and ignore pointer interaction. Scrim accepts no children.

Scrim strength is deliberately perceptual rather than a small numeric step. It changes the starting paint intensity and, for directional scrims, the gradient reach. Themes normally set only --brick-surface-scrim-color; Brick keeps the relative soft, medium, and strong ladder consistent.

Native global/ARIA/data attributes, events, className, style, and an HTMLElement ref pass through.

With asChild, Surface applies its paint recipes to exactly one existing non-Fragment element without adding a wrapper. It preserves the child's host, class, style, handlers, and ref while composing the forwarded Surface ref.

Shared responsibility

Accessibility

Surface adds no role, accessible name, landmark, focus target, or keyboard behavior. Choose as for the actual document structure and name repeated landmarks when required. Background and foreground variables change together, and forced-colors styling preserves visible boundaries.

Responsive behavior

Surface follows the size of its parent and uses logical padding. inset accepts Brick's mobile-first responsive value shape with required initial and optional sm, md, lg, and xl overrides:

tsx
<Surface inset={{ initial: "lg", xl: "2xl" }}>
  Wide promo-panel content
</Surface>

Use xl and 2xl for page-sized panels, heroes, and split layouts. Ordinary cards and local panels should normally stay within sm through lg. Surface does not own viewport height, safe areas, columns, content measure, or the choice of when a product changes layout.

Stable visual contract

Styling and tokens

Customization

Use recipes first, then override selected variables on a deliberate instance:

tsx
<Surface
  bordered
  inset="md"
  style={{
    "--brick-surface-background": "color-mix(in srgb, Canvas, rebeccapurple 8%)",
    "--brick-surface-border-color": "rebeccapurple",
  }}
>
  Customized region
</Surface>

This escape hatch does not make arbitrary values part of the recipe API.

Tokens and CSS hooks

Stable hooks are .brick-surface, [data-slot="surface"], data-slot, data-tone, data-level, data-bordered, data-elevation, data-radius, and data-inset. Responsive inset adds only the authored data-inset-sm, data-inset-md, data-inset-lg, and data-inset-xl overrides.

Public variables:

  • --brick-surface-background
  • --brick-surface-foreground
  • --brick-surface-border-color
  • --brick-surface-border-width
  • --brick-surface-elevation-none
  • --brick-surface-elevation-low
  • --brick-surface-elevation-medium
  • --brick-surface-elevation-high
  • --brick-surface-shadow
  • --brick-surface-radius
  • --brick-surface-padding
  • --brick-surface-inset-none
  • --brick-surface-inset-sm
  • --brick-surface-inset-md
  • --brick-surface-inset-lg
  • --brick-surface-inset-xl
  • --brick-surface-inset-2xl
  • --brick-surface-scrim-color
  • --brick-surface-scrim-soft
  • --brick-surface-scrim-medium
  • --brick-surface-scrim-strong
  • --brick-surface-scrim-gradient-stop
  • --brick-surface-scrim-gradient-stop-soft
  • --brick-surface-scrim-gradient-stop-medium
  • --brick-surface-scrim-gradient-stop-strong

Advanced reference

Open these details only when you need to inspect DOM ownership, native forwarding, or lower-level composition.

Maintainer resources

Tests, playground evidence, source notes, and release history remain available without crowding the plug-and-play guide.