transfer-list.tsx
Overview
transfer-list.tsx implements a React component named TransferList that provides a dual-list interface allowing users to transfer items between two lists: a left list and a right list. This UI pattern is commonly known as a "transfer list" or "shuttle list." The component supports item selection, filtering via search inputs, and moving selected items between lists with callback support for state synchronization with parent components.
This component is optimized for client-side rendering ('use client') and uses React hooks and memoization to manage state and performance. It also leverages iconography from the lucide-react library and UI elements from a local design system (e.g., Button, Input).
Exports Summary
Types:
TransferListItemTypeTransferListMoveDirection(enum)TransferListProps
Component:
TransferList(memoized React functional component)
Detailed API Documentation
Types
TransferListItemType
Represents the shape of an individual item in the transfer lists.
Property | Type | Description |
|---|---|---|
| string | Unique identifier for the item. |
| string | Display label for the item. |
| boolean | Optional flag indicating if the item is selected. Defaults to |
| boolean | Optional flag indicating if the item is disabled (non-selectable). Defaults to |
TransferListMoveDirection
Enum representing the direction of item movement between lists.
Value | Description |
|---|---|
| Items moved from right to left list. |
| Items moved from left to right list. |
TransferListProps
Props accepted by the TransferList component.
Property | Type | Description |
|---|---|---|
|
| The full list of items to be displayed across both lists. |
|
| Array of keys representing items initially placed in the right list (target). |
| (targetKeys: string[], direction: TransferListMoveDirection, moveKeys: string[]) => void (optional) | Callback fired when items are moved between lists. Receives the new right list keys, direction of move, and keys of moved items. |
(item: TransferListItemType) => ReactNode (optional) | Render prop to render additional content for each item in the right list. |
Component: TransferList
A memoized React functional component rendering two searchable lists with transfer buttons in the middle.
Props
See TransferListProps above.
Internal State
leftList: Items currently displayed on the left list.rightList: Items currently displayed on the right list.leftSearch: Search input value for filtering the left list.rightSearch: Search input value for filtering the right list.
Behavior & Implementation Details
Initialization: Uses a
useEffecthook to split the incomingitemsintoleftListandrightListbased on whether their keys appear intargetKeys.Selection Toggling: Clicking an item toggles its
selectedstate using thetoggleSelectionfunction.Filtering: Both lists support case-insensitive filtering based on the search inputs.
Moving Items:
moveToRight: Moves selected items from the left list to the right list.moveToLeft: Moves selected items from the right list to the left list.After movement, calls the
onChangecallback if provided, passing updated keys and movement direction.
Disabled Items: Items marked as
disabledin the right list do not show a selectable checkbox icon.Custom Rendering: The optional children render prop allows injecting custom JSX next to right list items.
Usage Example
import { TransferList, TransferListItemType, TransferListMoveDirection } from './transfer-list';
const items: TransferListItemType[] = [
{ key: '1', label: 'Item One' },
{ key: '2', label: 'Item Two', disabled: true },
{ key: '3', label: 'Item Three' },
];
function MyComponent() {
const [selectedKeys, setSelectedKeys] = React.useState<string[]>([]);
const handleChange = (
targetKeys: string[],
direction: TransferListMoveDirection,
moveKeys: string[],
) => {
console.log('Moved items:', moveKeys, 'to', direction);
setSelectedKeys(targetKeys);
};
return (
<TransferList
items={items}
targetKeys={selectedKeys}
onChange={handleChange}
>
{(item) => item.disabled ? <em>(disabled)</em> : null}
</TransferList>
);
}
Important Implementation Details and Algorithms
State Synchronization: The component splits
itemsinto left and right lists using thetargetKeysprop on initialization and wheneveritemsortargetKeyschange, ensuring it stays in sync with external state.Selection Handling: Instead of a centralized selected state, selection is stored per-item within the
leftListandrightListarrays via theselectedboolean property.Performance Optimization: The component is wrapped with
React.memoto prevent unnecessary re-renders when props do not change.UI/UX Details:
The component uses accessible button elements for item selection toggles.
Search inputs clear and filter lists dynamically.
Movement buttons disable when no items are selected (implicit by no effect if no selection).
Uses icons from the
lucide-reactlibrary for visual clarity of selection and movement.
Styling: Utility classes (likely Tailwind CSS) are applied for layout, spacing, shadows, borders, and hover states.
Interactions With Other Parts of the System
UI Components: Relies on
ButtonandInputcomponents from the local UI library (@/components/ui/button,@/components/ui/input).Icons: Uses SVG icons imported from the
lucide-reacticon set.Parent Components: Designed to be controlled or uncontrolled via
targetKeysandonChange. Parent components provide the master list of items and react to changes in selection.Styling System: Assumes a utility-first CSS framework (such as Tailwind CSS) for styling classes referenced in JSX.
Structure Diagram
classDiagram
class TransferList {
-leftList: TransferListItemType[]
-rightList: TransferListItemType[]
-leftSearch: string
-rightSearch: string
+moveToRight()
+moveToLeft()
+toggleSelection(list, setList, key)
+render()
}
TransferList ..> TransferListItemType : uses
TransferListMoveDirection <|-- TransferList : uses enum
Summary
The transfer-list.tsx file provides a reusable, accessible, and customizable React component for managing dual-list item transfers with search and selection capabilities. It cleanly separates concerns between state management, UI rendering, and event handling, making it suitable for integration into larger React applications that require item selection and organization workflows. Its design embraces React best practices with hooks and memoization, augmented by a modern iconography and UI toolkit.