Component
Board
Records as cards in columns by stage, moved between stages by drag or keyboard.
Plain-text source, for agents and clipboard use: /components/source/board.txt
When to use it
Shows how many records sit at each stage of a process and lets people move one forward by moving its card. Each column is a stage with a count, each card is a record with its reference, name and key facts. Cards move by their handle: drag it, or focus it and use the keyboard. Every move is announced, the counts update, and the board dispatches flux-board-move so the product can save the new stage.
Examples
Quotes by stage
Drag a card by its handle, or focus the handle, press Space, use the arrow keys and press Space to drop.
Enquiry
2-
QT-2208
Golden Circle, Nordic Trails
-
QT-2214
Ring Road self-drive, Lindqvist family
Quoted
3-
QT-2190
Northern Lights, Polar Agency
-
QT-2197
South Coast, Aurora Schools
-
QT-2201
Snæfellsnes, private group
On request
1-
QT-2176
Glacier walk, Nordic Trails
Confirmed
1-
KB-104931
Golden Circle, Anna Lindqvist
Press Space to pick the card up. The arrow keys move it within a column and between columns. Press Space to drop it, or Escape to put it back.
<div class="flux-board" data-flux-board role="region" aria-label="Quotes by stage" tabindex="0">
<section class="flux-board__column" aria-labelledby="board-column-0">
<div class="flux-board__header">
<h3 class="flux-board__title" id="board-column-0">Enquiry</h3>
<span class="flux-board__count">2</span>
</div>
<ol class="flux-board__cards">
<li class="flux-board__card">
<span class="flux-board__ref">QT-2208</span>
<button class="flux-board__handle" type="button" aria-pressed="false" aria-label="Move QT-2208" aria-describedby="board-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
<p class="flux-board__name">Golden Circle, Nordic Trails</p>
<p class="flux-board__meta"><span>Departs 14 Nov</span><span>24 passengers</span></p>
</li>
<li class="flux-board__card">
<span class="flux-board__ref">QT-2214</span>
<button class="flux-board__handle" type="button" aria-pressed="false" aria-label="Move QT-2214" aria-describedby="board-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
<p class="flux-board__name">Ring Road self-drive, Lindqvist family</p>
<p class="flux-board__meta"><span>Departs 2 Dec</span><span>4 passengers</span></p>
</li>
</ol>
</section>
<section class="flux-board__column" aria-labelledby="board-column-1">
<div class="flux-board__header">
<h3 class="flux-board__title" id="board-column-1">Quoted</h3>
<span class="flux-board__count">3</span>
</div>
<ol class="flux-board__cards">
<li class="flux-board__card">
<span class="flux-board__ref">QT-2190</span>
<button class="flux-board__handle" type="button" aria-pressed="false" aria-label="Move QT-2190" aria-describedby="board-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
<p class="flux-board__name">Northern Lights, Polar Agency</p>
<p class="flux-board__meta"><span>Departs 21 Nov</span><span>18 passengers</span></p>
</li>
<li class="flux-board__card">
<span class="flux-board__ref">QT-2197</span>
<button class="flux-board__handle" type="button" aria-pressed="false" aria-label="Move QT-2197" aria-describedby="board-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
<p class="flux-board__name">South Coast, Aurora Schools</p>
<p class="flux-board__meta"><span>Departs 9 Jan</span><span>36 passengers</span></p>
</li>
<li class="flux-board__card">
<span class="flux-board__ref">QT-2201</span>
<button class="flux-board__handle" type="button" aria-pressed="false" aria-label="Move QT-2201" aria-describedby="board-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
<p class="flux-board__name">Snæfellsnes, private group</p>
<p class="flux-board__meta"><span>Departs 12 Dec</span><span>8 passengers</span></p>
</li>
</ol>
</section>
<section class="flux-board__column" aria-labelledby="board-column-2">
<div class="flux-board__header">
<h3 class="flux-board__title" id="board-column-2">On request</h3>
<span class="flux-board__count">1</span>
</div>
<ol class="flux-board__cards">
<li class="flux-board__card">
<span class="flux-board__ref">QT-2176</span>
<button class="flux-board__handle" type="button" aria-pressed="false" aria-label="Move QT-2176" aria-describedby="board-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
<p class="flux-board__name">Glacier walk, Nordic Trails</p>
<p class="flux-board__meta"><span>Departs 18 Nov</span><span>12 passengers</span></p>
</li>
</ol>
</section>
<section class="flux-board__column" aria-labelledby="board-column-3">
<div class="flux-board__header">
<h3 class="flux-board__title" id="board-column-3">Confirmed</h3>
<span class="flux-board__count">1</span>
</div>
<ol class="flux-board__cards">
<li class="flux-board__card">
<span class="flux-board__ref">KB-104931</span>
<button class="flux-board__handle" type="button" aria-pressed="false" aria-label="Move KB-104931" aria-describedby="board-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
<p class="flux-board__name">Golden Circle, Anna Lindqvist</p>
<p class="flux-board__meta"><span>Departs 14 Sep</span><span>12 passengers</span></p>
</li>
</ol>
</section>
</div>
<p class="flux-visually-hidden" id="board-help">Press Space to pick the card up. The arrow keys move it within a column and between columns. Press Space to drop it, or Escape to put it back.</p>Anatomy
| Part | Description |
|---|---|
| Board | A focusable horizontal scroll region of columns. |
| Column | A section named by its heading, with a mono count and an ordered list of cards on layer-02. |
| Card | A layer-01 list item with a hairline: mono reference, handle, name and meta. |
| Handle | A button named “Move” and the reference, described by the instructions. |
| Lifted card | shadow-md and an interactive border while it is being moved. |
API
| Name | Kind | Description |
|---|---|---|
flux-board | class | The board. data-flux-board adds dragging, keyboard moves, announcements and counts. Give it role="region", a name and tabindex="0". |
flux-board__column | __header | __title | __count | class | A stage: its section, heading row, heading and count. |
flux-board__cards | class | The ordered list of cards in a stage. It keeps a minimum height so an empty stage is still a drop target. |
flux-board__card | __ref | __name | __meta | class | A card and its reference, name and facts. |
flux-board__handle | class | The move button. aria-pressed is true while the card is lifted. |
flux-board-move | element | Cancelable event dispatched on the board after a move. detail holds card, from and to columns, and index. A framework that renders the cards cancels it: the card goes back where it started and the framework renders the move. |
States
| State | Treatment |
|---|---|
| Resting | layer-01 card with a hairline. |
| Lifted | shadow-md and border-interactive; the handle turns brand and aria-pressed is true. |
| Empty stage | The column keeps its list ground so it can still be dropped into. |
Keyboard
| Keys | Action |
|---|---|
Space / Enter | On a handle, picks the card up; pressed again, drops it. |
Arrow Up / Arrow Down | Moves the lifted card within its column. |
Arrow Left / Arrow Right | Moves the lifted card to the previous or next column. |
Escape | Puts the lifted card back where it was. |
Accessibility
- Every pick-up, move and drop is announced with the column and position, through an assertive live region.
- The handle carries the instructions through aria-describedby.
- Columns are sections named by their headings, so a screen reader can jump between stages.
- Offer another way to change a stage too, such as a status select on the record, for people who cannot drag.
Tokens
The tier-3 and tier-2 tokens this component binds to. Change the token, not the component.
- --flux-board-column-width | -gap | -column-bg | -column-padding
- --flux-board-card-bg | -card-border | -card-padding | -card-gap
- --flux-board-lifted-shadow | -drop-border
Do and don’t
Do
- Order columns the way records move, left to right.
- Save on flux-board-move and move the card back if the save fails, with an error toast.
Don’t
- Do not put a status badge on a card; the column is the status.
- Do not colour columns. The stage name and count carry it.