# Turntable deck

A belt-drive deck whose arm is geared to its platter by the groove: one revolution walks the stylus in by exactly one groove pitch, and the arm angle is solved from the radius it reaches.

> 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/turntable-deck.json
```

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

## Notes

- Progress and platter angle are not two animations; they are one number seen at two scales, because the spiral gears them together. Scrubbing the platter therefore walks the stylus back out and the readout counts down with it.
- The arm is solved, not tweened: the pivot is a fixed distance from the spindle and the stylus a fixed distance from the pivot, so asking for a groove radius fixes the angle. The tracking error falls out of that geometry and goes in the readout — this arm nulls at two radii and stays under one and a half degrees between them.
- The spiral repeats. When the stylus reaches the run-out the next revolution puts it back at the lead-in, which is the one place the gearing is a loop rather than a machine.
- Nothing here plays, times or decodes anything. The belt is drawn where a belt goes rather than solved, the arm tube is a straight taper between projected ends, and the record's label is concentric structure in palette roles.
- An original archetype. No manufacturer, product line, wordmark, paint scheme or record label is reproduced here or in the demo.

## Usage

```tsx
import { TurntableDeck } from "@/components/ui/turntable-deck"

<TurntableDeck rpm={45} cue="play" />

// Controlled, or a platter you can scrub with a thumb.
<TurntableDeck progress={0.35} />
<TurntableDeck interactive onProgressChange={setProgress} />
```

## Props

| name | type | default | description |
| --- | --- | --- | --- |
| `view` | `"plan" | "front" | "profile" | "iso"` | `"plan"` | Where the camera stands. One deck, four projections: straight down, straight on, side elevation, or three-quarter from above. |
| `progress` | `number` | — | Controlled position through the side, 0 lead-in to 1 run-out. Omit it and the deck runs behavior. |
| `behavior` | `"play" | "scratch" | "static"` | `"play"` | Run the side through, or rock the platter back and forth over a slow crawl forward — which carries the stylus back up the spiral. |
| `cue` | `"play" | "lift" | "rest"` | `"play"` | Where the arm is standing: in the groove, picked up over it, or parked on its rest off the record. |
| `rpm` | `33 | 45 | 78` | `33` | The speed selector. Scales the platter against the 33 rpm default; an unknown value falls back to 33. |
| `turnsPerSide` | `number` | `40` | Revolutions of the platter in a whole side, clamped to 2–400. A real one is several hundred; the gearing is exact for whatever you set. |
| `speed` | `number` | `0.55` | Platter revolutions per second at 33 rpm. |
| `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 the platter to scrub, or arrow-key it a revolution at a time. |
| `onProgressChange` | `(progress: number) => void` | — | Position through the side throughout a drag or a key press. |
| `showGrooves` | `boolean` | `true` | Draw the groove spiral on the record. |
| `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/turntable-deck.tsx`
