Section Frame

Decorative wrapper that adds subtle border lines around a rounded inset panel. The hairlines mark the section edges; the tinted panel floats inside them with 16px of breathing room and 14px rounded corners.

Default (All Lines)

Framed Section

Content inside the frame with subtle borders and background.

tsx
<SectionFrame>
  <div className="py-16 px-4">
    <h2>Framed Section</h2>
    <p>Content inside the frame.</p>
  </div>
</SectionFrame>

Horizontal Lines Only

Horizontal Lines Only

Top and bottom lines without side borders.

tsx
<SectionFrame showSides={false}>
  <div>Content</div>
</SectionFrame>

Top Line Only

Top Line Only

Single top divider line.

tsx
<SectionFrame showBottom={false} showSides={false}>
  <div>Content</div>
</SectionFrame>

No Background

No Background

Frame lines without the subtle background tint.

tsx
<SectionFrame showBackground={false}>
  <div>Content</div>
</SectionFrame>

Full Bleed

Full Bleed

Surface spans the viewport with square corners and no hairlines. Children keep their own max-width containers.

tsx
<SectionFrame fullBleed>
  <div>Content</div>
</SectionFrame>

Full Bleed With a Bottom Line

Hairlines are opt-in under fullBleed. Asked for, they land on the surface’s own edge rather than outside a panel — how the case-study hero closes off its band.

Band with a closing edge

One hairline, flush with the bottom of the surface.

tsx
<SectionFrame fullBleed showBottom>
  <div>Content</div>
</SectionFrame>

Light Surfaces

A light plane inside the dark page. Re-points the generic colour tokens for its subtree, so section content adapts without any component opting in. white is the same ladder on a brighter ground.

Paper

Warm cream ground.

White

Brighter ground, same token ladder.

tsx
<SectionFrame surface="paper">…</SectionFrame>
<SectionFrame fullBleed surface="white">…</SectionFrame>

// Dark island inside a light section (media zones, CTA cards)
<div className="surface-ink">…</div>

Ink Panel on a Light Ground

The house pattern is light grounds with dark content: panel="ink" keeps the inset panel dark so cards and sections look the same here as on the dark pages. Framed variant only — fullBleed has no panel.

Ink Panel

Dark panel floating on a cream ground — the section keeps its original dark treatment.

tsx
<SectionFrame surface="paper" panel="ink">
  <AboutSection />
</SectionFrame>

Design Details

Horizontal Lines

Span full viewport width (edge to edge)

Vertical Lines & Background

Aligned to the page container (--container-page) with its gutter

Line Color

var(--border-subtle) — ~8% foreground opacity. Matches other subtle borders across the system (dividers, card outlines).

Background Panel

var(--surface-section), inset by var(--spacing-4) (16px) from each hairline with var(--radius-2xl) (14px) rounded corners.

Internal Content Padding

Children are wrapped in .page-container with px-4 sm:px-6 lg:px-8 so section content sits inside the rounded panel with consistent breathing room (16px mobile, 24px tablet, 32px desktop) without each consumer having to bump its own padding.

Aligning a Card to the Panel

.panel-container

Two different insets are in play inside a frame. The panel sits var(--spacing-4) (16px) in from the page container, while section content sits at the wider px-4 sm:px-6 lg:px-8 scale so it clears the panel's rounded corners. A standalone card that should read as a sibling of the panels — rather than as content inside one — has to use the panel's inset, or it lands 16px narrow on each side.

.panel-container (globals.css) is that container: still --container-page, but with a fixed 16px inline padding at every breakpoint, because the panel's inset doesn't change responsively. CTASection uses it to line the CTA card up with the edges of the panels above it.

tsx
<div className="panel-container">
  <CTACard {...props} />
</div>

Common Patterns

Section Divider

<SectionFrame showBottom={false} showSides={false}>

Full Frame (Technical Look)

<SectionFrame> — All props default to true

Content Band

<SectionFrame showSides={false}>

Props

PropTypeDefaultDescription
showTopbooleantrue (framed) / false (fullBleed)Show top border line. Under fullBleed the lines are opt-in, and sit flush on the surface edge.
showBottombooleantrue (framed) / false (fullBleed)Show bottom border line. Under fullBleed the lines are opt-in, and sit flush on the surface edge.
showSidesbooleantrueShow left and right border lines
showBackgroundbooleantrueShow subtle background tint
fullBleedbooleanfalseSurface spans the viewport with square corners and no hairlines
surface'default' | 'paper' | 'white''default'Light ground for the section — "paper" is warm cream, "white" the same stock a shade brighter
panel'default' | 'ink''default'Framed variant only. "ink" keeps the inset panel dark on a light ground
classNamestring-Additional CSS classes
children*ReactNode-Section content

Import

tsx
import { SectionFrame } from '@/components/ui/SectionFrame'