Skip to content

Components · Layout

SectionCard

A titled card for one section: header with actions and "View all", body, footer, and built-in loading, empty and error states.

@rookcom/monarch-react/patternsComponent

Header actions, "View all" and footer

Open tasks

Assigned to you this week.

3

  • Draft the launch brief
  • Review pricing copy
  • Book the kickoff call

Usage examples

Loading, empty and error states

Collapsible and danger tone

Purpose

Puts one section of a dashboard, detail or settings page in a card: a SectionHeader (title, description, meta, actions, "View all" link), the body, an optional footer, and the loading, empty and error states every data-backed section needs. It can be collapsible.

Use when

  • Dashboard widgets and detail-page panels that load their own data.
  • A titled card with header actions or a "View all" link.
  • A table or list that runs edge to edge inside a titled card (flush).

Avoid when

  • A group of settings rows with Save/Discard: use SettingsSection.
  • An unboxed section title: use SectionHeader.
  • A plain surface without a title: use Card.

Design principles

  • Always a labelled region: the heading names the <section>, so landmark navigation lists it.
  • One state at a time: the body shows the content, a skeleton, an empty state or an error, never two.
  • Refreshing is not loading: busy keeps the content and shows a spinner by the title.
  • The heading level follows the page outline (headingLevel), never the visual size.

API reference

import { SectionCard } from '@rookcom/monarch-react/patterns';
ExportKindRenderingRoot class
SectionCardcomponentclient.mn-section-card-

Renders <section aria-labelledby> and forwards its ref; native attributes pass through.

The header is a SectionHeader without children; title, description, meta, actions, link and headingLevel are passed to it.

States reuse LoadingState, EmptyState and ErrorState (compact). Pass empty for a custom empty state with actions.

Exported from @rookcom/monarch-react/patterns.

Generated from the TypeScript declarations of packages/react/src/components/layout/section-card.

Properties

SectionCard

A titled card for one section of a page or dashboard: header with actions and a "View all" link, body, optional footer, and built-in loading, empty and error states. Optionally collapsible.

PropTypeDescription
title requiredReactNodeThe section title, rendered as a heading that labels the section.
actionsReactNodeButtons or a menu at the end of the header.
busybooleanThe content is refreshing in place: a spinner after the title and `aria-busy` on the section, while the current content stays visible.
childrenReactNode
classNamestring
collapsiblebooleanThe title becomes a disclosure button that shows and hides the body.
defaultOpenbooleanInitial expanded state (uncontrolled). Default `true`.
descriptionReactNodeA sentence under the title explaining the section.
emptyReactNodeReplaces the default empty state (for example an EmptyState with actions).
emptyDescriptionReactNode
emptyTitleReactNodeTitle of the default empty state. Default "Nothing here yet".
errorDescriptionReactNode
errorTitleReactNodeTitle of the error state. Default "This section didn’t load".
flushbooleanNo body padding, for a table or list that runs edge to edge.
footerReactNodeContent of the footer bar: secondary actions, a summary, a pager.
headingIdstringId for the heading. Generated when omitted.
headingLevel"h2" | "h3" | "h4" | "h5" | "h6"Heading element. Default `h2`.
iconReactNodeDecorative icon before the title. Hidden from assistive technology.
idstring
linkReactNodeA trailing "View all" link (SectionHeaderLink), after `actions`.
loadingLabelstringAnnounced while loading. Default "Loading".
loadingVariantLoadingStateVariantSkeleton shape while loading. Default `rows`.
metaReactNodeA short secondary line: a count, a date range, "Updated 5 min ago".
onOpenChange((open: boolean) => void)
onRetry(() => void)Shows a retry button in the error state.
openbooleanExpanded state (controlled). Only with `collapsible`.
retryingbooleanThe retry is in flight.
stateSectionCardStateWhat the body shows: the children (`ready`, default), a skeleton (`loading`), an EmptyState (`empty`) or an ErrorState (`error`). Exposed as `data-state`.
tone"danger" | "default"`danger` for a destructive zone (danger border and title). Exposed as `data-tone`.

Variants

PropValuesDescription
state'ready''loading''empty''error'What the body shows. Exposed as data-state.
tone'default''danger'danger uses the danger border and title colour. Exposed as data-tone.
flush'false''true'Removes the body padding and adds a divider, for tables and lists. data-flush.
collapsible'false''true'The title becomes a disclosure button. data-collapsible, data-open.

States

StateExposed asBehaviour
Readydata-state="ready"Shows the children.
Loadingdata-state="loading", aria-busyA skeleton (loadingVariant) with a polite loadingLabel announcement.
Emptydata-state="empty"empty, or a compact EmptyState from emptyTitle and emptyDescription.
Errordata-state="error"A compact ErrorState with errorTitle, errorDescription and a retry button when onRetry is given.
Busyaria-busyRefreshing in place: a spinner after the title; content stays.
Collapseddata-open absentThe body and footer are hidden; the header stays.

Interaction behaviour

  • Header actions and the "View all" link behave as usual.
  • With collapsible, activating the title toggles the body (uncontrolled with defaultOpen, controlled with open and onOpenChange).
  • The error state’s retry button calls onRetry; show retrying while it runs.

Keyboard support

KeysAction
TabMoves to the title toggle (when collapsible), header actions, link, then the body.
Enter / SpaceOn the title toggle, expands or collapses the section.

Accessibility

Role
region (section with aria-labelledby)
Accessible name
The section title.
  • The heading labels the section; set headingId to point other elements at it.
  • The collapsible toggle follows the APG disclosure pattern: a button inside the heading with aria-expanded and aria-controls.
  • The icon is decorative and hidden from assistive technology.
  • Loading and busy set aria-busy; the loading label is announced politely.

Responsive behaviour

  • Header actions wrap under the title when space runs out (SectionHeader).
  • Below 480px the header, body and footer padding tighten.
  • The footer wraps its content and keeps it end-aligned.

Theme support

  • Surface, borders, footer and danger colours use Monarch semantic tokens, so every theme applies.
  • The chevron rotation is instant with reduced motion.

Do and don't

Do

  • Drive state from the query, so every section has a loading, empty and error story.
  • Use flush for tables and edge-to-edge lists.
  • Give "View all" links text that makes sense alone ("View all tasks").

Don't

  • Do not render your own spinner inside the body; use state="loading" or busy.
  • Do not nest SectionCards.
  • Do not use it for settings with a save bar; SettingsSection has that built in.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsEmptyState, ErrorState, LoadingState, SectionHeader

Testing coverage

  • Is a region labelled by its heading, with icon, actions, link, body and footer; ref forwarding; Tab order.
  • Shows loading (busy, announced), empty (default and custom) and error (retry) states instead of the children.
  • busy keeps the content and marks the section busy.
  • Collapsible uncontrolled: the title is a disclosure button; Enter and Space toggle the body and footer.
  • Collapsible controlled with open, and defaultOpen={false}.
  • Exposes tone and flush; honours headingLevel and headingId.
  • Renders on the server.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery/section-card; Cross-browser axe: /components/section-card

Tests: packages/react/src/components/layout/section-card