Skip to content
Component installs need the registry setup
VegaStack Design

Destination Picker

Choose where something goes — spaces at the top of a folders-only tree, recent places, a folder search, and destinations refused with a reason.

Status
preview
Since
0.25.89
Accessibility pattern
folders-only tree, refusals announced

Last updated

Recent

Install

Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Destination Picker before installation. Retain the digest printed by this command.

pnpm exec vegastack-design verify destination-picker

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/destination-picker

Run the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.

The same command installs the registry items it composes: @vegastack/button, @vegastack/folder-tree, @vegastack/panel-search, @vegastack/skeleton, @vegastack/use-announcer, @vegastack/use-async-search.

Usage

import { DestinationPicker } from "@/components/ui/destination-picker";

<DialogBody>
  <DestinationPicker
    spaces={spaces}
    loadFolders={(space, parent) => api.folders(space, parent)}
    value={target}
    onValueChange={setTarget}
    disabledReason={(d) =>
      d.folderId === item.parentId ? "It's already here" : undefined
    }
    recents={recentPlaces}
    search={(q, signal) => api.searchFolders(q, { signal })}
  />
</DialogBody>;

Scope

The body of every "Move to…" dialog. The spaces are the top of a folders-only FolderTree in picker mode; each opens to its folders (loaded once through loadFolders), and choosing a space means its top level. The host owns the dialog and its Move button, enabled once value is set.

Anatomy

DestinationPicker — data-slot="destination-picker" | "destination-picker-entry" | "destination-picker-recents" | "destination-picker-refused" | "destination-picker-results"

Examples

Move to…

recents sit above the tree, search finds a folder anywhere (the tree comes back when the box is cleared), and disabledReason keeps a destination visible while refusing it: the reason shows on the row, under the picker, and is announced.

Recent

API Reference

PropTypeDefaultDescription
loadFolders*(spaceId: string, parentId: string | null) => Promise<DestinationFolder[]>—Loads the folders directly inside a space's top (parentId: null) or a folder.
onValueChange*(value: Destination) => void—Called when a destination is chosen.
spaces*readonly DestinationSpace[]—The spaces, in order.
classNamestring—Classes on the root.
disabledReason((destination: Destination) => string | undefined)—Why a destination can't take this move (it is where the item already is, inside the item itself, or the reader can't add there) — the row stays visible, the pick is refused and the reason is shown and announced. undefined means it can.
emptyLabelstring"No folders match."
labelstring"Destinations"The tree's accessible name.
recentLabelstring"Recent"
recentsreadonly DestinationEntry[]—Recent destinations, above the tree.
search((query: string, signal: AbortSignal) => Promise<DestinationEntry[]>)—Find folders by name anywhere; omit to hide the search box.
searchPlaceholderstring"Search folders"
valueDestination | null—The chosen destination.

Data attributes and CSS variables on DestinationPicker

AttributeValues
data-slot"destination-picker" | "destination-picker-entry" | "destination-picker-recents" | "destination-picker-refused" | "destination-picker-results"

Accessibility

  • The tree is FolderTree's picker mode: one tab stop, arrow keys move and open, Enter chooses.
  • A refused choice is announced through a polite live region and stays visible as text.
ContractStates tested
Behaviourdefault, loading, refused, search, recents
Accessibilitylabeled
Visualdefault, with-icon

Do / Don't

Do
Use DestinationPicker for every move — pages, files, tables, tasks — so one place reads the same everywhere.
Don't
Hand-build breadcrumbs and folder lists in each move dialog, or hide destinations that can't take the move.

On this page