KQ-1638 · HOVER/FORECAST

Hover Forecast

A trip board whose filter menus show what an option would remove before you choose it: resting on an option turns the cards it would drop into dashed ghosts that fade and lean aside about their foot, row by row down the grid on springs.snap, while the forecast count rolls on snap and the share meter glides on springs.glide; leaving the option springs them back, and committing exits the ghosts on the exit ease while the survivors glide into place. Arrow keys move through each menu previewing as they go, Enter or Space commits, Escape abandons, and the trip cards are one roving tab stop moved by arrows across the measured columns.

KQ-1638 · HOVER/FORECAST
Forecast service

Open a filter to preview it. Arrow keys preview options, Enter applies, Escape keeps the current results. Arrow keys move between trips.

This week's trips

Waylight · 14–18 Oct

12 trips

Showing all 12

12 trips · no filters

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/hover-forecast

Props

ghostOpacity
number
default 0.3
How faint a card the previewed option would remove becomes, 0–1.
layout
"cards" | "compact" | "rows"
default "cards"
Full trip cards with a route line, two-line compact cards, or one-line rows.
motionScale
number
default 1
Scales the ghosts' lean, their step aside and the stagger, 0–2; 0 keeps the fade only.
records
ForecastTrip[]
default defaultForecastTrips
The trips on the board.
filters
ForecastFilter[]
default defaultForecastFilters
The filter menus in bar order; each option carries a match(trip) predicate.
value / defaultValue
ForecastValue
default {}
The applied selection: filter id to option id, or null for any. Controlled or initial.
onApply
(value: ForecastValue, change: ForecastChange) => void
default —
Fires when an option is committed or the filters are reset, with the whole new selection.
onPreview
(preview: ForecastPreview | null) => void
default —
Fires when a preview starts, moves or ends, so results can be fetched ahead of the commit.
forecast
(value: ForecastValue) => number | Promise<number>
default counts matching records
The would-be total for a previewed selection; pending, zero and failed answers are each worded plainly.
onOpen
(trip: ForecastTrip) => void
default —
A trip card was opened (click or Enter).
status
"ready" | "loading" | "error"
default "ready"
Whether the trips have arrived: skeleton cards while loading, a retry when they failed.
onRetry
() => void
default —
Try again was pressed after the trips failed to load.
title
string
default "This week's trips"
The board's heading.
subtitle
string
default "Waylight · 14–18 Oct"
The line under the heading.
noun
{ one: string; other: string }
default { one: "trip", other: "trips" }
What one record is called in counts and sentences.
formatFare
(fare: number) => string
default whole dollars
Prints a fare.
label
string
default the title
The board's accessible name.
disabled
boolean
default false
Read only: menus do not open and cards do not open.
className
string
default —
Classes for the surface; give it a height and the grid scrolls inside it.