Skip to content
Sign in
Image studioCollection boardMenu

Collection boardPro

Folders and boards for generated images: drag one image or a whole selection onto a board, multi select with the keys people already know, and act on the selection from a bulk bar with Undo.

ProFifteen generations in two folders of boards. Drag a tile or a selection onto a board or New board, select with Cmd or Ctrl and Shift, and act on the selection from the bar.

Installation

$ pnpm dlx shadcn@latest add @chatcn-pro/collection-board

Usage

tsx
import { CollectionBoard } from "@/components/ui/chatcn/pro/collection-board"

<CollectionBoard
  images={images}
  boards={boards}
  onBoardsChange={setBoards}
  folders={folders}
  onDownload={(ids) => openExport(ids)}
  onDelete={(ids) => api.deleteImages(ids)}
/>

The sidebar lists All generations, then folders of boards, then loose boards and New board. Drag a tile past 6 px and it becomes a stack with a count that follows the pointer; the board under it lights up and the stack names where it will land. Dropping on New board makes a board with those images and opens its name for editing. Esc cancels a drag.

Drag is a shortcut, never the only way: the bulk bar's Add to board menu does the same from the keyboard and on touch, where tiles scroll instead of dragging. Removing images from a board and deleting them from the library both wait out an Undo window (undoMs, default 6 s); onDelete runs only when it closes.

Examples

States

Loading keeps the layout with quiet placeholders. An empty board says how to fill it. Long names truncate with the full name on hover, and the counts never truncate. Narrow containers turn the sidebar into one scrolling row of boards.

ProLoading, an empty board, and a long board name with a selection.

Props

PropTypeNotes
imagesCollectionImage[]Required. The whole library, newest first
boards, defaultBoards, onBoardsChangeCollectionBoard[]id, name, folderId, imageIds
foldersCollectionFolder[]Group boards in the sidebar
activeId, defaultActiveId, onActiveChangestring"all" shows every image
selectedIds, defaultSelectedIds, onSelectedChangestring[]
onOpen(image) => voidEnter or a double click
onDownload(ids) => voidShows Download in the bulk bar
onDelete(ids) => voidShows Delete in All generations, after Undo closes
onAddToBoard(boardId, ids) => voidAfter a drop or the menu
loadingbooleanSkeleton sidebar and tiles
allLabelstringDefault "All generations"
undoMsnumberDefault 6000

Keyboard

KeyAction
← → ↑ ↓, Home, EndMove through the grid
SpaceSelect or clear the focused image
Shift + arrowExtend the selection
⌘ or Ctrl + ASelect every image on the board
EnterOpen the focused image
Delete, BackspaceRemove from the board, or delete in All generations
EscClear the selection, or cancel a drag
F2 on a boardRename it

Accessibility

  • The grid is a multi select listbox with one tab stop; each tile is an option named by its alt text.
  • Boards are buttons named by their visible name and count, with aria-current on the open one.
  • The bulk bar is a toolbar named by the selection count. Its labels collapse to icons in narrow containers and stay as the accessible names.
  • Drops, menu adds, removals and Undo are announced in a polite live region.

Motion

  • A selected image insets to 0.88 in 150 ms, so selection reads without color; from the keyboard it changes at once.
  • The drag stack tracks the pointer 1:1 on transform and never eases its position. A board that received images swaps its count for a check for a moment.
  • The bulk bar and Undo rise 8 px with a 180 ms fade. Reduced motion keeps only the fades.