# Horse

The first machine here whose gait is a real thing rather than a label: a walk is four beats in a lateral sequence, a trot two on diagonals, a canter three on a lead — and the beat is counted off the footfalls. What each grounded foot is carrying then drives two joints nobody sets: a fetlock that sinks under load, and a neck that nods because the forehand is loading.

> 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-horse.json
```

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

## Notes

- A gait here is a set of touchdown instants, and the beat count is read off them rather than declared — 4 for a walk, 2 for a trot and a pace, 3 for a canter, 4 for a gallop. The pace is the proof that a beat count alone does not name a gait: it has a trot's two beats on the other diagonal.
- The fetlock is the one joint in the limb that nobody sets. Its angle is fetlockSink(load), so a loaded limb visibly sinks and a swinging one recoils, and the drop you are looking at is the support pattern made visible. It is a proportional rule, not a stiffness: there is no spring rate and no damping.
- The neck's nod is derived the same way — it answers the forehand's load against what the forehand carries standing square — so a walking horse nods twice a stride, once per foreleg, and a trotting one barely nods. balance is the dial between that and the scripted carriage.
- The load is a static weight distribution: the forehand's 58 percent shared out among whichever feet are down, summing to exactly one body while anything is down and to nothing in a suspension. No acceleration, no ground reaction force, no centre of pressure, no impulse at footfall.
- The body's rise through a suspension is a scripted curve per gait rather than a ballistic trajectory, and the animal never travels across the frame while its feet move. The mane, the tail's hair and the head's plating are drawn, not solved.

## Usage

```tsx
import { RobotHorse } from "@/components/ui/robot-horse"

<RobotHorse behavior="walk" />

// Or drive the footfall pattern yourself and watch the fetlocks take the weight.
<RobotHorse gait="canter" lead="left" phase={0.3} showContacts />
```

## Props

| name | type | default | description |
| --- | --- | --- | --- |
| `view` | `"plan" | "front" | "profile" | "iso"` | `"profile"` | Where the camera stands. One animal, four projections: straight down, straight on, side elevation, or three-quarter from above. |
| `behavior` | `"walk" | "trot" | "canter" | "gallop" | "graze" | "static"` | `"walk"` | What it does when phase is not supplied. Each one picks its own footfall pattern, its own stride length and how much of the neck's carriage the load takes. |
| `gait` | `"halt" | "walk" | "trot" | "pace" | "canter" | "gallop"` | — | Footfall pattern, overriding the one the behavior picked. pace — the lateral two-beat — is only reachable here. |
| `lead` | `"left" | "right"` | `"right"` | Which foreleg lands last. Only the canter and the gallop have a lead; the symmetrical gaits ignore it. |
| `phase` | `number` | — | Controlled cycle fraction. Supplying it stops the internal clock. |
| `speed` | `number` | `0.6` | Strides per second. |
| `offset` | `number` | `0` | Seconds of offset, so a string of them breaks step. |
| `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. |
| `arch` | `number` | — | Back curvature, −1 hollowed to 1 roached. Restrained, because a horse holds a topline. Omit and the behavior sets it. |
| `crouch` | `number` | — | Leg fold, 0 standing tall to 1 dropped. Omit and the behavior decides. |
| `neck` | `number` | — | Scripted neck carriage, −1 head to the floor to 1 head high. What the balance moves around. Omit and the behavior sets it. |
| `balance` | `number` | — | How much of the carriage the forehand's load takes, 0 scripted to 1 fully derived. At 1 the nod is entirely an output of the gait. Omit and the behavior decides. |
| `tail` | `number` | — | Tail carriage, −1 clamped under the quarters to 1 flagged out behind. Omit and the behavior sets it. |
| `ears` | `number` | — | Ears, −1 pinned back to 1 pricked forward. Omit and they prick at the pointer. |
| `gaze` | `number` | — | Head and eye aim, −1..1. Omit and it follows the pointer. |
| `interactive` | `boolean` | `true` | Drag across it to scrub the stride — the frame is one whole cycle — with arrows stepping 5% and shift 15%, Home parking it at the start and End handing it back to the behavior. The head tracks the pointer. |
| `onPhaseChange` | `(phase: number) => void` | — | Fired with the scrubbed cycle fraction, 0–1. |
| `showGround` | `boolean` | `true` | The ground line and the shadow. |
| `showContacts` | `boolean` | `false` | Mark the hooves carrying weight, which is the gait's support pattern drawn out. |
| `label` | `string` | — | Caption underneath the animal. |
| `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-horse.tsx`
