Design system Containers

Widget

A named group with a head: one zone, one job. The head owns the arrangement, never the typography.

.mk-widget

Overview

The widget is a named group with a head — one zone, one job, the rail's own grammar. This page documents the frame, the header variants, and whether the zone opens and closes. The body is deliberately drawn as grey bars — what sits inside belongs to its own components, and a widget that dictated its content would restyle every surface it was migrated onto.

Widget title

3 items

Usage

  • Define one named region of a pageUse a widget to group content and controls that serve one clear job within the page composition.
  • Keep header roles predictableThe title identifies the region; optional status, hint, disclosure, and contextual actions occupy their defined header slots without replacing the title.
  • Let body components keep their contractsThe widget provides structure, surface, and optional collapse behaviour. Lists, tables, forms, and other content inside retain their own spacing and interaction rules.

Anatomy

1 2 3 4 5

Widget title

Active 3 items
6
  1. 1Header. The fixed top band separates the zone's identity and controls from its content.
  2. 2Title. A real heading names the widget's one job and gives the page a usable document outline.
  3. 3Status. An optional read-only lifecycle fact may sit in the header when it describes the complete widget.
  4. 4Hint. Optional quiet arithmetic or supporting context, separate from status and controls.
  5. 5Actions. One or more contextual controls may follow. Every control keeps its own target and accessible name.
  6. 6Content region. The flexible widget body composes other components without changing their spacing or interaction rules.

Variants

Three independent decisions shape a widget: how its header is framed, whether its body can collapse, and whether the header carries a contextual menu. The grid keeps each pair separate so one choice does not imply the others.

Plain headerThe title follows the body's content flow.

Widget title

3 items
Framed headerA fixed band separates identity from content.

Widget title

3 items
Static bodyNo disclosure mark; the content always remains present.

Widget title

3 items
Collapsible bodyThe disclosure control promises open and closed states.

Widget title

3 items
Without header actionsUse when the widget exposes no contextual operation.

Widget title

3 items
With header menuA contextual menu follows the optional hint.

Widget title

3 items

States

Collapsible widget

A collapsible widget's header carries the expander triangle at its left; aria-expanded lives on that control, the triangle rotates with it, and closing leaves exactly the header. A static widget carries no triangle. The collapsible form uses a 64px header because that band must also stand alone as the complete closed face.

StateSpecimenWhat changes
Open

Widget title

3 items
The header keeps its divider, the content is present, and the expander points toward the available closing movement.
Closed

Widget title

3 items
Only the complete header remains. The title and optional arithmetic stay visible while the expander points toward opening.
  • Closed keeps the arithmeticA collapsed zone's head may carry its count as the hint — the page still answers how much waits inside.
  • The triangle is the contractOnly a collapsible head wears it. Decoration that looks like the expander promises an opening that never comes.

When content does not fit

A widget never grows past its share and never hides the overflow behind a scrollbar. The zone answers with its foot: .mk-widget-more — full width, the quiet hairline above, the count in the label — extends the zone in place, and its chevron flips with aria-expanded.

Widget title

12 items

Inner vertical scroll (.mk-widget-scroll) survives in exactly one seat — the builder's worklist. The pattern is under review; no new widget takes it without a decision.

Do and don't

Approvals

3 items
Do

One zone, one job: the name states it, and everything inside serves it.

Approvals

Guest notes

Don't

Two jobs under one frame — the widget stops answering "where do I do this", and both zones lose their own seat for an action.

Copy

  • The title names the jobA noun phrase for the zone's work — not a section number, not a verb.
  • The hint is quiet arithmeticA count or a state the head can carry without shouting.

Accessibility

  • The title is a headingReal heading levels, so the rail reads as an outline of zones.
  • The collapse is a named controlaria-expanded on the head's expander, its name saying the zone: "Collapse the approvals". The head itself is never the click target dressed as text.
  • Contained scroll announces itselfWhere the one scrolling seat remains, the cue appears on hover and focus both; keyboard reach is never scroll-only.

When to reach for something else

  • A record as a tileUse Card — a widget groups work, a card holds one record.
  • Repeating recordsUse Table.

Markup

<section class="mk-widget">
  <div class="mk-widget-head">
    <h3 class="mk-widget-title">Widget title</h3>
    <button class="mk-btn mk-btn-ghost mk-btn-flush mk-btn-inline" type="button">Quiet action</button>
  </div>
  <div class="mk-widget-body">…</div>
</section>

<!-- the framed 48px head, agreeing with record-card chrome -->
<section class="mk-widget">
  <header class="mk-widget-head mk-widget-head-framed">
    <h3 class="mk-widget-title">Widget title</h3>
  </header>
  <div class="mk-widget-body">…</div>
</section>

<!-- content does not fit: the zone extends by its foot, never by a scrollbar -->
<section class="mk-widget">
  <div class="mk-widget-head">…</div>
  <div class="mk-widget-body">…</div>
  <button class="mk-widget-more" type="button" aria-expanded="false">
    Show all 12
    <svg data-mk-icon="chevron" aria-hidden="true"></svg>
  </button>
</section>

<!-- collapsible: the expander lives in the head, the state on the control -->
<section class="mk-widget">
  <header class="mk-widget-head mk-widget-head-framed">
    <button class="mk-icon-btn" type="button" aria-expanded="false"
            aria-label="Expand the approvals">
      <svg class="chev" data-mk-icon="chevron" aria-hidden="true"></svg>
    </button>
    <h3 class="mk-widget-title">Widget title</h3>
  </header>
</section>