Column hop
A small board whose card hops between columns on a loop: its row collapses, the next one opens and it rises in.
Behaviour
- The card fades and sinks, its row collapses, then the next column's row opens first and the card rises into it, so nothing ever overlaps.
- Rows animate grid-template-rows 1fr / 0fr with CSS transitions: no measuring, no dependencies. Column counts follow the card.
- The loop pauses off screen, while the tab is hidden and while the pointer or keyboard focus is on the board, so a link in a card never moves away. The row it left is inert and hidden from screen readers.
- Card text wraps inside its box, even an unbroken string.
- Reduced motion: no sink, rise or collapse; the card fades out and straight back in (150ms each).
Props
| Prop | Type | Description |
|---|---|---|
| columns | { title: ReactNode; items: ReactNode[] }[] | The columns, left to right, with the cards that stay put. A string title is also its tooltip, since long ones truncate. |
| item | ReactNode | The card that hops. |
| itemByColumn | ReactNode[] | Per-column versions of the card, by column index, so it wears the state of the column holding it. Falls back to item. |
| stops | number[]default [0, 1] | Column indices it visits in order, then loops. Indices outside columns are ignored; fewer than two: it stays put. |
| interval | numberdefault 2.6 | Seconds it rests in each column. |
| itemClassName | string | Classes for every card box. |
| className | string | Merged onto the grid with cn(). The column count is a --cols variable, so grid-cols-1 sm:grid-cols-3 overrides it per breakpoint. |
Installation
npx shadcn@latest add https://purrfectui.com/r/column-hop.jsonHow to use
import { ColumnHop } from "@/components/ui/column-hop";
<ColumnHop
columns={[
{ title: "Triage", items: [<p key="a">Open redirect on /logout</p>] },
{ title: "Reproducing", items: [] },
{ title: "Done", items: [<p key="b">Stored XSS in comments</p>] },
]}
item={<p>Path traversal in upload</p>}
itemByColumn={[undefined, <p key="r">Path traversal in upload · running</p>]}
stops={[0, 1]}
interval={2.6}
/>Source code
Loading…
Credits
Ported from bountydesk.vaibhav.quest.
License
MIT. Copy it into your project and change it as you like.