Skip to main content

TransferList

TransferList.tsx

import React, { useState } from "react";
import './TransferList.css';

type Item = {
id: number;
label: string;
};

type TransferListProps = {
leftItems: Item[];
rightItems: Item[];
onChange: (leftItems: Item[], rightItems: Item[]) => void;
};

const TransferList = (props: TransferListProps) => {
const { leftItems, rightItems, onChange } = props;
const [selectedLeftItems, setSelectedLeftItems] = useState<number[]>([]);
const [selectedRightItems, setSelectedRightItems] = useState<number[]>([]);

const handleLeftItemClick = (id: number) => {
if (!selectedLeftItems.includes(id)) {
setSelectedLeftItems([...selectedLeftItems, id]);
} else {
setSelectedLeftItems(selectedLeftItems.filter(item => item !== id));
}
};

const handleRightItemClick = (id: number) => {
if (!selectedRightItems.includes(id)) {
setSelectedRightItems([...selectedRightItems, id]);
} else {
setSelectedRightItems(selectedRightItems.filter(item => item !== id));
}
};

const handleAddButtonClick = () => {
const newLeftItems = leftItems.filter(item => !selectedLeftItems.includes(item.id));
const newRightItems = [...rightItems, ...leftItems.filter(item => selectedLeftItems.includes(item.id))];
setSelectedLeftItems([]);
onChange(newLeftItems, newRightItems);
};

const handleRemoveButtonClick = () => {
const newRightItems = rightItems.filter(item => !selectedRightItems.includes(item.id));
const newLeftItems = [...leftItems, ...rightItems.filter(item => selectedRightItems.includes(item.id))];
setSelectedRightItems([]);
onChange(newLeftItems, newRightItems);
};

return (
<div className="transfer-list">
<div className="transfer-list-column">
<h3>Available Items</h3>
<ul>
{leftItems.map(item => (
<li
key={item.id}
className={selectedLeftItems.includes(item.id) ? "selected" : ""}
onClick={() => handleLeftItemClick(item.id)}
>
{item.label}
</li>
))}
</ul>
</div>
<div className="transfer-list-buttons">
<button onClick={handleAddButtonClick}>Add</button>
<button onClick={handleRemoveButtonClick}>Remove</button>
</div>
<div className="transfer-list-column">
<h3>Selected Items</h3>
<ul>
{rightItems.map(item => (
<li
key={item.id}
className={selectedRightItems.includes(item.id) ? "selected" : ""}
onClick={() => handleRightItemClick(item.id)}
>
{item.label}
</li>
))}
</ul>
</div>
</div>
);
};

export default TransferList;

Usage
import React, { useState } from "react";
import TransferList from "./TransferList";

const leftItems = [
{ id: 1, label: "Item 1" },
{ id: 2, label: "Item 2" },
{ id: 3, label: "Item 3" },
{ id: 4, label: "Item 4" },
{ id: 5, label: "Item 5" },
];

const rightItems = [
{ id:

TransferList.module.css
.transfer-list {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
}

.transfer-list-column {
flex: 1;
padding-right: 1rem;
}

.transfer-list-column h3 {
margin-top: 0;
}

.transfer-list-column ul {
list-style: none;
padding: 0;
margin: 0;
}

.transfer-list-column li {
cursor: pointer;
padding: 0.5rem;
margin: 0.5rem 0;
}

.transfer-list-column li:hover,
.transfer-list-column li.selected {
background-color: lightgray;
}

.transfer-list-buttons {
display: flex;
flex-direction: column;
align-items: center;
}

.transfer-list-buttons button {
margin-bottom: 1rem;
}