# Board column

A lane of cards on a board: a title with a capacity meter and an action, then groups of cards, each with a label and a count.

Block: `smbk-board-column`. Status: experimental. Figma: the Figma file, https://www.figma.com/community/file/1688324308358870630. Desktop and mobile: differ by presentation only.

## Options

| Axis | Values | Default | Meaning |
|---|---|---|---|

Parts: `smbk-board-column__head`, `smbk-board-column__heading`, `smbk-board-column__title`, `smbk-board-column__meter`, `smbk-board-column__action`, `smbk-board-column__group`, `smbk-board-column__group-head`, `smbk-board-column__dot`, `smbk-board-column__group-label`, `smbk-board-column__count`, `smbk-board-column__caret`, `smbk-board-column__group-body`, `smbk-board-column__cards`, `smbk-board-column__card`, `smbk-board-column__more`

## Markup

```html
<section class="smbk-board-column" aria-labelledby="board-column-1-title" data-scrollbar="">
  <div class="smbk-board-column__head">
    <div class="smbk-board-column__heading">
      <h3 class="smbk-board-column__title" id="board-column-1-title">Agents</h3>
      <div class="smbk-board-column__meter">
        <div
          aria-label="Agents on Agents"
          class="smbk-capacity-meter"
          role="meter"
          aria-valuemin="0"
          aria-valuemax="2"
          aria-valuenow="1"
          aria-valuetext="1 of 2 places"
        >
          <span class="smbk-capacity-meter__segments" aria-hidden="true">
            <span class="smbk-capacity-meter__segment smbk-capacity-meter__segment--filled"></span>
            <span class="smbk-capacity-meter__segment"></span>
          </span>
          <span class="smbk-capacity-meter__words" aria-hidden="true">1 of 2 places</span>
        </div>
      </div>
    </div>
    <div class="smbk-board-column__action">
      <button
        type="button"
        class="smbk-btn smbk-btn--tone-ghost smbk-btn--size-sm smbk-btn--icon-only"
        aria-label="Add an agent to Agents"
      >
        <i class="ph ph-plus smbk-icon smbk-icon--size-md smbk-btn__icon" aria-hidden="true"></i>
      </button>
    </div>
  </div>
  <div class="smbk-board-column__group">
    <div class="smbk-board-column__group-head">
      <span
        class="smbk-status-dot smbk-status-dot--tone-warning smbk-board-column__dot"
        aria-hidden="true"
      >
        <span class="smbk-status-dot__dot"></span>
      </span>
      <span class="smbk-board-column__group-label" id="board-column-2-label">Waiting on you</span>
      <span
        class="smbk-badge smbk-badge--look-soft smbk-badge--tone-info smbk-badge--size-sm smbk-board-column__count"
        id="board-column-2-count"
      >
        <span class="smbk-badge__label">6</span>
      </span>
    </div>
    <ul
      class="smbk-board-column__cards"
      aria-labelledby="board-column-2-label board-column-2-count"
    >
      <li class="smbk-board-column__card">
        <article class="smbk-card smbk-card--surface-raised smbk-card--layout-compact">
          <div class="smbk-card__content">
            <header class="smbk-card__header smbk-card__header--type-title smbk-card__header--size-sm">
              <div class="smbk-card__header-text">
                <div class="smbk-card__title-row">
                  <h4 class="smbk-card__title"><a class="smbk-card__link" href="#token-export">Review the token export</a></h4>
                </div>
              </div>
            </header>
            <div class="smbk-card__body smbk-card__body--type-text">Check the new color ladder against the contrast pairs.</div>
            <footer class="smbk-card__footer smbk-card__footer--type-actions smbk-card__footer--rule-off">
              <div class="smbk-card__footer-row">
                <div class="smbk-card__footer-start">
                  <span class="smbk-badge smbk-badge--look-soft smbk-badge--tone-info smbk-badge--size-sm">
                    <span class="smbk-badge__label">Design</span>
                  </span>
                </div>
                <div class="smbk-card__footer-end">
                  <span class="smbk-avatar smbk-avatar--size-xs smbk-avatar--tone-inverse smbk-avatar--type-image">
                    <img
                      class="smbk-avatar__image"
                      src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22270%22%3E%3Crect%20width%3D%22480%22%20height%3D%22270%22%20fill%3D%22%235c7798%22%2F%3E%3Ccircle%20cx%3D%22360%22%20cy%3D%2290%22%20r%3D%2260%22%20fill%3D%22%23cc0d0d%22%2F%3E%3C%2Fsvg%3E"
                      alt="Assigned to Maya Chen"
                    >
                  </span>
                </div>
              </div>
            </footer>
          </div>
        </article>
      </li>
      <li class="smbk-board-column__card">
        <article class="smbk-card smbk-card--surface-raised smbk-card--layout-compact">
          <div class="smbk-card__content">
            <header class="smbk-card__header smbk-card__header--type-title smbk-card__header--size-sm">
              <div class="smbk-card__header-text">
                <div class="smbk-card__title-row">
                  <h4 class="smbk-card__title"><a class="smbk-card__link" href="#release-notes">Write the release notes</a></h4>
                </div>
              </div>
            </header>
            <div class="smbk-card__body smbk-card__body--type-text">One line per change, in plain words.</div>
            <footer class="smbk-card__footer smbk-card__footer--type-actions smbk-card__footer--rule-off">
              <div class="smbk-card__footer-row">
                <div class="smbk-card__footer-start">
                  <span class="smbk-badge smbk-badge--look-soft smbk-badge--tone-info smbk-badge--size-sm">
                    <span class="smbk-badge__label">Docs</span>
                  </span>
                </div>
                <div class="smbk-card__footer-end">
                  <span
                    class="smbk-avatar smbk-avatar--size-xs smbk-avatar--tone-inverse smbk-avatar--type-initials"
                    role="img"
                    aria-label="Assigned to Leo Park"
                  >
                    <span class="smbk-avatar__initials" aria-hidden="true">LP</span>
                  </span>
                </div>
              </div>
            </footer>
          </div>
        </article>
      </li>
    </ul>
    <div class="smbk-board-column__more"><button type="button" class="smbk-btn smbk-btn--tone-ghost smbk-btn--size-sm"><span class="smbk-btn__label">Show all 6 waiting</span></button></div>
  </div>
  <div class="smbk-board-column__group">
    <div class="smbk-board-column__group-head">
      <span
        class="smbk-status-dot smbk-status-dot--tone-info smbk-board-column__dot"
        aria-hidden="true"
      >
        <span class="smbk-status-dot__dot"></span>
      </span>
      <span class="smbk-board-column__group-label" id="board-column-3-label">In progress</span>
      <span
        class="smbk-badge smbk-badge--look-soft smbk-badge--tone-info smbk-badge--size-sm smbk-board-column__count"
        id="board-column-3-count"
      >
        <span class="smbk-badge__label">1</span>
      </span>
    </div>
    <ul
      class="smbk-board-column__cards"
      aria-labelledby="board-column-3-label board-column-3-count"
    >
      <li class="smbk-board-column__card">
        <article class="smbk-card smbk-card--surface-raised smbk-card--layout-compact">
          <div class="smbk-card__content">
            <header class="smbk-card__header smbk-card__header--type-title smbk-card__header--size-sm">
              <div class="smbk-card__header-text">
                <div class="smbk-card__title-row">
                  <h4 class="smbk-card__title"><a class="smbk-card__link" href="#footer-links">Fix the footer links</a></h4>
                </div>
              </div>
            </header>
            <footer class="smbk-card__footer smbk-card__footer--type-actions smbk-card__footer--rule-off">
              <div class="smbk-card__footer-row">
                <div class="smbk-card__footer-start">
                  <span class="smbk-badge smbk-badge--look-soft smbk-badge--tone-danger smbk-badge--size-sm">
                    <span class="smbk-badge__label">Bug</span>
                  </span>
                </div>
                <div class="smbk-card__footer-end">
                  <span class="smbk-avatar smbk-avatar--size-xs smbk-avatar--tone-inverse smbk-avatar--type-image">
                    <img
                      class="smbk-avatar__image"
                      src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22270%22%3E%3Crect%20width%3D%22480%22%20height%3D%22270%22%20fill%3D%22%235c7798%22%2F%3E%3Ccircle%20cx%3D%22360%22%20cy%3D%2290%22%20r%3D%2260%22%20fill%3D%22%23cc0d0d%22%2F%3E%3C%2Fsvg%3E"
                      alt="Assigned to Maya Chen"
                    >
                  </span>
                </div>
              </div>
            </footer>
          </div>
        </article>
      </li>
    </ul>
  </div>
</section>
```

