refactor: DataTable 컴포넌트 반응형 개선

- 툴바 모바일 세로 스택 레이아웃 전환
- 검색창 w-full sm:w-64 반응형 너비
- 테이블 overflow-x-auto 가로 스크롤 지원
- 페이지네이션 모바일 레이아웃 개선
- 하드코딩 색상(slate-*) → CSS 변수 기반 색상으로 교체

Made-with: Cursor
This commit is contained in:
DDD1542 2026-03-07 03:34:27 +09:00
parent 542fab2140
commit e29c7163ed
1 changed files with 20 additions and 19 deletions

View File

@ -65,17 +65,17 @@ export function DataTable<TData, TValue>({
return ( return (
<div className={cn("space-y-4", className)}> <div className={cn("space-y-4", className)}>
{/* 테이블 상단 툴바 */} {/* 테이블 상단 툴바 - 모바일: 세로 스택, sm 이상: 가로 배치 */}
<div className="flex items-center justify-between"> <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center space-x-2"> <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:space-x-2">
{searchable && ( {searchable && (
<div className="relative"> <div className="relative">
<Search className="absolute top-2.5 left-2.5 h-4 w-4 text-slate-500" /> <Search className="absolute top-2.5 left-2.5 h-4 w-4 text-muted-foreground" />
<Input <Input
placeholder={searchPlaceholder} placeholder={searchPlaceholder}
value={globalFilter ?? ""} value={globalFilter ?? ""}
onChange={(event) => setGlobalFilter(event.target.value)} onChange={(event) => setGlobalFilter(event.target.value)}
className="w-64 pl-8" className="w-full pl-8 sm:w-64"
/> />
</div> </div>
)} )}
@ -98,15 +98,15 @@ export function DataTable<TData, TValue>({
</div> </div>
</div> </div>
{/* 테이블 */} {/* 테이블 - 가로 스크롤 지원 */}
<div className="rounded-md border"> <div className="overflow-x-auto rounded-md border">
<Table> <Table>
<TableHeader> <TableHeader>
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}> <TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => { {headerGroup.headers.map((header) => {
return ( return (
<TableHead key={header.id} className="bg-slate-50"> <TableHead key={header.id} className="bg-muted/50">
{header.isPlaceholder ? null : ( {header.isPlaceholder ? null : (
<div <div
className={cn( className={cn(
@ -143,7 +143,7 @@ export function DataTable<TData, TValue>({
<TableRow <TableRow
key={row.id} key={row.id}
data-state={row.getIsSelected() && "selected"} data-state={row.getIsSelected() && "selected"}
className={cn(onRowClick ? "cursor-pointer hover:bg-slate-50" : "")} className={cn(onRowClick ? "cursor-pointer hover:bg-muted/50" : "")}
onClick={() => onRowClick?.(row.original)} onClick={() => onRowClick?.(row.original)}
> >
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
@ -162,16 +162,17 @@ export function DataTable<TData, TValue>({
</Table> </Table>
</div> </div>
{/* 페이지네이션 */} {/* 페이지네이션 - 모바일: 세로 스택, sm 이상: 가로 배치 */}
<div className="flex items-center justify-between px-2"> <div className="flex flex-col gap-3 px-2 sm:flex-row sm:items-center sm:justify-between">
<div className="flex-1 text-sm text-slate-600"> <div className="text-center text-sm text-muted-foreground sm:text-left">
{table.getFilteredSelectedRowModel().rows.length} {table.getFilteredRowModel().rows.length} {table.getFilteredSelectedRowModel().rows.length} {table.getFilteredRowModel().rows.length}
</div> </div>
<div className="flex items-center space-x-6 lg:space-x-8"> <div className="flex flex-col items-center gap-3 sm:flex-row sm:gap-6 lg:gap-8">
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<p className="text-sm font-medium"> </p> {/* 모바일에서 "페이지당 행 수" 텍스트 숨김 */}
<p className="hidden text-sm font-medium sm:block"> </p>
<select <select
className="h-8 w-16 rounded border border-slate-300 text-sm" className="h-8 w-16 rounded border border-input text-sm"
value={table.getState().pagination.pageSize} value={table.getState().pagination.pageSize}
onChange={(e) => { onChange={(e) => {
table.setPageSize(Number(e.target.value)); table.setPageSize(Number(e.target.value));
@ -184,10 +185,10 @@ export function DataTable<TData, TValue>({
))} ))}
</select> </select>
</div> </div>
<div className="flex w-24 items-center justify-center text-sm font-medium"> <div className="flex items-center gap-1">
{table.getState().pagination.pageIndex + 1} / {table.getPageCount()} <div className="flex w-24 items-center justify-center text-sm font-medium">
</div> {table.getState().pagination.pageIndex + 1} / {table.getPageCount()}
<div className="flex items-center space-x-2"> </div>
<Button <Button
variant="outline" variant="outline"
className="h-8 w-8 p-0" className="h-8 w-8 p-0"