Skip to content
Sign in
Image studioRemix lineageMenu

Remix lineagePro

The family tree of an image: the original, every variation, remix and upscale made from it, and what was made from those. Open any image to ink its line back to the original.

ProAn architecture study and everything made from it. Click any image to open it: its line back to the original is inked and the breadcrumb names every ancestor.

Installation

$ pnpm dlx shadcn@latest add @chatcn-pro/remix-lineage

Usage

tsx
import { RemixLineage } from "@/components/ui/chatcn/pro/remix-lineage"

<RemixLineage
  nodes={images}
  value={openId}
  onValueChange={setOpenId}
  actions={(node) => <Button onClick={() => remix(node)}>Remix</Button>}
/>

Pass every image in the family as a flat list; parentId links each one to the image it was made from, and kind (vary-subtle, vary-strong, remix, upscale, inpaint, outpaint, edit, reference) sets the default label. Clicking an image opens it: the tree inks the path from the original to that image, relatives outside the path step back, and the details row names every ancestor as a breadcrumb you can click.

The tree lays itself out (leaves take consecutive slots, every parent centers over its children) and scrolls past maxHeight. Drag the background, scroll or use the arrow keys to move around; opening an image glides it to the center. The layout, ancestry and edge helpers are exported from chatcn-pro-studio-2b-lineage for server use.

Examples

Left to right with folded branches

orientation defaults to horizontal, the direction a history strip reads. Fold a branch with collapsed (or the count on its edge); the image you have open is never hidden, whatever the list says.

ProGenerations flow left to right with two branches folded away. Right and Left arrows unfold and fold them.

States

A pending image shows a spinner and a dashed edge; a failed one shows its reason in the details, written as how to fix it.

ProLoading, no lineage, and an original with no remixes yet.

Props

PropTypeNotes
nodesLineageNode[]id, parentId, kind, label, src, thumbnail, alt, prompt, createdAt, author, status, error
value, defaultValue, onValueChangestringThe open image. Default the newest
onOpen(node) => voidClick, Enter or a breadcrumb
orientation"horizontal" | "vertical"Default horizontal
collapsed, defaultCollapsed, onCollapsedChangestring[]Ids whose variations are hidden
actions(node) => ReactNodeButtons at the end of the details row
loadingbooleanA skeleton tree
hideDetailsbooleanHide the breadcrumb and details row
maxHeightnumberDefault 440. The tree pans past it
labelstringAccessible name. Default "Remix lineage"
now, localeTimes read 4 min ago, 3 h ago, Yesterday; other locales use their own words

Keyboard

KeyAction
↑ ↓Previous and next image in tree order
→Expand a folded image, then move to its first variation
←Fold an expanded image, then move to its parent
Home EndFirst and last image
Enter, SpaceOpen the image
*Expand every sibling

Accessibility

  • An APG tree: one tab stop, aria-level, aria-setsize, aria-posinset and aria-expanded on every image, the open image aria-selected. In right to left layouts the arrow keys swap with the layout.
  • Each image is named by its visible label and time, then its state in words: "Inpaint sky, Generating, still generating".
  • The breadcrumb is a navigation landmark with the open image as aria-current. Opening, folding and unfolding are announced politely.
  • Captions off the inked path step down the gray ramp; only thumbnails dim, so text stays readable.

Motion

  • Opening an image with the pointer glides it to the center; from the keyboard it moves at once. Reduced motion always moves at once.
  • The ancestry line re-inks without animation: the change is the point. Thumbnails fade in over 200 ms once decoded.