1import * as React from 'react';
2import { cn } from '../lib/cn';
3
4interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
5 label?: string;
6}
7
8const TableRoot = ({
9 className,
10 label,
11 ref,
12 ...props
13}: TableProps & { ref?: React.Ref<HTMLTableElement> }) => (
14 <div
15 role={label ? 'region' : undefined}
16 aria-label={label}
17 tabIndex={label ? 0 : undefined}
18 className="border-border focus-visible:ring-ring ring-offset-background relative w-full overflow-auto rounded-md border focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
19 >
20 <table ref={ref} className={cn('w-full text-xs', className)} {...props} />
21 </div>
22);
23TableRoot.displayName = 'Table';
24
25const TableHeader = ({
26 className,
27 ref,
28 ...props
29}: React.HTMLAttributes<HTMLTableSectionElement> & {
30 ref?: React.Ref<HTMLTableSectionElement>;
31}) => <thead ref={ref} className={cn('bg-card [&_tr]:border-b', className)} {...props} />;
32TableHeader.displayName = 'TableHeader';
33
34const TableBody = ({
35 className,
36 ref,
37 ...props
38}: React.HTMLAttributes<HTMLTableSectionElement> & {
39 ref?: React.Ref<HTMLTableSectionElement>;
40}) => <tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />;
41TableBody.displayName = 'TableBody';
42
43const TableFooter = ({
44 className,
45 ref,
46 ...props
47}: React.HTMLAttributes<HTMLTableSectionElement> & {
48 ref?: React.Ref<HTMLTableSectionElement>;
49}) => (
50 <tfoot
51 ref={ref}
52 className={cn('border-t font-medium [&>tr]:last:border-b-0', className)}
53 {...props}
54 />
55);
56TableFooter.displayName = 'TableFooter';
57
58const TableRow = ({
59 className,
60 ref,
61 ...props
62}: React.HTMLAttributes<HTMLTableRowElement> & { ref?: React.Ref<HTMLTableRowElement> }) => (
63 <tr
64 ref={ref}
65 className={cn(
66 'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
67 className,
68 )}
69 {...props}
70 />
71);
72TableRow.displayName = 'TableRow';
73
74const TableHead = ({
75 className,
76 scope = 'col',
77 ref,
78 ...props
79}: React.ThHTMLAttributes<HTMLTableCellElement> & { ref?: React.Ref<HTMLTableCellElement> }) => (
80 <th
81 ref={ref}
82 scope={scope}
83 className={cn(
84 'border-border text-muted-foreground h-10 border-r px-3 py-4 text-left align-middle font-medium last:border-r-0 [&:has([role=checkbox])]:pr-0',
85 className,
86 )}
87 {...props}
88 />
89);
90TableHead.displayName = 'TableHead';
91
92const TableCell = ({
93 className,
94 ref,
95 ...props
96}: React.TdHTMLAttributes<HTMLTableCellElement> & { ref?: React.Ref<HTMLTableCellElement> }) => (
97 <td
98 ref={ref}
99 className={cn(
100 'border-border border-r px-3 py-4 align-middle last:border-r-0 [&:has([role=checkbox])]:pr-0',
101 className,
102 )}
103 {...props}
104 />
105);
106TableCell.displayName = 'TableCell';
107
108const TableCaption = ({
109 className,
110 ref,
111 ...props
112}: React.HTMLAttributes<HTMLTableCaptionElement> & {
113 ref?: React.Ref<HTMLTableCaptionElement>;
114}) => (
115 <caption ref={ref} className={cn('text-muted-foreground mt-4 text-sm', className)} {...props} />
116);
117TableCaption.displayName = 'TableCaption';
118
119const Table = Object.assign(TableRoot, {
120 Header: TableHeader,
121 Body: TableBody,
122 Footer: TableFooter,
123 Row: TableRow,
124 Head: TableHead,
125 Cell: TableCell,
126 Caption: TableCaption,
127});
128
129export { Table };
130export type { TableProps };