Skip to content

Commit d647df7

Browse files
committed
feat: Table 컴포넌트 구현
1 parent 957aa8b commit d647df7

File tree

3 files changed

+109
-4
lines changed

3 files changed

+109
-4
lines changed

.husky/pre-commit

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
#!/usr/bin/env sh
2-
. "$(dirname -- "$0")/_/husky.sh"
3-
41
npx lint-staged

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"lint": "eslint .",
1010
"preview": "vite preview",
1111
"postinstall": "node scripts/setup-git-hooks.cjs",
12-
"prepare": "husky && husky install"
12+
"prepare": "husky"
1313
},
1414
"lint-staged": {
1515
"**/*.{js,jsx}": [

src/components/Table.tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import {
2+
HTMLAttributes,
3+
ReactNode,
4+
TableHTMLAttributes,
5+
TdHTMLAttributes,
6+
} from "react";
7+
8+
import { cn } from "@/utils/cn";
9+
10+
interface TableProps<T> extends TableHTMLAttributes<HTMLTableElement> {
11+
data: T[];
12+
headRow: () => ReactNode;
13+
bodyRow: (params: T) => ReactNode;
14+
footerRow?: () => ReactNode;
15+
}
16+
17+
function Table<T>({
18+
data,
19+
className,
20+
headRow,
21+
bodyRow,
22+
footerRow,
23+
...props
24+
}: TableProps<T>) {
25+
return (
26+
<div className="rounded-lg border-[1px] border-gray-200 text-black overflow-hidden">
27+
{/* ───── 스크롤이 필요한 영역 ───── */}
28+
<div className="overflow-x-auto">
29+
<table
30+
className={cn(
31+
"table-fixed min-w-full text-left border-collapse",
32+
className,
33+
)}
34+
{...props}
35+
>
36+
<thead className="bg-red-50">{headRow()}</thead>
37+
<tbody className="bg-white">{data.map(bodyRow)}</tbody>
38+
</table>
39+
</div>
40+
41+
{/* ──── 스크롤과 무관한 하단 영역 ───── */}
42+
{footerRow && (
43+
<table className="w-full border-collapse">
44+
<tbody>{footerRow()}</tbody>
45+
</table>
46+
)}
47+
</div>
48+
);
49+
}
50+
51+
interface TrProps extends HTMLAttributes<HTMLTableRowElement> {
52+
showLastBottomBorder?: boolean;
53+
}
54+
55+
function Tr({ children, className, showLastBottomBorder, ...props }: TrProps) {
56+
const tableRowClassName = cn(
57+
showLastBottomBorder ? "border-b-[1px]" : "not-last:border-b-[1px]",
58+
"border-gray-20",
59+
className,
60+
);
61+
62+
return (
63+
<tr className={tableRowClassName} {...props}>
64+
{children}
65+
</tr>
66+
);
67+
}
68+
69+
function Th({
70+
children,
71+
className,
72+
...props
73+
}: TdHTMLAttributes<HTMLTableCellElement>) {
74+
const thClassName = cn(
75+
"px-3.5 py-3 text-sm font-normal",
76+
"first:sticky left-0 border-gray-20 z-10 bg-red-50",
77+
className,
78+
);
79+
80+
return (
81+
<th className={thClassName} {...props}>
82+
{children}
83+
</th>
84+
);
85+
}
86+
87+
interface TdProps extends TdHTMLAttributes<HTMLTableCellElement> {
88+
noSticky?: boolean;
89+
}
90+
91+
function Td({ children, className, noSticky, ...props }: TdProps) {
92+
const tdClassName = cn(
93+
"px-3.5 py-3 break-words whitespace-normal",
94+
noSticky ? "" : "first:sticky left-0 z-10 bg-white first:whitespace-nowrap",
95+
className,
96+
);
97+
return (
98+
<td className={tdClassName} {...props}>
99+
{children}
100+
</td>
101+
);
102+
}
103+
104+
Table.Tr = Tr;
105+
Table.Th = Th;
106+
Table.Td = Td;
107+
108+
export default Table;

0 commit comments

Comments
 (0)