# Belt drive

A toothed belt between two pulleys with an idler you can wind down to take up slack. The belt is routed along its real tangents, and its teeth march by arc length.

> 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/belt-drive.json
```

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

## Notes

- Not the conveyor: nothing rides on this belt, it transmits. The driven pulley turns at the ratio the tooth counts give, and the teeth are placed by arc length along the belt, so they stay in step with both pulleys.
- The path is the taut one — external tangents between the pulleys and a real wrap arc on each. Moving the idler changes the belt length, and the readout says by how much; the component computes the path a belt would take rather than holding one length and slackening.
- Geometry only: no tension, no tooth jump, no slip.

## Usage

```tsx
import { BeltDrive } from "@/components/ui/belt-drive"

<BeltDrive driveTeeth={18} drivenTeeth={30} tension={0.45} />

// Controlled, or a belt you can scrub.
<BeltDrive travel={1.5} />
<BeltDrive interactive onTravelChange={setTravel} />
```

## Props

| name | type | default | description |
| --- | --- | --- | --- |
| `view` | `"plan" | "front" | "profile" | "iso"` | `"front"` | Where the camera stands. One drive, four projections: straight down, straight on, side elevation, or three-quarter from above. |
| `travel` | `number` | — | Controlled belt travel, in turns of the drive pulley. Omit it and the belt runs behavior. |
| `behavior` | `"run" | "shuttle" | "static"` | `"run"` | Run one way, or shuttle back and forth across four fifths of a turn. |
| `speed` | `number` | `0.35` | Drive turns per second, or shuttles 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 the belt along its run, or arrow-key it a twentieth of a turn at a time. |
| `onTravelChange` | `(travel: number) => void` | — | Belt travel in drive turns, throughout a drag or a key press. |
| `driveTeeth` | `number` | `18` | Teeth on the driving pulley, rounded and clamped to 10–48. The pitch radius follows. |
| `drivenTeeth` | `number` | `30` | Teeth on the driven pulley, rounded and clamped to 10–48. |
| `tension` | `number` | `0.45` | How far the idler is wound down its slot, 0–1. Lengthens the belt and takes more wrap. |
| `showIdler` | `boolean` | `true` | Include the tensioner in the loop. Without it the belt is a plain two-pulley run. |
| `showPlate` | `boolean` | `true` | Draw the back plate the shafts are carried in. |
| `label` | `string` | — | Caption below the ratio and belt-length 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/belt-drive.tsx`