## React

```tsx
import { BoardColumn, BoardGroup } from './design-system/components/board-column/board-column.js';
import { CapacityMeter } from './design-system/components/capacity-meter/capacity-meter.js';
import { Button } from './design-system/components/button/button.js';
import { Card, CardHeader, CardFooter } from './design-system/components/card/card.js';
import { Badge } from './design-system/components/badge/badge.js';
import { Avatar } from './design-system/components/avatar/avatar.js';

<BoardColumn title="Agents" meter={<CapacityMeter filled={1} segments={2} aria-label="Agents on Agents" />} action={<Button tone="ghost" size="sm" icon-only icon="Plus" aria-label="Add an agent to Agents" />}>
  <BoardGroup label="Waiting on you" dot="warning" count={6} more={<Button tone="ghost" size="sm">Show all 6 waiting</Button>}>
    <Card surface="raised" layout="compact" header={<CardHeader size="sm" headingLevel={4} title="Review the token export" href="#token-export" />} footer={<CardFooter start={<Badge look="soft" size="sm" tone="info">Design</Badge>} end={<Avatar size="xs" tone="inverse" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22270%22%3E%3Crect%20width%3D%22480%22%20height%3D%22270%22%20fill%3D%22%235c7798%22%2F%3E%3Ccircle%20cx%3D%22360%22%20cy%3D%2290%22%20r%3D%2260%22%20fill%3D%22%23cc0d0d%22%2F%3E%3C%2Fsvg%3E" alt="Assigned to Maya Chen" />} />}>Check the new color ladder against the contrast pairs.</Card>
    <Card surface="raised" layout="compact" header={<CardHeader size="sm" headingLevel={4} title="Write the release notes" href="#release-notes" />} footer={<CardFooter start={<Badge look="soft" size="sm" tone="info">Docs</Badge>} end={<Avatar size="xs" tone="inverse" alt="Assigned to Leo Park">LP</Avatar>} />}>One line per change, in plain words.</Card>
  </BoardGroup>
  <BoardGroup label="In progress" dot="info" count={1}>
    <Card surface="raised" layout="compact" header={<CardHeader size="sm" headingLevel={4} title="Fix the footer links" href="#footer-links" />} footer={<CardFooter start={<Badge look="soft" size="sm" tone="danger">Bug</Badge>} end={<Avatar size="xs" tone="inverse" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22270%22%3E%3Crect%20width%3D%22480%22%20height%3D%22270%22%20fill%3D%22%235c7798%22%2F%3E%3Ccircle%20cx%3D%22360%22%20cy%3D%2290%22%20r%3D%2260%22%20fill%3D%22%23cc0d0d%22%2F%3E%3C%2Fsvg%3E" alt="Assigned to Maya Chen" />} />} />
  </BoardGroup>
</BoardColumn>
```

