Hero
betav0.1.0A page-level introduction surface built on Paper: an elevation-1 panel with two blurred brand accents, a header row and a body separated by a rule. Hero is a container, not a layout — the header and the body are children the host composes, both optional, each taking arbitrary content. What the node pins (surface, radius, border, layer, spacing) is a token-backed default the host can move through props: `elevation` and `padding` pass through to Paper, `gap` sets the gutter; the accents are always drawn. Compose it with `HeroHeader` (icon slot, title column, actions cluster) and `HeroBody` (separator and content). No MUI counterpart: new.
Variants
The Figma composition
Node 7909:12676 (dark) and 7929:13938 (light): thumbnail, title and subtitle, an actions cluster, a separator, and two statistics in the body. Layer 1, 24px padding, 16px gutter, two blurred brand accents; the thumbnail is a Paper one layer up.
Title
Subtitle
Disconnected banner
Node 7703:26617: header only — a bare glyph, a title in the alert text tone, one line and one primary button. No body, so no rule.
XTM Hub is disconnected
Please connect your product so you can deploy resources
Scenario page
Node 7930:14475: chips under the title, seven controls in the actions cluster, three statistics and two buttons pushed to the far end of the body (className='justify-between'). The node draws the second body button in the alert tone, which Button has no variant for; it is rendered secondary here.
EASM Scenario
HighAttack scenarioNot scheduledEntity page
Node 7929:13941: a brand-coloured label above the title in the title column, two statistics in the body.
Text
Wks-paris-01.corp.local
Dense
The entity page at padding={16} and gap={8}: the same parts and the same surface, half the air.
Text
Wks-paris-01.corp.local
Body only
A Hero with no header. separator={false} drops the rule that would otherwise sit under nothing.
Examples
<Hero>
<HeroHeader
icon={<Thumbnail elevation={2}><Icon name="server" size={24} /></Thumbnail>}
action={<Button>Action</Button>}
>
<Text as="h1" variant="title-md" className="m-0">Title</Text>
<Text as="p" variant="content-compact" className="m-0 text-default-secondary">Subtitle</Text>
</HeroHeader>
<HeroBody>
<HeroStat icon="radar" severity="medium" value="5" label="Stimuli" />
</HeroBody>
</Hero>// Header only (node 7703:26617): a bare glyph, no body, no separator.
<Hero>
<HeroHeader icon={<Icon name="unlink" size={24} />} action={<Button>Connect product to XTM Hub</Button>}>
<Text as="h1" variant="title-md" className="m-0 text-alert">XTM Hub is disconnected</Text>
<Text as="p" variant="content-compact" className="m-0 text-default-secondary">Please connect your product so you can deploy resources</Text>
</HeroHeader>
</Hero>// Dense.
<Hero padding={16} gap={8}>
<HeroHeader>
<Text as="h2" variant="title-xs" className="m-0">Detection coverage</Text>
</HeroHeader>
<HeroBody className="flex-col">
<Text as="p" variant="content-base" className="m-0">80% of injects detected.</Text>
</HeroBody>
</Hero>// One layer up, for a Hero nested in a layer-1 surface.
<Hero elevation={2}>
<HeroHeader>
<Text as="h2" variant="title-xs" className="m-0">Coverage</Text>
</HeroHeader>
</Hero>Props
| Prop | Type |
|---|---|
elevation | 0 | 1 | 2 | 3 — passed through to Paper. Default 1, the layer the node renders in both modes. |
padding | 0 | 8 | 16 | 24 | 32 (px) — passed through to Paper. Default 24. |
gap | 0 | 8 | 16 | 24 | 32 (px) — the gutter between header and body, and the body's inset below its separator. Default 16. |
className | string — merged onto the root through cn(). |
children | ReactNode — normally a HeroHeader and/or a HeroBody, but any content is accepted. |
HeroHeader.icon | ReactNode — leading slot. The node draws a Thumbnail one layer up (elevation 2) holding a 24px Icon. |
HeroHeader.action | ReactNode — trailing slot: any number of controls, 8px apart. |
HeroHeader.children | ReactNode — the title column. |
HeroBody.separator | boolean — the rule above the content. Default true; pass false for a body with no header. |
HeroBody.children | ReactNode — the content row (a column with className="flex-col"). |
Accessibility
Ratios are the computed output of pnpm check:contrast on the four elevation layers and on the brand accent wash, in both modes. The root is a Paper: a plain div with no role, no tabIndex and no keyboard behaviour of its own; supply role="region" and aria-labelledby on the root when the Hero is a landmark of the page. The accents are decorative — aria-hidden, pointer-events none, painted below every child — and carry no meaning (1.1.1, 1.4.1). The separator is decorative and non-gating, the same ruling as Paper's border. Hero paints no text: the title level is the host's (a title-md Text with the heading tag the page outline needs), so no level is invented (1.3.1). The only focusable elements are the controls the host passes to the header action slot, each bringing its own focus ring (2.1.1, 2.4.7). The root clips overflow, so an inline overlay drawn inside it is cut at the edge: every library overlay portals to body and is unaffected.