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.
<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.
<SectionFrame showSides={false}>
<div>Content</div>
</SectionFrame>Top Line Only
Top Line Only
Single top divider line.
<SectionFrame showBottom={false} showSides={false}>
<div>Content</div>
</SectionFrame>No Background
No Background
Frame lines without the subtle background tint.
<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.
<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.
<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.
<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.
<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.
<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 trueContent Band
<SectionFrame showSides={false}>Props
| Prop | Type | Default | Description |
|---|---|---|---|
showTop | boolean | true (framed) / false (fullBleed) | Show top border line. Under fullBleed the lines are opt-in, and sit flush on the surface edge. |
showBottom | boolean | true (framed) / false (fullBleed) | Show bottom border line. Under fullBleed the lines are opt-in, and sit flush on the surface edge. |
showSides | boolean | true | Show left and right border lines |
showBackground | boolean | true | Show subtle background tint |
fullBleed | boolean | false | Surface 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 |
className | string | - | Additional CSS classes |
children* | ReactNode | - | Section content |
Import
import { SectionFrame } from '@/components/ui/SectionFrame'