## Stylesheet

```css
/* smbk-board-column — Board column and Board group. Figma "Board column" 7118:731 (Meter and Action
 * booleans) and "Board group" 7118:654 (Count, Dot and Show all booleans).
 * A lane of cards pressed into the page: the canvas surface with the strong inset shadow inside a subtle
 * hairline, the medium container corners, 12 all round. Its head holds the title in Heading XS, the
 * capacity meter under it and an action at the end; then its groups, each a label with a status dot and a
 * count, the cards in a list and an optional "Show all". On a wide screen a column is the large column
 * width; in a narrow space it fills the width. A column given a height scrolls inside itself. A group can fold
 * under its head, always or only in a narrow space: it is then a native details element, its head the summary
 * with a caret at its end, its cards and "Show all" what it discloses (see the folding rules at the end). */

.smbk-board-column {
  box-sizing: border-box;
  display: flex;
  flex: none;
  flex-direction: column;
  gap: var(--smbk-space-stack-xl);
  width: var(--smbk-size-column-min-lg);
  max-width: 100%;
  padding: var(--smbk-space-inset-lg);
  overflow-y: auto;
  border: var(--smbk-border-width-hairline) solid var(--smbk-color-border-subtle);
  border-radius: var(--smbk-radius-container-md);
  background: var(--smbk-color-surface-canvas);
  color: var(--smbk-color-text-default);
  box-shadow: var(--smbk-elevation-inset-strong);
  /* The system's scrollbar: thin, in the subtle border color, on a clear track. */
  scrollbar-width: thin;
  scrollbar-color: var(--smbk-color-border-subtle) transparent;
}

/* A column that scrolls is a region the keyboard reaches: its ring is drawn inside its edge. */
.smbk-board-column:focus-visible {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: calc(-1 * var(--smbk-focus-ring-width));
}

.smbk-board-column__head {
  display: flex;
  align-items: flex-start;
  gap: var(--smbk-space-inline-md);
}

.smbk-board-column__heading {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--smbk-space-stack-sm);
  min-width: 0;
}

.smbk-board-column__title {
  margin: 0;
  color: var(--smbk-color-text-default);
  font-family: var(--smbk-typography-heading-xs-font-family);
  font-size: var(--smbk-typography-heading-xs-font-size);
  font-weight: var(--smbk-typography-heading-xs-font-weight);
  line-height: var(--smbk-typography-heading-xs-line-height);
  letter-spacing: var(--smbk-typography-heading-xs-letter-spacing);
  text-transform: var(--smbk-typography-heading-xs-text-transform);
  overflow-wrap: anywhere;
}

.smbk-board-column__meter {
  display: flex;
}

.smbk-board-column__action {
  display: flex;
  flex-shrink: 0;
  gap: var(--smbk-space-inline-xs);
}

/* ---- a group: its label row, its cards and "Show all" ---- */

.smbk-board-column__group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--smbk-space-stack-md);
}

.smbk-board-column__group-head {
  display: flex;
  align-items: center;
  gap: var(--smbk-space-inline-sm);
}

.smbk-board-column__group-label {
  margin: 0;
  color: var(--smbk-color-text-subtle);
  font-family: var(--smbk-typography-label-sm-font-family);
  font-size: var(--smbk-typography-label-sm-font-size);
  font-weight: var(--smbk-typography-label-sm-font-weight);
  line-height: var(--smbk-typography-label-sm-line-height);
  letter-spacing: var(--smbk-typography-label-sm-letter-spacing);
  text-transform: var(--smbk-typography-label-sm-text-transform);
}

.smbk-board-column__cards {
  display: flex;
  flex-direction: column;
  gap: var(--smbk-space-stack-md);
  align-self: stretch;
  margin: 0;
  padding: 0;
  list-style: none;
}

.smbk-board-column__card {
  display: block;
}

/* ---- a group that folds ----
   A group given a fold is a details element: its head is the summary, so it opens and closes with Enter and Space and
   says whether it is open with no script, and its cards and "Show all" sit in the body it discloses, the same room
   above them as in a group that does not fold. The head is at least the extra-small control height, the least a press
   needs, with a caret at its end in the extra-small icon size, the label's, that turns when the group is open; pointing at it darkens its
   label and caret, and keyboard focus rings it. A group that folds only in a narrow space is a plain group in a wide
   one: the React component draws it so, and in markup written by hand the stylesheet shows its body whatever the
   open state and hides the caret. */

.smbk-board-column__group--fold-always,
.smbk-board-column__group--fold-narrow {
  display: block;
}

.smbk-board-column__group-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--smbk-space-stack-md);
  padding-top: var(--smbk-space-stack-md);
}

:is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow) > .smbk-board-column__group-head {
  box-sizing: border-box;
  min-height: var(--smbk-size-control-xs);
  border-radius: var(--smbk-radius-control-sm);
  list-style: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

:is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow) > .smbk-board-column__group-head::-webkit-details-marker {
  display: none;
}

:is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow) > .smbk-board-column__group-head:focus-visible {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: var(--smbk-focus-ring-offset);
}

@media (hover: hover) {
  :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow) > .smbk-board-column__group-head:hover .smbk-board-column__group-label {
    color: var(--smbk-color-text-default);
  }

  :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow) > .smbk-board-column__group-head:hover .smbk-board-column__caret {
    color: var(--smbk-color-icon-default);
  }
}

.smbk-board-column__caret {
  flex-shrink: 0;
  color: var(--smbk-color-icon-subtle);
  font-size: var(--smbk-size-icon-xs);
  transition: transform var(--smbk-motion-expand-duration) var(--smbk-motion-expand-easing);
}

/* A group the React component is closing (data-closing) is still open until its motion ends; its caret turns back as
   the motion starts. */
.smbk-board-column__group[open]:not([data-closing]) > .smbk-board-column__group-head .smbk-board-column__caret {
  transform: rotate(180deg);
}

/* ---- motion: the body unfolds with the expand purpose and folds back the same way, as an accordion's item does.
   The group's height grows from its head to its own while the body fades in from the purpose's slight blur, and the
   caret turns with it. The React component moves it, the same in every browser, and marks the group data-motion
   once it runs; while it moves (data-moving) it is clipped, with room for the head's focus ring. Markup written by
   hand is moved by the stylesheet alone where the browser can animate to a natural height, and opens at once
   elsewhere. Under reduced motion the height lands at once and the fade still plays. ---- */

.smbk-board-column__group[data-moving] {
  overflow: clip;
  overflow-clip-margin: calc(var(--smbk-focus-ring-width) + var(--smbk-focus-ring-offset));
}

@supports (interpolate-size: allow-keywords) {
  :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow):not([data-motion]) {
    interpolate-size: allow-keywords;
  }

  :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow):not([data-motion])::details-content {
    block-size: 0;
    opacity: 0;
    filter: blur(var(--smbk-motion-expand-blur));
    overflow: clip;
    overflow-clip-margin: calc(var(--smbk-focus-ring-width) + var(--smbk-focus-ring-offset));
    transition-property: block-size, opacity, filter, content-visibility;
    transition-duration: var(--smbk-motion-expand-duration);
    transition-timing-function: var(--smbk-motion-expand-easing);
    transition-behavior: allow-discrete;
  }

  :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow):not([data-motion])[open]::details-content {
    block-size: auto;
    opacity: 1;
    filter: none;
  }

  /* Under reduced motion the height steps: at once as it opens, and only once it has faded as it closes. */
  @media (prefers-reduced-motion: reduce) {
    :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow):not([data-motion])::details-content {
      transition-duration: 0s, var(--smbk-motion-expand-duration), var(--smbk-motion-expand-duration), var(--smbk-motion-expand-duration);
      transition-delay: var(--smbk-motion-expand-duration), 0s, 0s, 0s;
    }

    :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow):not([data-motion])[open]::details-content {
      transition-delay: 0s;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .smbk-board-column__caret {
    transition: none;
  }
}

/* A group that folds only in a narrow space, written by hand, in a wide one: its body shows whatever the open state,
   its head takes no press look and no caret, so it reads as a group that does not fold. */
@container style(--smbk-layout: wide) {
  .smbk-board-column__group--fold-narrow > .smbk-board-column__group-head {
    min-height: 0;
    cursor: auto;
  }

  .smbk-board-column__group--fold-narrow .smbk-board-column__caret {
    display: none;
  }

  .smbk-board-column__group.smbk-board-column__group--fold-narrow:not([data-motion])::details-content {
    content-visibility: visible;
    block-size: auto;
    opacity: 1;
    filter: none;
  }
}

@media (hover: hover) {
  @container style(--smbk-layout: wide) {
    .smbk-board-column__group--fold-narrow > .smbk-board-column__group-head:hover .smbk-board-column__group-label {
      color: var(--smbk-color-text-subtle);
    }
  }
}

/* ---- touch: a folding group's head takes an invisible press area ----
   On a touch screen an invisible area, centred on it, takes the press out to the comfortable target in each direction
   it falls short of it; its look, its focus ring and its place stay as drawn. */

@media (pointer: coarse) {
  :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow) > .smbk-board-column__group-head {
    position: relative;
  }

  :is(.smbk-board-column__group--fold-always, .smbk-board-column__group--fold-narrow) > .smbk-board-column__group-head::after {
    content: '';
    position: absolute;
    inset: min(0%, (100% - var(--smbk-size-target-comfortable)) / 2);
  }
}

/* ---- the narrow form: the column fills the width it is given ---- */

@container style(--smbk-layout: narrow) {
  .smbk-board-column {
    width: 100%;
  }
}
```

