KQ-2090 · CROSSROADS/PLAN

Crossroads Plan

An agent's plan that stops at its open questions: it runs on a rail until a crossroads, where the rail forks into the branches on offer, each previewed a few steps deep with the agent's recommendation and reason, and the run holds at the first undecided crossroads with everything after it folded into one faded line. Choosing drives one value per crossroads on springs.glide — the chosen column widens to the full width while its remaining steps grow downward on a cascade, and the branch not taken withers, its content fading as its column narrows to a 40px stub that keeps a dashed rail, a hollow node, a Reopen button and its title turned on its side — with witherSpeed scaling that spring (stiffness by speed², damping by speed, so its character never changes). Left and Right pick a branch, Enter chooses, Backspace reopens the last crossroads, and under 36rem the branches become tabs with the same keys.

KQ-2090 · CROSSROADS/PLAN

Fieldline · 0 of 2 decided

Switch freight vendors

Run heldChoose at the crossroads first: Switch every lane at once, or region by region?

At a crossroads, Left and Right pick a branch and Enter chooses it. Backspace reopens the last crossroads.

  1. Export current lanes and rates (done)
  2. Score three carriers on cost and coverage (done)

Crossroads · run held here

Switch every lane at once, or region by region?

Agent recommends region by region: On-time rate is the contract’s risk; waves cap a bad week to one region.

Recommended · Slower; two carriers live for three weeks.

  1. Start with North’s 9 lanes
  2. Watch on-time rate for a week
  3. Move South and East

+ 2 more steps

Then tell drivers and dispatch and 2 more steps, and 1 more crossroads — held until you choose.

held at a crossroads · 0 of 2 decided

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/crossroads-plan

Props

branchStyle
"rails" | "cards" | "lines"
default "rails"
How branches are drawn: metro rails with a drawn fork and nodes, bordered branch cards, or quiet text lists on hairlines.
witherSpeed
number
default 1
How fast the branch not taken withers and the chosen one grows, 0.5× to 2×; scales the glide spring without changing its damping ratio.
accent
string
default "var(--accent-bright)"
The chosen path, the picked branch, the recommendation and Approve — any CSS colour.
plan
CrossroadsSegment[]
default defaultCrossroadsPlan
The plan in order: { kind: "steps", id, steps } runs and { kind: "decision", decision } crossroads, each decision with an id, question, branches (id, title, summary, steps), recommended branch id and rationale.
choices / defaultChoices
Record<string, string>
default — / {}
Decision id to chosen branch id, controlled or initial.
onChooseBranch
(decisionId: string, branchId: string) => void
default —
Fires from the key, click or Take this path that chose a branch.
onReopen
(decisionId: string) => void
default —
Fires from Backspace or a stub's Reopen that reopened a crossroads.
onApprove
(choices: Record<string, string>) => void
default —
Approve plan was pressed with every crossroads decided.
preview
number
default 3
Steps of each branch shown before it is chosen; the rest grow in when it is.
title
string
default "Switch freight vendors"
The plan's name.
product
string
default "Fieldline"
Who it is for, shown above the title with the count of decided crossroads.
maxHeight
number
default —
Tallest the plan grows, in px, before it scrolls inside its own box with a bottom fade; choosing scrolls the next crossroads into view inside the plan, never the page.
status
"ready" | "loading" | "error"
default "ready"
Whether the plan has arrived: loading draws placeholder rows, error offers Try again. An empty plan says so.
onRetry
() => void
default —
Try again was pressed after the plan failed to load.
label
string
default the title
The surface's accessible name.
disabled
boolean
default false
Read only: nothing can be chosen, reopened or approved.
className
string
default —
Classes for the outer surface.