# Keyboard

A whole key deck placed by a unit grid: rows in 1u, 1.25u and 6.25u widths on one pitch, sculpted caps, and a split layout whose halves are genuinely turned apart.

> For the complete index, see [llms.txt](https://robocn.dev/llms.txt). A Markdown version of any page is available by appending `.md` to its URL or by sending an `Accept: text/markdown` header.

## Install

```bash
bunx --bun shadcn@latest add https://robocn.dev/r/robot-keyboard.json
```

Registry item: `robot-keyboard` · [`https://robocn.dev/r/robot-keyboard.json`](https://robocn.dev/r/robot-keyboard.json)

## Notes

- The rows are specified in unit widths and laid out on one pitch, so the stagger falls out of the widths the way it does on a real board rather than being nudged into place. A 60% deck comes to sixty-one keys because that is what the rows add up to.
- `split` is a change to where the keys are, not a second drawing: each half is turned about the deck's own centre and pushed out, and every cap carries the turn as its own spin. The one difference in the rows is that a 6.25u space cannot belong to one half, so it becomes two thumb keys.
- Sculpting is real geometry: each row's caps stand at their own height and their top faces tilt toward the home row, which is why the deck has a profile from a side camera and a flat board does not.
- The caps are blank, and a passage is a rhythm across the deck rather than text. Nothing here encodes a character, maps a layout, or reproduces anyone's key set.
- No dynamics and no electronics: no rollover, no debounce, no ghosting. The scan order is the real one — a row strobed, the columns read across it — and the scan rate is whatever `speed` says.

## Usage

```tsx
import { RobotKeyboard } from "@/components/ui/robot-keyboard"

<RobotKeyboard layout="compact" behavior="type" />

// Controlled, or a deck you can scrub a passage across.
<RobotKeyboard typed={0.4} layout="split" profile="sculpted" />
<RobotKeyboard interactive onTypedChange={setTyped} />
```

## Props

| name | type | default | description |
| --- | --- | --- | --- |
| `view` | `"plan" | "front" | "profile" | "iso"` | `"iso"` | Where the camera stands. One deck, four projections: straight down, straight on, side elevation, or three-quarter from above. |
| `typed` | `number` | — | Controlled position through the passage, 0 to 1. Omit it and the deck runs behavior. It is `typed` rather than `stroke` because `stroke` is an SVG attribute. |
| `behavior` | `"type" | "ripple" | "scan" | "idle" | "static"` | `"type"` | Type the passage, run a self-test wave across the deck, strobe the matrix with nothing pressed, or sit still. |
| `layout` | `"compact" | "extended" | "split"` | `"compact"` | Which deck it is. `extended` adds a function row and a four-column block; `split` cuts the same rows down the middle and turns the halves apart. |
| `profile` | `"sculpted" | "flat"` | `"sculpted"` | Sculpted rows dish toward the home row and tilt their faces with it, which is what gives the deck a profile in elevation. Flat makes every cap one height. |
| `strokes` | `number` | `16` | Keystrokes in the passage, rounded and clamped to 4–40. |
| `rake` | `number` | `6` | How far the case is tipped up from the desk, degrees, clamped 0–16. |
| `backlight` | `boolean` | `true` | Light the caps that are down. |
| `showScan` | `boolean` | `false` | Draw the row rails and outline the cell the scan is reading. |
| `speed` | `number` | `0.22` | Passages per second. |
| `animate` | `boolean` | `true` | Off parks the machine at phase and stops rendering. A reduced-motion preference does the same. |
| `paused` | `boolean` | `false` | Freeze where it stands. |
| `phase` | `number` | `0` | Seconds of offset, so a row of machines breaks step. |
| `interactive` | `boolean` | `false` | Drag across the deck to scrub the passage, or arrow-key it a stroke at a time. |
| `onTypedChange` | `(typed: number) => void` | — | Position through the passage throughout a drag or a key press. |
| `label` | `string` | — | Caption below the state readout. |
| `variant` | `"solid" | "outline" | "blueprint" | "wire"` | `"solid"` | How the machine is painted. Geometry never changes between variants. |
| `size` | `"xs" | "sm" | "md" | "lg" | "xl" | number` | `"md"` | Rendered width in pixels, or a step on the scale. |
| `color` | `string` | `var(--robot-shell)` | Body panels — the colour the machine reads as. |
| `accent` | `string` | `var(--robot-accent)` | Status colour: tip light, live tool, readouts. |
| `metal` | `string` | `var(--robot-metal)` | Bare machined parts: collars, bolts, tool bodies. |
| `dark` | `string` | `var(--robot-dark)` | Cast joints, base, shadow side. |
| `palette` | `Partial<RobotPalette>` | — | Override any subset of roles at once, including glow and grid. |

## Source

- `src/components/ui/robot-keyboard.tsx`