## Tokens it reads

```json
{
  "space": {
    "stack": {
      "xl": {
        "$type": "dimension",
        "$value": "{{space.24}}",
        "$description": "Gap between things stacked one above another, extra large."
      },
      "sm": {
        "$type": "dimension",
        "$value": "{{space.8}}",
        "$description": "Gap between things stacked one above another, small."
      },
      "md": {
        "$type": "dimension",
        "$value": "{{space.12}}",
        "$description": "Gap between things stacked one above another, medium."
      }
    },
    "inset": {
      "lg": {
        "$type": "dimension",
        "$value": "{{space.12}}",
        "$description": "Padding inside a component, large."
      }
    },
    "inline": {
      "md": {
        "$type": "dimension",
        "$value": "{{space.8}}",
        "$description": "Gap between things side by side, medium."
      },
      "xs": {
        "$type": "dimension",
        "$value": "{{space.4}}",
        "$description": "Gap between things side by side, extra small."
      },
      "sm": {
        "$type": "dimension",
        "$value": "{{space.6}}",
        "$description": "Gap between things side by side, small."
      }
    }
  },
  "size": {
    "column": {
      "min": {
        "lg": {
          "$type": "dimension",
          "$value": "{{size.width.400}}",
          "$description": "The narrowest grid column, large: 400. Each value points to a density token, so compact density still applies."
        }
      }
    },
    "control": {
      "xs": {
        "$type": "dimension",
        "$value": "{{size.24}}",
        "$description": "Height of the extra-small control: 24 in both densities, the smallest target allowed. Dashboard recipe: use compact density; 40 for the page’s one main action and for forms; 32 for toolbars and filters, the size used most; 28 for actions inside table rows and cards. On phones switch to comfortable density, or give small controls an invisible 44 px tap area (size/target/comfortable)."
      }
    },
    "icon": {
      "xs": {
        "$type": "dimension",
        "$value": "{{size.12}}",
        "$description": "Icon box, extra small."
      }
    },
    "target": {
      "comfortable": {
        "$type": "dimension",
        "$value": "{{size.44}}",
        "$description": "Comfortable touch target (44)."
      }
    }
  },
  "border-width": {
    "hairline": {
      "$type": "dimension",
      "$value": "{{border-width.1}}",
      "$description": "Thin lines: dividers and almost every edge."
    }
  },
  "color": {
    "border": {
      "subtle": {
        "$type": "color",
        "$value": "{{color.grey.300}}",
        "$description": "Dividers and quiet edges."
      },
      "focus": {
        "$type": "color",
        "$value": "{{color.red.600}}",
        "$description": "Keyboard focus ring on controls."
      }
    },
    "surface": {
      "canvas": {
        "$type": "color",
        "$value": "{{color.grey.200}}",
        "$description": "Page background."
      }
    },
    "text": {
      "default": {
        "$type": "color",
        "$value": "{{color.grey.900}}",
        "$description": "Main text."
      },
      "subtle": {
        "$type": "color",
        "$value": "{{color.grey.700}}",
        "$description": "Secondary text: descriptions, metadata."
      }
    },
    "icon": {
      "default": {
        "$type": "color",
        "$value": "{{color.grey.900}}",
        "$description": "Icons."
      },
      "subtle": {
        "$type": "color",
        "$value": "{{color.grey.700}}",
        "$description": "Quiet icons."
      }
    }
  },
  "radius": {
    "container": {
      "md": {
        "$type": "dimension",
        "$value": "{{radius.12}}",
        "$description": "Corners of cards, panels and dialogs, medium."
      }
    },
    "control": {
      "sm": {
        "$type": "dimension",
        "$value": "{{radius.4}}",
        "$description": "Corners of controls, small."
      }
    }
  },
  "elevation": {
    "inset-strong": {
      "$type": "shadow",
      "$value": {
        "light": "inset -1px 2px 2px 0px #373d4333",
        "dark": "inset -1px 2px 2px 0px #0000004d"
      }
    }
  },
  "focus": {
    "ring": {
      "width": {
        "$type": "dimension",
        "$value": "{{border-width.2}}",
        "$description": "Thickness of the focus ring."
      },
      "offset": {
        "$type": "dimension",
        "$value": "{{space.2}}",
        "$description": "Gap between a control and its focus ring."
      }
    }
  },
  "typography": {
    "heading-xs": {
      "$type": "typography",
      "$value": {
        "fontFamily": "Funnel Display, Funnel Display Fallback, system-ui, sans-serif",
        "fontSize": {
          "min": "20px",
          "max": "28px"
        },
        "fontWeight": 400,
        "lineHeight": 1.2,
        "letterSpacing": "0px"
      }
    },
    "label-sm": {
      "$type": "typography",
      "$value": {
        "fontFamily": "Geist, Geist Fallback, system-ui, sans-serif",
        "fontSize": "12px",
        "fontWeight": 500,
        "lineHeight": 1.4,
        "letterSpacing": "0px"
      },
      "$description": "Label SM: labels on controls and short UI text (buttons, chips, tabs, menu headings). Geist Medium, sentence case. Code and keys use Code SM and Code MD."
    }
  },
  "motion": {
    "expand": {
      "duration": {
        "$type": "duration",
        "$value": "{{duration.320}}"
      },
      "easing": {
        "$type": "cubicBezier",
        "$value": "{{easing.cubic-out}}"
      },
      "blur": {
        "$type": "dimension",
        "$value": "2px",
        "$description": "How blurred the content is as it starts to open, and as it finishes closing."
      }
    }
  }
}
```

