ChessBoard
Every example on this page is live, drawn by the library's Storybook, where you can also change its props and see the result.
A chess position, drawn from its FEN record in the frame's two colors. White's pieces are outlined and Black's are solid, and the dark squares are hatched, so the board stays sharp on e-ink and follows dark mode without swapping the two armies.
Use it instead of a board image from a chess API: an image is soft on e-ink, always shows White at the bottom, and breaks when its website is down.
Import
import { ChessBoard, materialOf } from "~lib/data-display/chess-board";
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
fen | string | Yes | N/A | The position, as a whole FEN record or just its piece placement |
size | number | No | N/A | Width and height in pixels, for a thumbnail. Leave it out to fill the box it sits in |
orientation | "white" | "black" | No | The side to move | Which side is at the bottom (White when the record doesn't say) |
coordinates | boolean | No | true | Letter the files and number the ranks along the edges |
highlight | string[] | No | N/A | Squares to frame, such as ["e2", "e4"] for the last move |
label | string | No | "Chess position" | What screen readers announce |
The file letters and rank numbers are left out when the board is too small for them to fit, including in previews shown at a smaller size.
Examples
Starting Position
A Puzzle
Frame squares with highlight, such as the last move or a hint.
Black to Move
When the record says Black is to move, Black is at the bottom. Set orientation to choose.
Filling Its Box
Leave out size and the board is as large a square as the box it sits in holds, centered in it.
In a box with no height of its own, the board is as tall as it is wide. Previews of the widget at
other sizes keep the board square too, as large as each box allows.
In a widget, give the board its box in CSS rather than a size worked out from the measured
box. A preview is a saved render with its scripts removed, laid out again in boxes of other
sizes, so a pixel size is frozen at whatever the box measured when it was saved, and in a
smaller box the last ranks are cut off. A box in CSS shrinks with it instead:
// Down a column: as wide as the column, and the first block to give up height.
<div className="aspect-square w-full min-h-0 shrink">
<ChessBoard fen={fen} />
</div>
// Across a row: as tall as the row, leaving the panel beside it its least width.
<div className="aspect-square h-full shrink-0" style={{ maxWidth: "calc(100% - 312px)" }}>
<ChessBoard fen={fen} />
</div>
Use size only for a thumbnail that should be the same pixels wherever it is shown.
Thumbnail
Who Is Ahead
materialOf counts each side's pieces and their worth in points (a pawn 1, a knight or bishop 3,
a rook 5, a queen 9), and the balance between them, above zero when White is ahead.
import { ChessBoard, materialOf } from "~lib/data-display/chess-board";
import { Stat } from "~lib/data-display/stat";
const Position = ({ fen }: { fen: string }) => {
const { balance } = materialOf(fen);
return (
<div className="flex items-center gap-4">
<ChessBoard fen={fen} size={240} />
<Stat
label="Material"
value={
balance === 0
? "Even"
: `${balance > 0 ? "White" : "Black"} +${Math.abs(balance)}`
}
/>
</div>
);
};
To draw the pieces themselves beside the board, use MaterialStrip.
See Also
- MaterialStrip - Each side's pieces and points, drawn beside the board
- QRCode - A code to play the puzzle on a phone
- Stat - A labelled figure