Data Display

Issue Cascade Board

A dark, ambient-glow issue list where cards cascade in, status pills re-layout on change and edges shimmer on hover — built for product launch sections.

This is a WebberUI Pro component

The install command below needs a licence to run; without one it returns 401.

How to install Pro components →See the plans →

Turn an issue list into a "work in motion" scene for a product launch section: two or three blurred glow orbs drift on a dark backdrop, and rows cascade in from top to bottom as the board scrolls into view. Clicking a status pill cycles it through to do, in progress, in review and done — the pill resizes, its text cross-fades and the status icon redraws. With grouping on, a row flies from its old group to the new one; with auto-play on, the next card advances one step every few seconds. Every icon and sub-part is implemented inside the component.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add "https://webberui.com/r/issue-cascade-board.en.json?t=<install token>"

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

2200
Active edited usageDefault props
<IssueCascadeBoard/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add "https://webberui.com/r/issue-cascade-board.en.json?t=<install token>"

Or, once registries are configured in components.json, install it as @webberui/issue-cascade-board.

Usage

import * as React from "react";
import {
  IssueCascadeBoard,
  type IssueItem,
} from "@/components/ui/issue-cascade-board";

const initial: IssueItem[] = [
  { id: "1", key: "HX-142", title: "Checkout total rounds incorrectly", status: "doing", labels: ["Bug"], assignee: "Ivy Lin", priority: 3 },
  { id: "2", key: "HX-138", title: "Add a Traditional Chinese sort option", status: "review", labels: ["Feature"], assignee: "Ben Chen", priority: 2 },
  { id: "3", key: "HX-151", title: "Trip cards wrap badly on narrow screens", status: "todo", assignee: "Sam Chang", priority: 1 },
];

export function LaunchBoard() {
  const [items, setItems] = React.useState(initial);
  return (
    <IssueCascadeBoard
      items={items}
      onStatusChange={(id, status) =>
        setItems((prev) => prev.map((it) => (it.id === id ? { ...it, status } : it)))
      }
      groupBy="status"
      autoPlay
    />
  );
}

Props

PropTypeDefaultDescription
itemsIssueItem[]—Controlled issue list; when provided, status changes are only reported via onStatusChange and the parent updates the list
defaultItemsIssueItem[][]Initial issue list for uncontrolled mode
onStatusChange(id: string, status: IssueStatus) => void—Called when a status pill is clicked or auto-play advances a card
groupBy"none" | "status""none"status splits rows into four groups; rows fly between groups with a layout animation
autoPlaybooleanfalseEvery interval, advance the next unfinished card by one status
intervalnumber2200Auto-play interval (ms, minimum 400)
glowbooleantrueShow the blurred glow orbs in the background
theme"dark" | "auto""dark"dark is always dark; auto follows the page light/dark mode
accentstring"#6366f1"Accent for the in-progress status and the glow; falls back to --wb-issue-cascade-accent
statusLabelsPartial<Record<IssueStatus, string>>To do / In progress / In review / DoneOverride the status display text
classNamestring—Merged into the root container

IssueItem

FieldTypeDefaultDescription
idstring—Unique id
keystring—Display identifier such as HX-142, rendered in a monospace font
titlestring—Issue title, truncated when too long
status"todo" | "doing" | "review" | "done"—Current status
labelsstring[]—Label chips (shown at 768px and wider)
assigneestring—Assignee name, shown as an initials avatar (last character for CJK names)
priority0 | 1 | 2 | 30Priority bars: none / low / medium / high

The IssueItem, IssueStatus and IssueCascadeBoardProps types are also exported by name.

How it works

  • CSS variables: --wb-issue-cascade-stagger (default 70ms, per-row entrance delay), --wb-issue-cascade-accent (default #6366f1) and --wb-issue-cascade-glow-duration (default 1.6s, one turn of the hover edge glow). Override them at the theme level
  • Entrance: fires once when an IntersectionObserver sees the board enter the viewport; each row goes y: 16 → 0 while opacity and blur(6px) clear, with a spring (stiffness 260, damping 26) for the movement
  • Status icons: to do is a hollow ring, in progress a ring with a half fill, in review six dashed arcs, done a filled circle with a check — all redrawn with pathLength on change
  • Auto-play: picks the next unfinished card in order and advances it one step; once everything is done it cycles from the cursor back to to do. It pauses while the board is out of view, and the orb drift stops too
  • Controlled mode: when you pass items, the component never changes status on its own — update the array in onStatusChange. Auto-play advances through the same callback

Accessibility

  • The issue list is role="list"; in grouped mode each group is a section labelled by its heading
  • Status pills are buttons with an aria-label such as "HX-142 status: In progress, click to change"; they are reachable with Tab, toggle with Enter / Space and show a focus-visible ring
  • Status changes (click, auto-play or a controlled update from outside) are announced through an aria-live="polite" region
  • During auto-play a "Pause auto-play" button is provided (WCAG 2.2.2), with aria-pressed reflecting the paused state
  • Priority bars and assignee avatars have role="img" with a text label
  • When the user has turned on reduce motion, the cascade entrance and layout animations are skipped, the orbs do not drift, the hover edge glow does not rotate, and statuses switch directly