## Purpose

One lane of a board: the work for one project, one person or one stage. Its head says what the lane is and how full it is; under it, its cards are grouped by where each one stands, such as "Waiting on you" and "In progress".

## Anatomy

- The block, a lane pressed into the page: the canvas surface with the strong inset shadow, inside a subtle hairline, with the medium container corners.
- The head part: the heading part on the left, holding the title part in a small heading style and, under it, the meter part, and the action part at the end.
- The meter part holds a capacity meter, or a line of text that sums the lane up.
- The action part holds a small ghost icon button that adds to the lane.
- The group part, one per group: the group head part (the dot part, a status dot; the group label part in a small label style and the subtle text color; the count part, a small soft badge), then the cards part, a list with one card part per item, then the more part, a small ghost button that shows the rest. A group that folds is a disclosure: its group head is the row that opens and closes it, with the caret part at its end, and the group body part holds the cards and the more part.

## When to use

- Inside a board, one column per lane.
- On its own, for one lane of work in a narrow side panel.

## When not to use

- For a list that is not split into lanes. Use a [list](list.md).
- For content that is not a set of comparable items. Use a [card](card.md) or a section.

## Behavior

On a wide screen a column is the large column width; in a narrow space it fills the width it is given. It is as tall as its cards. Given a height by the page, it scrolls inside itself with the system's scrollbar: a thin, see-through bar over its cards that takes no room and shows while the mouse is over it or it scrolls.

