Back to Onyx

Content

web/lib/opal/src/layouts/content/README.md

3.3.04.8 KB
Original Source

Content

Import: import { Content, type ContentProps } from "@opal/layouts";

A two-axis layout component for displaying icon + title + description rows. Routes to an internal layout based on the sizePreset and variant combination.

Two-Axis Architecture

sizePreset — controls sizing (icon, padding, gap, font)

ContentXl presets (variant="heading")

PresetIconIcon paddingmoreIcon1mI1 paddingmoreIcon2mI2 paddingTitle fontLine-height
headline2rem (32px)p-0.5 (2px)1rem (16px)p-0.5 (2px)2rem (32px)p-0.5 (2px)font-heading-h22.25rem (36px)
section1.5rem (24px)p-0.5 (2px)0.75rem (12px)p-0.5 (2px)1.5rem (24px)p-0.5 (2px)font-heading-h31.75rem (28px)

ContentLg presets (variant="section")

PresetIconIcon paddingGapTitle fontLine-height
headline2rem (32px)p-0.5 (2px)0.25rem (4px)font-heading-h22.25rem (36px)
section1.25rem (20px)p-1 (4px)0remfont-heading-h3-muted1.75rem (28px)

ContentMd presets

PresetIconIcon paddingIcon colorGapTitle fontLine-height
main-content1rem (16px)p-1 (4px)text-040.125rem (2px)font-main-content-emphasis1.5rem (24px)
main-ui1rem (16px)p-0.5 (2px)text-030.25rem (4px)font-main-ui-action1.25rem (20px)
secondary0.75rem (12px)p-0.5 (2px)text-040.125rem (2px)font-secondary-action1rem (16px)

Icon container height (icon + 2 x padding) always equals the title line-height.

variant — controls structure / layout

variantDescription
headingIcon on top (flex-col) — ContentXl
sectionIcon inline (flex-row) — ContentLg or ContentMd
bodyBody text layout — ContentSm

Valid Combinations -> Internal Routing

sizePresetvariantRoutes to
headline / sectionheadingContentXl (icon on top)
headline / sectionsectionContentLg (icon inline)
main-content / main-ui / secondarysectionContentMd
main-content / main-ui / secondarybodyContentSm

Invalid combinations (e.g. sizePreset="headline" + variant="body") are excluded at the type level.

Props

PropTypeDefaultDescription
sizePresetSizePreset"headline"Size preset (see tables above)
variantContentVariant"heading"Layout variant (see table above)
iconIconFunctionComponentOptional icon component
titlestring(required)Main title text
descriptionstringOptional description below the title
editablebooleanfalseEnable inline editing of the title
onTitleChange(newTitle: string) => voidCalled when user commits an edit
moreIcon1IconFunctionComponentSecondary icon in icon row (ContentXl only)
moreIcon2IconFunctionComponentTertiary icon in icon row (ContentXl only)

Internal Layouts

ContentXl

For headline / section presets with variant="heading". Icon row on top (flex-col), supports moreIcon1 and moreIcon2 in the icon row. Description is always font-secondary-body text-text-03.

ContentLg

For headline / section presets with variant="section". Always inline (flex-row). Description is always font-secondary-body text-text-03.

ContentMd

For main-content / main-ui / secondary presets. Always inline. Both icon and description are optional. Description is always font-secondary-body text-text-03.

Usage Examples

tsx
import { Content } from "@opal/layouts";
import SvgSearch from "@opal/icons/search";

// ContentXl — headline, icon on top
<Content
  icon={SvgSearch}
  sizePreset="headline"
  variant="heading"
  title="Agent Settings"
  description="Configure your agent's behavior"
/>

// ContentXl — with more icons
<Content
  icon={SvgSearch}
  sizePreset="headline"
  variant="heading"
  title="Agent Settings"
  moreIcon1={SvgStar}
  moreIcon2={SvgLock}
/>

// ContentLg — section, icon inline
<Content
  icon={SvgSearch}
  sizePreset="section"
  variant="section"
  title="Data Sources"
  description="Connected integrations"
/>

// ContentMd — with icon and description
<Content
  icon={SvgSearch}
  sizePreset="main-ui"
  title="Instructions"
  description="Agent system prompt"
/>

// ContentMd — title only (no icon, no description)
<Content
  sizePreset="main-content"
  title="Featured Agent"
/>

// Editable title
<Content
  icon={SvgSearch}
  sizePreset="headline"
  variant="heading"
  title="My Agent"
  editable
  onTitleChange={(newTitle) => save(newTitle)}
/>