web/lib/opal/src/layouts/README.md
Import: import { Content, ContentAction, IllustrationContent } from "@opal/layouts";
Layout primitives for composing content blocks. These components handle sizing, font selection, icon alignment, and optional inline editing — things that are tedious to get right by hand and easy to get wrong.
| Component | Description | Docs |
|---|---|---|
Content | Icon + title + description row. Routes to an internal layout (ContentXl, ContentLg, ContentMd, or ContentSm) based on sizePreset and variant. | Content README |
ContentAction | Wraps Content in a flex-row with an optional rightChildren slot for action buttons. Adds padding alignment via the shared SizeVariant scale. | ContentAction README |
IllustrationContent | Center-aligned illustration + title + description stack for empty states, error pages, and placeholders. | IllustrationContent README |
import { Content, ContentAction, IllustrationContent } from "@opal/layouts";
import { Button } from "@opal/components";
import SvgSettings from "@opal/icons/settings";
import SvgNoResult from "@opal/illustrations/no-result";
// Simple heading
<Content
icon={SvgSettings}
title="Account Settings"
description="Manage your preferences"
sizePreset="headline"
variant="heading"
/>
// Label with tag
<Content
icon={SvgSettings}
title="OpenAI"
description="GPT"
sizePreset="main-content"
variant="section"
tag={{ title: "Default", color: "blue" }}
/>
// Row with action button
<ContentAction
icon={SvgSettings}
title="Provider Name"
description="Some description"
sizePreset="main-content"
variant="section"
padding="lg"
rightChildren={
<Button icon={SvgSettings} prominence="tertiary" />
}
/>
// Empty state with illustration
<IllustrationContent
illustration={SvgNoResult}
title="No results found"
description="Try adjusting your search or filters."
/>
Content)Content uses a two-axis system:
sizePreset — controls sizing tokens (icon size, padding, gap, font, line-height).variant — controls structural layout (icon placement, description rendering).Valid preset/variant combinations are enforced at the type level via a discriminated union. See the Content README for the full matrix.
ContentAction)ContentAction uses the same SizeVariant scale (lg, md, sm, xs, 2xs, fit) defined in @opal/shared that powers Interactive.Container and Button. This ensures that padding on content rows aligns with adjacent interactive elements at the same size.
From @opal/layouts:
// Components
Content
ContentAction
IllustrationContent
// Types
ContentProps
ContentActionProps
IllustrationContentProps
SizePreset
ContentVariant
These are not exported — Content routes to them automatically:
| Layout | Used when | File |
|---|---|---|
ContentXl | sizePreset is headline or section with variant="heading" | content/ContentXl.tsx |
ContentLg | sizePreset is headline or section with variant="section" | content/ContentLg.tsx |
ContentMd | sizePreset is main-content, main-ui, or secondary with variant="section" | content/ContentMd.tsx |
ContentSm | variant="body" | content/ContentSm.tsx |