Table
Table은 구조화된 데이터를 행과 열로 표시하는 컴파운드 컴포넌트입니다. 정렬, 스트라이프, 스티키 헤더 등을 지원하며 유연한 데이터 표시가 가능합니다.
3
Variants
3
Sizes
8
Sub-components
Pure
React
Playground
Preview
D
| Status | ||||
|---|---|---|---|---|
| PAY-7291 | Success | emily@example.com | Dec 20, 2030 | $316.00 |
| PAY-7292 | Success | james@example.com | Dec 20, 2030 | $242.00 |
| PAY-7293 | Pending | sarah@example.com | Dec 21, 2030 | $837.00 |
| PAY-7294 | Success | david@example.com | Dec 21, 2030 | $124.00 |
| PAY-7295 | Failed | olivia@example.com | Dec 22, 2030 | $495.00 |
| PAY-7296 | Success | michael@example.com | Dec 22, 2030 | $158.00 |
| PAY-7297 | Pending | sophie@example.com | Dec 23, 2030 | $721.00 |
| PAY-7298 | Success | daniel@example.com | Dec 24, 2030 | $89.00 |
| PAY-7299 | Failed | emma@example.com | Dec 24, 2030 | $362.00 |
| PAY-7300 | Success | ryan@example.com | Dec 25, 2030 | $550.00 |
Variant
Size
Options
<Table>
<Table.Header>
<Table.Row>
<Table.Head sortable sortDirection={sortKey === 'id' ? sortDir : null} onSort={() => handleSort('id')}>Invoice</Table.Head>
<Table.Head>Status</Table.Head>
<Table.Head sortable sortDirection={sortKey === 'email' ? sortDir : null} onSort={() => handleSort('email')}>Email</Table.Head>
<Table.Head sortable sortDirection={sortKey === 'date' ? sortDir : null} onSort={() => handleSort('date')}>Date</Table.Head>
<Table.Head align="right" sortable sortDirection={sortKey === 'amount' ? sortDir : null} onSort={() => handleSort('amount')}>Amount</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{sortedData.map(row => (
<Table.Row key={row.id} interactive>
<Table.Cell className="font-mono font-normal">{row.id}</Table.Cell>
<Table.Cell>
<Badge
variant="subtle"
color={statusMap[row.status].color}
size="sm"
>
{statusMap[row.status].label}
</Badge>
</Table.Cell>
<Table.Cell className="text-text-muted">{row.email}</Table.Cell>
<Table.Cell className="text-text-muted whitespace-nowrap">{row.date}</Table.Cell>
<Table.Cell align="right" className="font-mono">${row.amount.toFixed(2)}</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>Variants
Default
| Name | Role | Status |
|---|---|---|
| Bob | Designer | Away |
| Alice | Engineer | Active |
<Table>
<Table.Header>
<Table.Row>
<Table.Head>Name</Table.Head>
<Table.Head>Role</Table.Head>
<Table.Head>Status</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>Bob</Table.Cell>
<Table.Cell>Designer</Table.Cell>
<Table.Cell>
<Badge variant="subtle" color="warning" size="sm">Away</Badge>
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>Alice</Table.Cell>
<Table.Cell>Engineer</Table.Cell>
<Table.Cell>
<Badge variant="subtle" color="success" size="sm">Active</Badge>
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>Bordered
| Name | Role | Status |
|---|---|---|
| Bob | Designer | Away |
| Alice | Engineer | Active |
<Table variant="bordered">...</Table>Striped
| Name | Role | Status |
|---|---|---|
| Bob | Designer | Away |
| Alice | Engineer | Active |
| Charlie | PM | Meeting |
| Diana | DevOps | Active |
<Table variant="striped">...</Table>Sizes
smCell PY8px
Cell PX12px
폰트14px
defaultCell PY12px
Cell PX16px
폰트14px
lgCell PY16px
Cell PX24px
폰트16px
| Size | Cell PY | Cell PX | 본문 폰트 | 헤더 폰트 |
|---|---|---|---|---|
sm | 8px | 12px | 14px | 12px |
default | 12px | 16px | 14px | 12px |
lg | 16px | 24px | 16px | 14px |
API
Component Structure
Table— Pure React.Header.Body.Footer.RowProps.HeadProps.CellProps.Caption
.Header'<thead>' 래퍼.Body'<tbody>' 래퍼.Footer'<tfoot>' 래퍼.RowProps테이블 행 (interactive, selected).HeadProps헤더 셀 (align, sortable).CellProps데이터 셀 (align).Caption테이블 캡션Props
Table
size"default""sm" | "default" | "lg"행 밀도 (sm: 컴팩트 / default: 표준 / lg: 여유)
variant"default""default" | "bordered" | "striped"테이블의 시각적 스타일
stickyHeaderfalseboolean스크롤 시 헤더 고정
wrapperClassNameundefinedstring스크롤 래퍼에 추가할 className (예: "max-h-[400px]"). stickyHeader와 함께 사용
| Name | Type | Default | Description |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | 행 밀도 (sm: 컴팩트 / default: 표준 / lg: 여유) |
variant | "default" | "bordered" | "striped" | "default" | 테이블의 시각적 스타일 |
stickyHeader | boolean | false | 스크롤 시 헤더 고정 |
wrapperClassName | string | undefined | 스크롤 래퍼에 추가할 className (예: "max-h-[400px]"). stickyHeader와 함께 사용 |
Table.Row
interactivefalseboolean호버 시 하이라이트 효과 표시
selectedfalseboolean행 선택 상태를 나타냄 (data-selected 속성 부여)
| Name | Type | Default | Description |
|---|---|---|---|
interactive | boolean | false | 호버 시 하이라이트 효과 표시 |
selected | boolean | false | 행 선택 상태를 나타냄 (data-selected 속성 부여) |
Table.Head
align"left""left" | "center" | "right"텍스트 수평 정렬
sortablefalseboolean정렬 인디케이터 표시
sortDirectionnull"asc" | "desc" | null현재 정렬 방향
onSortundefined() => void정렬 클릭 시 콜백
sortIconBuilt-in SVG{ asc?: ReactNode, desc?: ReactNode, default?: ReactNode }정렬 아이콘 커스터마이즈 (부분 오버라이드 지원)
| Name | Type | Default | Description |
|---|---|---|---|
align | "left" | "center" | "right" | "left" | 텍스트 수평 정렬 |
sortable | boolean | false | 정렬 인디케이터 표시 |
sortDirection | "asc" | "desc" | null | null | 현재 정렬 방향 |
onSort | () => void | undefined | 정렬 클릭 시 콜백 |
sortIcon | { asc?: ReactNode, desc?: ReactNode, default?: ReactNode } | Built-in SVG | 정렬 아이콘 커스터마이즈 (부분 오버라이드 지원) |
Table.Cell
align"left""left" | "center" | "right"텍스트 수평 정렬
| Name | Type | Default | Description |
|---|---|---|---|
align | "left" | "center" | "right" | "left" | 텍스트 수평 정렬 |
Customization
sortIcon sortIcon prop으로 정렬 아이콘을 자유롭게 커스터마이즈할 수 있습니다. 부분 오버라이드도 지원합니다.
Lucide 아이콘으로 변경
| Role | ||
|---|---|---|
| Bob | bob@example.com | Designer |
| Alice | alice@example.com | Engineer |
| Charlie | charlie@example.com | PM |
import { ArrowUp, ArrowDown, ArrowUpDown } from 'lucide-react'
<Table.Head
sortable
sortIcon={{
asc: <ArrowUp className="icon-xs" />,
desc: <ArrowDown className="icon-xs" />,
default: <ArrowUpDown className="icon-xs" />,
}}
>
Name
</Table.Head>부분 오버라이드
| Grade | |
|---|---|
| 95 | A+ |
| 87 | B+ |
| 72 | C+ |
// Override only asc and desc (default keeps built-in icon)
<Table.Head sortable sortIcon={{ asc: <span>↑</span>, desc: <span>↓</span> }}>
Score
</Table.Head>Tip: 정렬 아이콘에는 icon-xs(14px)를 권장합니다. 테이블 헤더 텍스트 크기에 가장 적합합니다.
Anatomy
1
2
3
NameStatus
4
5
Alice Johnson
Active
Bob Smith
Inactive
6
Showing 2 of 2 resultsCell PY
12pxCell PX
16pxHead Font
12px1
Table
루트 컨테이너
2
Header Row
헤더 행
3
Header Cell
헤더 셀
4
Body Row
데이터 행
5
Body Cell
데이터 셀
6
Footer
푸터 행
Best Practices
✓
권장
- ✓명확한 헤더 라벨 사용하기
- ✓숫자 데이터는 우측 정렬하기
- ✓대용량 데이터에는 스티키 헤더 사용하기
- ✓접근성을 위해 caption 설정하기
✕
지양
- ✗열 수가 너무 많은 테이블 만들지 않기
- ✗레이아웃 목적으로 테이블 사용하지 않기
- ✗정렬 로직을 컴포넌트 내부에 넣지 않기
- ✗셀 내에 지나치게 복잡한 콘텐츠 넣지 않기
Accessibility
키보드 조작
Tab정렬 버튼 간 포커스 이동
Enter정렬 실행
ARIA / WCAG
- 시맨틱 HTML(table/thead/tbody/th/td) 사용
- 정렬 방향은 aria-sort로 알림
- 정렬 아이콘은 aria-hidden="true"
- caption으로 테이블 설명 지원