A group shows the cards it is given; to keep a long group short, show a few and put a "Show all" button under them.

A group can fold under its head (`fold`): `always`, or `narrow`, only in a narrow space such as a phone, where the columns stack and a finished or failed group can wait closed under the work still to do. It starts closed unless `defaultExpanded` is set, or the page holds it with `expanded` and `onExpandedChange`. Pressing the head opens or closes it: the cards unfold with the expand motion as an accordion's item does, and the caret turns. A group that folds only in a narrow space is a plain group in a wide one, its cards always shown, and closed or open again as it was when the space turns narrow. Written by hand it is a `details` element with the `smbk-board-column__group--fold-always` or `--fold-narrow` class, its head the `summary`; in a wide space the stylesheet shows a narrow-only group's cards and hides its caret, where the browser lets a page show a closed disclosure's content.

## Accessibility

### What it does for you

- Each column is a region named by its title, so a screen reader can list the lanes and jump between them.
- The title is a third-level heading by default.
- Each group is a list named by its label and its count, such as "Waiting on you 6", one item per card.
- Given `headingLevel`, a group's label is a heading at that level, so the group sits in the page's outline under its column.
- A group that folds is a native disclosure: its head is one row that says whether it is open, and opens and closes with Enter and Space, with no script.
- The group's dot is decoration: the label says what the group is.
- While a column with a height has more to show than fits, it is a stop for the Tab key, so the arrow keys can scroll it, and shows the focus ring inside its edge.

