- Published on
Mixing shadcn/ui Data-Table and Sheet Components in Next.js
- Authors
- Name
- Ripal & Zalak
How to Mix shadcn/ui Data-Table and Sheet Components in Next.js
When building interactive and functional user interfaces, combining components like shadcn/ui Data-Table and Sheet can enhance usability. This guide explains how to integrate these components effectively in your Next.js application.
Problem Overview
While integrating the Data-Table component with a Sheet triggered on row click, developers often encounter layout issues where data renders incorrectly (e.g., collapsing into one column). This guide resolves such problems by:
- Structuring the Data-Table.
- Handling Sheet state effectively.
- Ensuring proper component interaction.
Prerequisites
- Next.js application setup.
- Installed shadcn/ui components.
- Familiarity with React Table and Radix UI components.
- Basic Tailwind CSS knowledge.
Implementation Steps
1. Data-Table Component Setup
First, create a DataTable
component with required props, state management, and proper event handling for row clicks.
'use client'
import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table'
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
data: TData[]
onRowClick?: (row: TData) => void
}
export function DataTable<TData, TValue>({
columns,
data,
onRowClick,
}: DataTableProps<TData, TValue>) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
onClick={() => onRowClick && onRowClick(row.original)}
className="cursor-pointer"
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</div>
)
}
2. Parent Component with Sheet State
Handle the Sheet visibility and row data in the parent component:
import { useState } from 'react'
import { DataTable } from '@/components/DataTable'
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetDescription,
} from '@/components/ui/sheet'
export default function Page() {
const [isSheetOpen, setIsSheetOpen] = useState(false)
const [rowDetails, setRowDetails] = useState(null)
const handleRowClick = (row) => {
setIsSheetOpen(true)
setRowDetails(row)
}
const columns = [
{ accessorKey: 'id', header: 'ID' },
{ accessorKey: 'name', header: 'Name' },
{ accessorKey: 'email', header: 'Email' },
]
const data = [
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' },
]
return (
<div>
<DataTable columns={columns} data={data} onRowClick={handleRowClick} />
<Sheet open={isSheetOpen} onOpenChange={setIsSheetOpen}>
<SheetContent>
<SheetHeader>
<SheetTitle>Row Details</SheetTitle>
<SheetDescription>
{rowDetails && (
<div>
<p>ID: {rowDetails.id}</p>
<p>Name: {rowDetails.name}</p>
<p>Email: {rowDetails.email}</p>
</div>
)}
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
</div>
)
}
Key Takeaways
- Define
onRowClick
in the Data-Table for custom row actions. - Use Sheet in the parent component to display additional data.
- Pass row data through state for dynamic content.
FAQs
1. Why is my data collapsing into a single column? Ensure that the flexRender
and column definitions in your Data-Table are correctly structured and align with your data.
2. How can I style the table and sheet components? Use TailwindCSS classes for customization or extend the shadcn/ui styles.
3. Can I use this approach with server-side data? Yes, fetch your data in getServerSideProps
or getStaticProps
and pass it as props to the components.
Conclusion
By combining shadcn/ui Data-Table and Sheet, you can build dynamic, user-friendly interfaces in Next.js. Use the above patterns to enhance your project and resolve common rendering issues.