Surface

Elevated container with a variant ladder.

The Surface component, running in the example app.

An elevated container, with a variant ladder for building hierarchy.

Nest the variants: each level sits one step further from the page background than the one around it.

Both the fill and the corner radius follow the active theme. The variants resolve to themed surface tokens and rounded-3xl resolves through the per-theme radius scale, so the same Surface is a 24px corner under Panel and a 32px one under Moon without knowing about either.

For a surface with a header, body and footer, use Card.

Installation

Surface ships with the library — no separate install.

import { Surface, Text } from 'panelui-native';

Or copy the source into your project, to own and edit it:

npx panelui-cli@latest add surface

Usage

<Surface>
  <Text weight="medium">Account</Text>

  <Surface variant="secondary" className="mt-3">
    <Text size="sm" muted>Signed in as khalid@example.com</Text>

    <Surface variant="tertiary" className="mt-3">
      <Text size="xs" muted>Session expires in 12 days</Text>
    </Surface>
  </Surface>
</Surface>

Examples

Nested hierarchy

The variants form a ladder, not a palette: each step sits one level further from the background, so nesting them builds depth without naming a colour.

<Surface>
  <Text weight="medium">Account</Text>
  <Surface variant="secondary" className="mt-3">
    <Text size="sm" muted>Signed in as khalid@example.com</Text>
    <Surface variant="tertiary" className="mt-3">
      <Text size="xs" muted>Session expires in 12 days</Text>
    </Surface>
  </Surface>
</Surface>

Bordered and elevated

A surface the same colour as the page needs a hairline to read as its own plane. elevated adds a soft shadow that lifts it off the page — off by default, because a nested surface takes its depth from its fill.

Surface — Bordered and elevated.
<Surface bordered>…</Surface>
<Surface elevated>…</Surface>
<Surface bordered elevated>…</Surface>

Padding scale

padding scales the inner spacing. none is for a surface wrapping a bled image or a chart, where the content reaches the edge.

Surface — Padding scale.
<Surface padding="none">…</Surface>
<Surface padding="sm">…</Surface>
<Surface padding="default">…</Surface>
<Surface padding="lg">…</Surface>

As a stat card

A bordered surface with generous padding is the whole card for a metric.

Surface — As a stat card.
<Surface bordered padding="lg" className="flex-1">
  <Text size="xs" muted className="uppercase tracking-wider">Revenue</Text>
  <Text size="xl" weight="semibold" className="mt-1">$24.8k</Text>
</Surface>

Variants

variant

  • default (default)
  • secondary
  • tertiary
  • transparent
<Surface variant="default" className="p-4">Default</Surface>
<Surface variant="secondary" className="p-4">Secondary</Surface>
<Surface variant="tertiary" className="p-4">Tertiary</Surface>
<Surface variant="transparent" className="p-4">Transparent</Surface>

padding

  • none
  • sm
  • default (default)
  • lg
<Surface padding="none">…</Surface>
<Surface padding="sm">…</Surface>
<Surface padding="default">…</Surface>
<Surface padding="lg">…</Surface>

bordered

  • true
<Surface bordered="true">…</Surface>

elevated

  • true
<Surface elevated="true">…</Surface>

API Reference

Surface

PropTypeDefaultDescription
classNamestring
borderedbooleanA hairline border. A surface the same colour as what it sits on needs one to read as a distinct plane rather than dissolving into the background.
elevatedbooleanA soft shadow lifting the surface off the page. Off by default because a nested surface reads its depth from its fill, not from a shadow it would only cast onto its parent.
padding'none' | 'sm' | 'default' | 'lg'defaultInner spacing. none is for a surface wrapping a bled image or a chart.

Every part also accepts the underlying React Native props (ViewProps or TextProps) and a className for Tailwind utilities.

Notes

borderCurve: 'continuous' is applied on iOS, giving Apple's squircle corner rather than a circular arc — visibly smoother at this radius. Android ignores it.

Use variant="transparent" when you want the padding and radius without a fill.

Public exports

Values: Surface

Types: SurfaceProps

On this page