Inspect a plate
Plate 042 / Preparation record
Sample positions
Arrow keys move between wells. Enter or Space selects a well.
| Well | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| A | ||||||
| B | ||||||
| C | ||||||
| D |
Selected position: A1
A labelled laboratory plate with supplied well states, 44px selection controls and keyboard navigation across up to 1536 wells.
Plate 042
Arrow keys move between wells. Enter or Space selects a well.
| Well | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| A | ||||
| B | ||||
| C |
Plate 042 / Preparation record
Sample positions
Arrow keys move between wells. Enter or Space selects a well.
| Well | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| A | ||||||
| B | ||||||
| C | ||||||
| D |
Selected position: A1
Three ways in. They share one source, so the pixels match whichever you pick.
npm install @noorddev/vlak-react
// once, next to your app's root
import "@noorddev/vlak-react/css";
import { WellPlate } from "@noorddev/vlak-react";Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/well-plate.
npx @noorddev/vlak-cli add well-plate
The StyleX leaf lands in components/vlak/, for your own compiler to own. See StyleX.
npx shadcn add https://vlak.dev/r/well-plate.json
The same registry item, installed by shadcn's CLI.
<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />
No React. Link vlak.css and use the markup and classes below.
import { WellPlate } from "@noorddev/vlak-react";
<WellPlate label="Plate 042" rows={["A", "B", "C"]} columns={["1", "2", "3", "4"]} wells={[
{ row: "A", column: "1", status: "Loaded", label: "Control" },
{ row: "A", column: "2", status: "Loaded", label: "Sample 042" },
{ row: "B", column: "1", status: "Reserved", disabled: true },
]} defaultValue={{ row: "A", column: "1" }} />A plate of up to 1536 wells, with roving keyboard focus and explicit unrecorded cells.
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | ||
rowsrequired | readonly string[] | ||
columnsrequired | readonly string[] | ||
wellsrequired | readonly WellRecord[] | ||
value | WellPosition | null | ||
defaultValue | WellPosition | null | null | |
onValueChange | (value: WellPosition) => void | ||
description | ReactNode | ||
disabled | boolean | false | |
readOnly | boolean | false | Static well cells add no tab stops; their scroll container remains focusable. |
Also accepts Omit<HTMLAttributes<HTMLDivElement>, "defaultValue">.
| Keys | Does |
|---|---|
| Tab | Enters the plate at one enabled well and then leaves the grid. |
| Arrow keys | Moves focus along a row or column, skipping disabled wells without changing selection. |
| Home, End | Moves to the first or last enabled well in the current row. |
| Ctrl+Home, Ctrl+End | Moves to the first or last enabled well in the plate. |
| Enter, Space | Selects the focused well. Controlled selection waits for the caller's updated value. |
<div class="rs-well-plate"><p class="rs-well-plate-label">Plate 042</p><div class="rs-well-plate-scroll"><table class="rs-well-plate-table"><caption>Supplied well records</caption><thead><tr><th class="rs-well-plate-heading" scope="col">Well</th><th class="rs-well-plate-heading" scope="col">1</th></tr></thead><tbody><tr><th class="rs-well-plate-heading" scope="row">A</th><td class="rs-well-plate-cell"><div class="rs-well-plate-well rs-well-plate-static"><span class="rs-well-plate-coordinate">A1</span><span>Loaded</span></div></td></tr></tbody></table></div></div>