Data
Transfer
Dual-list mover (pick list): select items in either panel and shuttle them across with the center controls.
Import
import { Transfer } from "@zephora/react";Examples
Basic
Items whose key is in `targetKeys` appear on the target side.
Source
- Write articles
- Publish articles
- Moderate comments
- Manage billing
- Manage users
Target
- Read articles
const permissions: TransferItem[] = [
{ key: "read", label: "Read articles" },
{ key: "write", label: "Write articles" },
{ key: "publish", label: "Publish articles" },
{ key: "comment", label: "Moderate comments" },
{ key: "billing", label: "Manage billing", disabled: true },
{ key: "users", label: "Manage users" },
];
<Transfer items={permissions} defaultTargetKeys={["read"]} />Controlled and searchable
`searchable` adds a filter input to each panel.
Available
- Write articles
- Publish articles
- Manage billing
- Manage users
Granted
- Read articles
- Moderate comments
const [granted, setGranted] = React.useState<string[]>(["read", "comment"]);
<Transfer
items={permissions}
targetKeys={granted}
onChange={setGranted}
titles={["Available", "Granted"]}
searchable
/>API
Transfer props
| Prop | Type | Default | Description |
|---|---|---|---|
items * | TransferItem[] | — | Full item pool. Items whose key is in `targetKeys` show on the target side. |
targetKeys | string[] | — | Controlled target-side keys. |
defaultTargetKeys | string[] | [] | Uncontrolled initial target-side keys. |
onChange | (targetKeys: string[]) => void | — | Fires with the new target-side keys after every move. |
titles | [ReactNode, ReactNode] | ["Source", "Target"] | Panel headings. |
searchable | boolean | false | Adds a filter input to each panel. |
unstyled | boolean | false | Headless mode — skips Zephora styling. |
TransferItem props
| Prop | Type | Default | Description |
|---|---|---|---|
key * | string | — | Unique item key. |
label * | string | — | Visible item label (also used for search). |
disabled | boolean | — | Item cannot be selected and is skipped by "move all". |