ContainerHeader

Updated: Sep 24, 2026
ContainerHeader is the title treatment for a region of content: a card, a panel, a container-owned section. It renders a title, an optional subtitle, and at most one leading visual — an icon or an Avatar with its badge and status options. It is display-only and reports itself as a heading.
Use ContainerHeader inside the content region it titles, typically within a Container or Card. It does not paint a surface. Header serves a different role: Page configures and renders that fixed, page-level route header.

Usage

import { Container, ContainerHeader, StatusIndicatorType } from '@wearables-ui-toolkit/mrbd';

type Thread = {
  name: string;
  statusLabel: string;
  photoUrl?: string;
  isActive: boolean;
};

export function ThreadCard({ thread }: { thread: Thread }) {
  return (
    <Container>
      <ContainerHeader
        title={thread.name}
        subtitle={thread.statusLabel}
        avatarSrc={thread.photoUrl}
        avatarAlt={thread.name}
        statusIndicator={thread.isActive ? StatusIndicatorType.ACTIVE : undefined}
      />
      {/* section content */}
    </Container>
  );
}
With a leading icon instead of an identity:
<ContainerHeader
  title={sectionTitle}
  subtitle={sectionSubtitle}
  icon={sectionIcon}
/>;
Text only, when the region needs a title but no visual:
<ContainerHeader title="Recently deleted" subtitle="Kept for 30 days" />;
The header fills the width of its parent and supplies its own internal spacing, so give the region around it structure with tokens rather than padding the header itself:
.section {
  display: flex;
  flex-direction: column;
  gap: var(--uit-spacing-small);
}

Props

The full prop type is ContainerHeaderProps. It extends HTMLAttributes<HTMLDivElement>, so standard DOM attributes — including data-* — are forwarded to the root element, and the component forwards its ref there too. There is no children slot: the header renders only the props below.
PropTypeDefaultDescription
title
string
—
Title text. Rendered in the emphasized label appearance, on one line, ellipsized when it does not fit.
subtitle
string
—
Subtitle text. Rendered in the secondary metadata appearance, on one line, ellipsized when it does not fit.
icon
IconSource
—
Leading icon. Rendered only when no avatar is present.
avatarSrc
string
—
Avatar image URL. Supplying it makes the leading visual an avatar.
avatarPrimaryContent
ReactNode
—
Custom node for the avatar’s primary slot. Also makes the leading visual an avatar.
avatarAlt
string
'Avatar'
Alt text passed to the avatar. The default is an English fallback only.
statusIndicator
StatusIndicatorType
—
Status dot on the avatar. Only renders, and only affects the accessible name, when an avatar is present.
statusIndicatorIcon
IconSource
—
Glyph drawn over the status dot. Only renders when statusIndicator is set.
primaryImageShape
AvatarShape
—
Clip shape of the avatar’s primary image.
placeholderStyle
PlaceholderStyle
—
Placeholder treatment used by the avatar when it has no image or content.
avatarBadgeSrc
string
—
Image URL for the avatar’s badge slot.
avatarBadgeContent
ReactNode
—
Custom node for the avatar’s badge slot.
className
string
''
Additional class on the root element.
style
CSSProperties
{}
Inline styles applied to the root element.
aria-label
string
title, subtitle, and the avatar’s status label joined with commas
Replaces the composed accessible name of the heading.

Types and enums

ContainerHeader defines no enums of its own. Its avatar props take the enums exported alongside Avatar, which you import from the package root:
import {
  AvatarShape,
  ContainerHeader,
  PlaceholderStyle,
  StatusIndicatorType,
} from '@wearables-ui-toolkit/mrbd';
  • AvatarShape — CIRCLE, ROUNDED_RECTANGLE.
  • PlaceholderStyle — AVATAR, IMAGE.
  • StatusIndicatorType — ACTIVE, INACTIVE, NOTIFICATION, UNREAD, POSITIVE, NEGATIVE, WARNING, CAUTION.
icon and statusIndicatorIcon take an IconSource, the same union IconImage accepts: an inline vector description, a { uri } reference, or a bare URL string.

Behavior

Leading visual precedence. The header shows exactly one leading visual, or none. An avatar — signalled by avatarSrc or avatarPrimaryContent — wins; the icon renders only when there is no avatar. With neither, the text block starts further in, so text-only headers still align with the rest of the region.
Avatar configuration. The embedded avatar renders at the small avatar size and accepts the shape, placeholder, status, and badge props listed above. Everything else about the avatar is component-owned. statusIndicator and statusIndicatorIcon only reach the avatar, so they do nothing on an icon-only or text-only header; statusIndicatorIcon additionally needs statusIndicator, because the dot is the glyph’s backdrop. The avatar clips to a circle unless primaryImageShape says otherwise.
Icons. An inline vector source renders as svg and takes the primary icon color; a URL source renders as a mask tinted to the same color, unless the source sets tinted: false, which renders the asset in full color. The icon slot is component-owned, so preserve its size.
Text. Title and subtitle are each single-line and ellipsized; the whole text block is omitted when both are empty, which leaves a header that is only its leading visual. Title uses the emphasized label appearance in the primary text color; subtitle uses the metadata appearance in the secondary text color, which composites with a lighten blend so it lifts against the material behind it.
Layout. The root is a full-width flex row with vertically centered content and a component-owned minimum height. All spacing lives on the internal slots, so the header has no outer padding of its own and paints no background. The minimum height holds even for a text-only header, which keeps a column of sections aligned.

Accessibility

  • The root reports role="heading" at level 2, with an accessible name built by joining title, subtitle, and — when an avatar is present — the label for statusIndicator, in that order, with commas.
  • With no title, subtitle, or avatar status, the heading has no accessible name. Give it a title, or pass aria-label.
  • Passing aria-label replaces that composed name entirely. Do that only when the visible text is not a usable label.
  • The embedded avatar is hidden from assistive technology, so the identity is announced once, through the heading. avatarAlt therefore does not reach the accessibility tree here — put the name in title.
  • The header is not interactive and takes no focus; put actions in the region’s content instead.
  • Level 2 is fixed. If the surrounding document needs a different level, express the hierarchy with your own heading element instead.
  • Use it for the title row of a card, panel, or container-owned section.
  • Keep the title and subtitle short because each is clipped to one line.
  • Use the avatar props when the section is about a person, group, or app.
  • Put the region’s real name in title so the heading and visible text agree.

Avoid

  • Configure Header through Page for the page-level route header.
  • Use ListItem for a focusable row in VerticalList, and ordinary typography for a simple section label.
  • Choose an avatar or icon because both do not render together.
  • Pair statusIndicator with an avatar; there is no status dot without one.
  • Place ContainerHeader inside the material region it titles rather than wrapping the header in another rounded surface.