All templates
Table dialog
Modal - Table
A modal that previews customers ready to be imported in a selectable table, with Cancel and Import in the footer. Modal, dialog, table, data table, import, upload, CSV, select rows, multi select, bulk action.
npx @adaptavant/edscli templates table-dialogPreview
Open in new tabCode
'use client';
import {
Button,
Heading,
Modal,
ModalContent,
ModalFooter,
ModalHeader,
Table,
type TableProps,
Text,
} from '@adaptavant/eds-core';
import * as React from 'react';
type Customer = {
id: string;
name: string;
email: string;
phone: string;
lastVisit: string;
};
const CUSTOMERS: Customer[] = [
{
id: '1',
name: 'Aaron Blake',
email: 'aaron.blake@example.com',
phone: '+1 415 555 0101',
lastVisit: '02 Oct 2026',
},
{
id: '2',
name: 'Abigail Chen',
email: 'abigail.chen@example.com',
phone: '+1 415 555 0132',
lastVisit: '28 Sep 2026',
},
{
id: '3',
name: 'Adam Foster',
email: 'adam.foster@example.com',
phone: '+1 212 555 0144',
lastVisit: '21 Sep 2026',
},
{
id: '4',
name: 'Aisha Patel',
email: 'aisha.patel@example.com',
phone: '+1 212 555 0178',
lastVisit: '15 Sep 2026',
},
{
id: '5',
name: 'Alice Moreno',
email: 'alice.moreno@example.com',
phone: '+1 646 555 0190',
lastVisit: '09 Sep 2026',
},
{
id: '6',
name: 'Andre Silva',
email: 'andre.silva@example.com',
phone: '+44 20 7946 0123',
lastVisit: '30 Aug 2026',
},
{
id: '7',
name: 'Arjun Mehta',
email: 'arjun.mehta@example.com',
phone: '+44 20 7946 0958',
lastVisit: '22 Aug 2026',
},
{
id: '8',
name: 'Ava Thompson',
email: 'ava.thompson@example.com',
phone: '+61 2 5550 1234',
lastVisit: '14 Aug 2026',
},
{
id: '9',
name: 'Benjamin Clark',
email: 'ben.clark@example.com',
phone: '+1 312 555 0167',
lastVisit: '03 Aug 2026',
},
{
id: '10',
name: 'Caleb Turner',
email: 'caleb.turner@example.com',
phone: '+1 503 555 0110',
lastVisit: '27 Jul 2026',
},
];
const COLUMNS: TableProps<Customer>['columns'] = [
{ header: 'Name', accessorKey: 'name', size: 180 },
{ header: 'Email', accessorKey: 'email', size: 240 },
{ header: 'Phone', accessorKey: 'phone', size: 160 },
{ header: 'Last visit', accessorKey: 'lastVisit', size: 120 },
];
/** Preview: the table modal, always open. */
export default function TableDialogTemplate() {
return (
<div className="h-screen bg-canvas">
<TableModal onClose={() => {}} onConfirm={() => {}} open />
</div>
);
}
/**
* A modal that previews the customers about to be imported. Every row starts
* selected; unselecting a row leaves it out of the import.
*/
export function TableModal({
open,
onClose,
onConfirm,
}: {
open: boolean;
onClose: () => void;
onConfirm: (customers: Customer[]) => void;
}) {
const allIds = CUSTOMERS.map((customer) => customer.id);
const [selectedIds, setSelectedIds] = React.useState<string[]>(allIds);
const count = selectedIds.length;
// Closing resets the selection.
const close = () => {
setSelectedIds(allIds);
onClose();
};
return (
<Modal
closeButtonProps={{ label: 'Close', onClick: close }}
onClose={close}
open={open}
size={800}
titleId="table-modal-title"
>
<ModalHeader>
<Heading as="h2" className="text-heading-20" id="table-modal-title">
Import customers
</Heading>
</ModalHeader>
{/* A fixed height, so only the table scrolls under the summary. */}
<ModalContent className="flex h-[480px] flex-col gap-4 overflow-hidden">
<Text className="text-body-14">
{count} {count === 1 ? 'customer is' : 'customers are'} ready to be
imported
</Text>
<div className="min-h-0 flex-1 overflow-y-auto">
<Table
columns={COLUMNS}
data={CUSTOMERS}
getRowId={(customer) => customer.id}
role="grid"
rowSelection={{
mode: 'multiple',
selectedRowIds: selectedIds,
onRowSelectionChange: setSelectedIds,
selectAllLabel: 'Select all customers',
getRowLabel: (customer) => `Select ${customer.name}`,
}}
/>
</div>
</ModalContent>
<ModalFooter>
<Button onClick={close} variant="neutralTertiary">
Cancel
</Button>
<Button
isDisabled={count === 0}
onClick={() => {
onConfirm(
CUSTOMERS.filter((customer) => selectedIds.includes(customer.id))
);
close();
}}
>
Import
</Button>
</ModalFooter>
</Modal>
);
}