# Lanes — Animated Section Block for React

> Kanban board section on plain pointer events: drag cards within and between lanes as a lifted, velocity-tilted preview while siblings re-flow FLIP-style around a placeholder, the target lane lights up, and the card springs into its slot on release. Fully keyboard operable (Space to pick up, arrows to move, Space to drop, Escape to cancel) with live-region announcements, per-lane WIP limits that turn the header amber, and controlled or uncontrolled state.

- Page: https://crucibleui.com/components/sections/lanes
- Category: [sections](https://crucibleui.com/components/sections)
- Tier: pro (one-time purchase, see https://crucibleui.com/pricing)
- Engine: motion
- npm dependencies: motion

## Install

```bash
npx shadcn@latest add @crucible/lanes
```

Pro install requires adding the token-bearing `@crucible` registry to components.json (issued at https://crucibleui.com/account after purchase).

Import from `@/components/crucible/lanes`.

## Props (`LanesProps`)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `lanes?` | `LanesLane[]` | — | Controlled board value. Pair with `onLanesChange`; if you never feed the change back in, cards spring back to where they came from. |
| `defaultLanes?` | `LanesLane[]` | `a built-in sample sprint board` | Initial board for uncontrolled use. |
| `onLanesChange?` | `(lanes: LanesLane[], detail: LanesMoveDetail) => void` | — | Fires after every committed move with the full next board + move detail. |
| `accentColor?` | `string` | `"#a5b4fc"` | The single accent used for the drop-target lane, the placeholder slot, the lifted card's edge and focus rings. Any CSS color. |
| `label?` | `string` | `"Board"` | Accessible name for the board region. |
| `ref?` | `React.Ref<LanesHandle>` | — | Imperative handle — `moveCard()`, `getLanes()`. |
| `className?` | `string` | — | — |

## Usage example

```tsx
"use client";

import * as React from "react";

import { Lanes } from "@/components/crucible/lanes";

export default function LanesDemo() {
  return (
    <div className="relative isolate flex h-full min-h-[360px] w-full items-center justify-center overflow-hidden rounded-xl bg-neutral-950">
      <div
        aria-hidden
        className="pointer-events-none absolute inset-0 -z-10"
        style={{
          background:
            "radial-gradient(70% 60% at 50% 0%, rgba(165,180,252,0.07), transparent 70%)",
        }}
      />
      <div className="relative z-10 flex w-full max-w-5xl flex-col gap-3 px-4 py-6 sm:px-6">
        <p className="text-xs text-neutral-500">
          Drag a card — or Space to pick up, arrows to move.
        </p>
        <Lanes label="Sprint board" />
      </div>
    </div>
  );
}
```

## Accessibility & performance

Honors `prefers-reduced-motion` with a designed static frame or fade (never a blank box) and passes `className` through.