### What you must do

- Give each column a title of its own.
- Set `headingLevel` to fit the page's outline, one below the heading above the board. A group's `headingLevel` goes one below its column's, and the cards' titles one below that.
- Name the add button for what it adds and where, such as "Add an agent to the blog", and the "Show all" button for what it shows, such as "Show all 6 waiting".

### How to test

- Tab through a column: focus goes through the head, the cards and "Show all" in reading order, with the focus ring showing in both themes and in a forced-color mode.
- Give a column a height it cannot fit in: it takes focus as a stop, and the arrow keys scroll it.
- With a screen reader, each column is found as a region by its title, and each group as a list with its label and count.
- On a phone, Tab to a folding group's head and press Enter or Space: it opens and says it is expanded; press again and it closes.
- With text at 200% and the page 320 pixels wide, the title and cards wrap and nothing is cut off.

### Keyboard

| Key | What it does |
|---|---|
| Tab | Moves focus through the head's buttons, the cards that are links or buttons, and "Show all". A column that scrolls is a stop of its own. |
| Up Arrow or Down Arrow | Scrolls a column that has more to show than fits, while the column has focus. |
| Enter | Follows a focused link, presses a focused button, or opens or closes a folding group from its head. |
| Space | Presses a focused button, or opens or closes a folding group from its head. |

## Usage rules

### Do

- Give each column a short title of its own.
- Order the groups by what needs the reader first.

### Don't

- Use a bare "Add" on every column.
- Let a group run on for dozens of cards; show a few and offer the rest.
