Theme Switcher

Data Table

Preview

Tables purposefully designed for dynamic, application data with features like sorting, filtering, and pagination. Powered by TanStack Table.

m5gr84i9316successken99@example.com
3u1reuv4242successAbe45@example.com
derv1ws0837processingMonserrat44@example.com
5kma53ae874successSilas22@example.com
bhqecj4p721failedcarmella@example.com

No results.

import {
	DataTable,
	DataTableActionCell,
	DataTableBody,
	DataTableEmptyRow,
	DataTableHead,
	DataTableHeader,
	DataTableHeaderSortButton,
	DataTableRows,
	createColumnHelper,
	getCoreRowModel,
	getFilteredRowModel,
	getPaginationRowModel,
	getSortedRowModel,
	useReactTable,
} from "@ngrok/mantle/data-table";

type Payment = {
	id: string;
	amount: number;
	status: "pending" | "processing" | "success" | "failed";
	email: string;
};

const columnHelper = createColumnHelper<Payment>();
const columns = [
	columnHelper.accessor("id", {
		id: "id",
		header: (props) => (
			<DataTableHeader>
				<DataTableHeaderSortButton
					column={props.column}
					sortingMode="alphanumeric"
				>
					ID
				</DataTableHeaderSortButton>
			</DataTableHeader>
		),
		cell: (props) => (
			<TableCell key={props.cell.id}>{props.getValue()}</TableCell>
		),
	}),
	columnHelper.accessor("amount", {
		id: "amount",
		header: (props) => (
			<DataTableHeader className="w-[200px]">
				<DataTableHeaderSortButton
					className="justify-end"
					column={props.column}
					iconPlacement="start"
					sortingMode="alphanumeric"
				>
					Amount
				</DataTableHeaderSortButton>
			</DataTableHeader>
		),
		cell: (props) => (
			<TableCell key={props.cell.id} className="text-right">
				{props.getValue()}
			</TableCell>
		),
	}),
	columnHelper.accessor("status", {
		id: "status",
		header: (props) => (
			<DataTableHeader>
				<DataTableHeaderSortButton
					column={props.column}
					sortingMode="alphanumeric"
				>
					Status
				</DataTableHeaderSortButton>
			</DataTableHeader>
		),
		cell: (props) => (
			<TableCell key={props.cell.id}>{props.getValue()}</TableCell>
		),
	}),
	columnHelper.accessor("email", {
		id: "email",
		header: (props) => (
			<DataTableHeader>
				<DataTableHeaderSortButton
					column={props.column}
					sortingMode="alphanumeric"
				>
					Email
				</DataTableHeaderSortButton>
			</DataTableHeader>
		),
		cell: (props) => (
			<TableCell key={props.cell.id}>{props.getValue()}</TableCell>
		),
	}),
	columnHelper.display({
		id: "actions",
		header: () => <DataTableHeader />,
		cell: () => (
			<DataTableActionCell>
				<DropdownMenu>
					<DropdownMenuTrigger asChild>
						<IconButton
							appearance="outlined"
							className="max-w rounded"
							type="button"
							size="sm"
							label="Open actions"
							icon={<DotsThree weight="bold" />}
						/>
					</DropdownMenuTrigger>
					<DropdownMenuContent align="end">
						<DropdownMenuItem className="flex items-center gap-2">
							<Icon svg={<PencilSimple />} /> Edit
						</DropdownMenuItem>
						<DropdownMenuItem className="text-danger-600 flex items-center gap-2">
							<Icon svg={<TrashSimple />} />
							Delete
						</DropdownMenuItem>
					</DropdownMenuContent>
				</DropdownMenu>
			</DataTableActionCell>
		),
	}),
];

function PaymentsExample() {
	const data = useMemo(() => examplePayments, []);

	const table = useReactTable({
		data,
		columns,
		getCoreRowModel: getCoreRowModel(),
		getPaginationRowModel: getPaginationRowModel(),
		getSortedRowModel: getSortedRowModel(),
		getFilteredRowModel: getFilteredRowModel(),
		initialState: {
			pagination: {
				pageSize: 100,
			},
		},
	});

	return (
		<DataTable table={table}>
			<DataTableHead />
			<DataTableBody>
				{table.getRowModel().rows.length > 0 ? (
					<DataTableRows />
				) : (
					<DataTableEmptyRow>
						<p className="flex items-center justify-center min-h-20">
							No results.
						</p>
					</DataTableEmptyRow>
				)}
			</DataTableBody>
		</DataTable>
	);
}

API Reference

The DataTable accepts the following props in addition to...