Skip to content

데이터 테이블 (Data Table)

DataTable 컴포넌트는 Headless UI 라이브러리 TanStack을 기반으로 구축된 테이블 컴포넌트입니다.

@tanstack/vue-table, @tanstack/vue-virtual을 사용하여 구현되었습니다.

display: gridgrid-template-columns를 사용하여 컬럼 리사이징이 가능하도록 구현되었습니다.

이름
이메일
권한
부서
상태
마지막 접속

주요 기능 (Features)

  • 행 선택 (Row Selection): 단일 및 다중 행 선택을 지원하며, 외부에서 selection 값이 변경되면 선택 행으로 자동 스크롤됩니다. smoothScroll prop으로 스크롤 애니메이션 여부를 제어할 수 있습니다.
  • 정렬 (Sorting): UI 인디케이터를 포함한 단일 컬럼 정렬 (오름차순/내림차순)을 지원합니다.
  • 컬럼 리사이징 (Column Resizing): 테이블 헤더에서만 컬럼 리사이징을 지원하며, 드래그 중에는 바디 영역에도 세로 가이드 라인이 표시됩니다.
  • 컬럼 표시 제어 (Column Visibility): 프로그래밍 방식으로 컬럼의 표시 여부를 제어할 수 있습니다.
  • 커스텀 셀 (Custom Cells): Vue 컴포넌트 또는 렌더 함수(Render functions)를 사용하여 셀 렌더링을 완전히 커스터마이징할 수 있습니다.
  • 로딩 및 빈 상태 (Loading & Empty States): 로딩 중이거나 데이터가 없을 때를 처리하기 위한 전용 Slot과 Prop을 제공합니다.
  • 툴팁 지원 (Tooltip Support): 내용이 길어 잘리는 경우(Ellipsis), 툴팁을 통해 전체 내용을 확인할 수 있습니다.
  • 다양한 크기 (Sizes): mini, small, normal (기본), large 네 가지 크기를 지원합니다.
  • 행 높이 모드 (Row Height Mode): rowHeightMode prop으로 행 높이를 고정(fixed)하거나 내용에 따라 자동 조절(auto)할 수 있습니다.
  • 행 오버레이 (Row Overlay): row-overlay 슬롯을 사용하여 각 행의 우측에 오버레이 콘텐츠(버튼, 드롭다운 등)를 표시할 수 있습니다.

테이블 변형 (Table Variant)

variant prop을 사용하여 테이블의 시각적 스타일을 inset (기본값) 또는 attached 모드로 설정할 수 있습니다.

Inset (Default)

이름
이메일
권한
부서
상태
마지막 접속

Attached

이름
이메일
권한
부서
상태
마지막 접속

테이블 크기 (Table Size)

size prop을 사용하여 테이블 행의 높이와 폰트 크기를 조절할 수 있습니다.

Mini

이름
이메일
권한
부서
상태
마지막 접속

Small

이름
이메일
권한
부서
상태
마지막 접속

Normal (Default)

이름
이메일
권한
부서
상태
마지막 접속

Large

이름
이메일
권한
부서
상태
마지막 접속

Row Selection (행 선택)

selection-mode prop으로 선택 모드를 설정할 수 있습니다.

  • 'none': 선택 불가 (기본값)
  • 'single': 단일 행 선택
  • 'checkbox': 체크박스를 통한 다중 행 선택

selection prop 또는 v-model:selection으로 선택 행을 외부에서 제어할 수 있습니다. 외부 값이 변경되어 선택 행이 바뀌면, 테이블은 해당 행이 보이도록 자동 스크롤합니다. 기본적으로 부드러운 스크롤이 적용되며, smoothScrollfalse로 설정하면 즉시 스크롤합니다. 이 설정은 키보드로 행 선택을 이동할 때도 유용합니다. 선택된 행이 뷰포트의 가장 아래쪽에 있는 상태에서 아래 방향키를 누르면, 다음 선택 행이 뷰포트의 위쪽에 보이도록 뷰포트 크기만큼 이동하는 페이지 단위 스크롤처럼 동작합니다. 체크박스 다중 선택에서는 전달된 배열에서 처음 매칭된 행을 기준으로 스크롤합니다.

Single Selection (단일 선택)

기본적인 단일 선택 모드입니다. 행을 클릭하여 선택합니다.

이름
이메일
권한
부서
상태
마지막 접속
vue
<template>
    <DataTable
        :data="data"
        :columns="columns"
        selection-mode="single"
        @update:selection="handleRowSelection"
    />
</template>

Checkbox Selection (체크박스 선택)

selection-mode="checkbox"를 설정하면 첫 번째 컬럼에 체크박스가 자동으로 추가됩니다.

이름
이메일
권한
부서
상태
마지막 접속
vue
<template>
    <DataTable
        :data="data"
        :columns="columns"
        selection-mode="checkbox"
        @update:selection="handleRowSelection"
    />
</template>

Expand Row (행 확장)

단일 선택 모드(selection-mode="single")일 때, 이미 선택된 행을 한 번 더 클릭하면 행이 확장되면서 추가 정보를 보여주는 기능을 지원합니다. expanded-row 슬롯을 사용하여 확장 영역의 내용을 정의할 수 있습니다.

이름
이메일
권한
부서
상태
마지막 접속
vue
<script setup lang="ts">
import { DataTable } from '@jennifersoft/vue-components-v2';

const subColumns = [
    { accessorKey: 'date', header: '접속 일자', size: 120 },
    { accessorKey: 'ip', header: 'IP 주소', size: 150 },
    { accessorKey: 'status', header: '상태', size: 100 },
];

const subData = [
    { date: '2023-10-01', ip: '192.168.1.1', status: 'Success' },
    { date: '2023-10-05', ip: '192.168.1.10', status: 'Failed' },
    { date: '2023-10-12', ip: '10.0.0.5', status: 'Success' },
];
</script>

<template>
    <DataTable :data="data" :columns="columns" selection-mode="single">
        <template #expanded-row="{ row }">
            <div class="expanded-content">
                <p style="margin-bottom: 8px;">
                    <strong>상세 정보:</strong> {{ row.name }}님의 접속 이력
                </p>
                <DataTable :data="subData" :columns="subColumns" size="mini" />
            </div>
        </template>
    </DataTable>
</template>

<style scoped>
.expanded-content {
    padding: 16px;
    background-color: var(--gray-50);
    border-bottom: 1px solid var(--gray-200);
}
</style>

컬럼 라인 (Column Lines)

show-column-lines prop을 사용하여 데이터 셀의 세로 구분선을 표시할 수 있습니다.

이름
이메일
권한
부서
상태
마지막 접속

행 라인 (Row Lines)

show-row-lines: false prop을 사용하여 데이터 행의 가로 구분선을 표시하지 않을 수 있습니다.

이름
이메일
권한
부서
상태
마지막 접속

스트라이프 행 (Striped Rows)

striped-rows prop을 사용하여 홀수 행에 배경색을 적용하여 가독성을 높일 수 있습니다.

이름
이메일
권한
부서
상태
마지막 접속

헤더 숨기기 (Hide Header)

hide-header prop을 사용하여 테이블의 컬럼 헤더를 숨길 수 있습니다.

행 높이 모드 (Row Height Mode)

row-height-mode prop을 사용하여 행의 높이 동작을 제어할 수 있습니다.

  • fixed (기본값): 행 높이가 고정되며, 내용이 길면 말줄임(...)으로 표시됩니다.
  • auto: 행 높이가 내용에 따라 자동으로 조절되어 여러 줄의 텍스트를 표시할 수 있습니다.
vue
<template>
    <DataTable :data="data" :columns="columns" row-height-mode="auto" />
</template>

주의사항

row-height-mode="auto"일 때는 가상 스크롤의 smoothScroll 옵션이 자동으로 비활성화됩니다. 행 높이가 가변적이면 부드러운 스크롤 계산이 정확하지 않을 수 있기 때문입니다.

사용법 (Usage)

vue
<script setup lang="ts">
import { ref } from 'vue';
import { DataTable } from '@jennifersoft/vue-components-v2';
import type { ColumnDef } from '@tanstack/vue-table';

interface User {
    id: number;
    name: string;
    email: string;
    role: string;
    department: string;
    status: string;
    lastLogin: string;
}

const data = ref<User[]>([
    {
        id: 1,
        name: '김철수',
        email: 'chulsu.kim@example.com',
        role: '관리자',
        department: '개발팀',
        status: '활성',
        lastLogin: '2024-01-15',
    },
    {
        id: 2,
        name: '이영희',
        email: 'younghee.lee@example.com',
        role: '사용자',
        department: '디자인팀',
        status: '휴식',
        lastLogin: '2024-01-20',
    },
    // ... 더 많은 데이터
]);

const columns: ColumnDef<User>[] = [
    { accessorKey: 'name', header: '이름', size: 100 },
    { accessorKey: 'email', header: '이메일', size: 100 },
    { accessorKey: 'role', header: '권한', size: 100 },
    { accessorKey: 'department', header: '부서', size: 100 },
    { accessorKey: 'status', header: '상태', size: 100 },
    { accessorKey: 'lastLogin', header: '마지막 접속', size: 100 },
];
</script>

<template>
    <DataTable :data="data" :columns="columns" />
</template>

컬럼 정의 (Column Definitions)

컬럼은 @tanstack/vue-tableColumnDef 타입을 사용하여 정의합니다.

타입 안전한 컬럼 정의 (Type-Safe Column Definition)

createColumnHelper를 사용하면 위에서 커스텀한 meta 속성(align)의 타입 추론 및 자동 완성 지원을 받을 수 있습니다.

typescript
import { createColumnHelper } from '@tanstack/vue-table';

const columnHelper = createColumnHelper<User>();

const columns = [
    columnHelper.accessor('name', {
        header: '이름',
        meta: {
            align: 'center', // 'left' | 'center' | 'right' 자동 완성 지원
        },
    }),
];

기본 컬럼 (Basic Column)

typescript
{
  accessorKey: 'status',
  header: '상태',
  size: 120, // 픽셀 단위 초기 크기
  minSize: 80, // 최소 크기
  maxSize: 200, // 최대 크기
  meta: {
      align: 'center', // 'left' | 'center' | 'right' (기본값: 'left')
      disableRowClick: false, // true이면 이 셀 클릭 시 행 선택이 발생하지 않음
      onCellClick: (cell, event) => { /* 셀 클릭 핸들러 */ }
  }
}

정렬 커스터마이징 (Sorting Customization)

DataTable은 단일 컬럼 정렬만 지원합니다. 헤더 클릭으로 정렬할 수 있으며, defaultSort prop을 사용하면 처음 표시될 정렬 컬럼과 방향을 지정할 수 있습니다. defaultSort.id는 컬럼의 id 또는 accessorKey와 일치해야 합니다.

이름
이메일
권한
부서
상태
마지막 접속
vue
<script setup lang="ts">
const defaultSort = {
    id: 'lastLogin',
    desc: true,
};
</script>

<template>
    <DataTable :data="data" :columns="columns" :default-sort="defaultSort" />
</template>

기본적으로 테이블은 데이터의 타입에 따라 정렬을 수행하지만, cell 포맷팅으로 인해 표시되는 값과 실제 정렬 기준값이 다른 경우(예: 1,000 ms 문자열로 표시되지만 숫자로 정렬해야 하는 경우) sortingFn을 사용하여 정렬 방식을 지정할 수 있습니다.

  • basic: 표준 JavaScript 비교 연산자를 사용합니다. (숫자, 문자열 등)
  • datetime: 날짜 객체를 정렬합니다.
  • alphanumeric: 문자와 숫자가 섞인 문자열을 정렬합니다.
  • Custom Function: 직접 정렬 로직을 작성할 수 있습니다.
typescript
{
  accessorKey: 'responseTime',
  header: '응답 시간',
  cell: (info) => `${info.getValue().toLocaleString()} ms`, // 포맷팅된 문자열 표시
  sortingFn: 'basic', // 원본 데이터(숫자) 기준으로 정렬
}

텍스트 정렬 (Text Alignment)

컬럼 정의의 meta.align 속성을 사용하여 헤더와 셀의 텍스트 정렬을 제어할 수 있습니다.

  • left: 왼쪽 정렬 (기본값)
  • center: 가운데 정렬
  • right: 오른쪽 정렬
이름 (Left)
권한 (Center)
금액 (Right)
vue
<script setup lang="ts">
import { DataTable } from '@jennifersoft/vue-components-v2';
import { ref } from 'vue';

const columnsWithAlignment = [
    {
        accessorKey: 'name',
        header: '이름 (Left)',
        size: 100,
        meta: { align: 'left' },
    },
    {
        accessorKey: 'role',
        header: '권한 (Center)',
        size: 100,
        meta: { align: 'center' },
    },
    {
        accessorKey: 'price',
        header: '금액 (Right)',
        size: 100,
        meta: { align: 'right' },
    },
];

const dataWithAlignment = ref([
    { id: 1, name: 'Items A', role: 'Admin', price: '1,000,000' },
    { id: 2, name: 'Items B', role: 'User', price: '500,000' },
    { id: 3, name: 'Items C', role: 'Guest', price: '10,000' },
]);
</script>

<template>
    <DataTable
        :data="dataWithAlignment"
        :columns="columnsWithAlignment"
        :enable-row-selection="true"
    />
</template>

셀 슬롯 (Cell Slots / Templates)

prop을 통한 렌더 함수 정의 외에도, Vue의 슬롯 기능을 사용하여 셀 내용을 커스터마이징할 수 있습니다. 컬럼의 id 또는 accessorKey를 기반으로 cell-{columnId} 형식의 슬롯 이름을 사용합니다. datacolumns를 같은 제네릭 타입으로 선언하면 cell-* 슬롯과 expanded-row 슬롯의 row가 해당 타입으로 추론됩니다.

이름
이메일
권한
부서
상태
마지막 접속
vue
<script setup lang="ts">
import { DataTable, Badge } from '@jennifersoft/vue-components-v2';
import type { ColumnDef } from '@jennifersoft/vue-components-v2';

interface User {
    id: number;
    name: string;
    status: '활성' | '휴식' | '차단';
}

const data: User[] = [
    { id: 1, name: '김철수', status: '활성' },
    { id: 2, name: '이영희', status: '휴식' },
];

const columns: ColumnDef<User>[] = [
    { accessorKey: 'name', header: '이름', size: 100 },
    { accessorKey: 'status', header: '상태', size: 100 },
];

const getBadgeColor = (status: User['status']) => {
    switch (status) {
        case '활성':
            return 'green-light';
        case '휴식':
            return 'orange-light';
        default:
            return 'red-light';
    }
};
</script>

<template>
    <DataTable :data="data" :columns="columns">
        <!-- status 컬럼 커스터마이징 -->
        <template #cell-status="{ value }">
            <Badge
                :color="getBadgeColor(value as User['status'])"
                :text="value"
            />
        </template>

        <!-- row는 User 타입으로 추론됩니다. -->
        <template #cell-name="{ value, row }">
            <strong>{{ value }}</strong> (ID: {{ row.id }})
        </template>
    </DataTable>
</template>

슬롯 타입 (Slot Types)

DataTable은 동적 셀 슬롯과 확장 행 슬롯의 타입을 제공합니다. 직접 사용하는 경우에는 대부분 자동 추론만으로 충분합니다. DataTable을 감싸는 래퍼 컴포넌트를 만들거나 슬롯을 다시 전달해야 하는 경우에는 패키지에서 export하는 슬롯 타입을 사용할 수 있습니다.

typescript
import type {
    DataTableCellSlotProps,
    DataTableExpandedRowSlotProps,
    DataTableRowOverlaySlotProps,
    DataTableSlots,
} from '@jennifersoft/vue-components-v2';

interface User {
    id: number;
    name: string;
    status: string;
}

type UserCellSlotProps = DataTableCellSlotProps<User>;
type UserExpandedRowSlotProps = DataTableExpandedRowSlotProps<User>;
type UserRowOverlaySlotProps = DataTableRowOverlaySlotProps<User>;
type UserTableSlots = DataTableSlots<User>;

슬롯별 props는 다음과 같습니다.

SlotProps
cell-{id}{ row: T; cell: Cell<T, any>; value: any; index: number }
expanded-row{ row: T; tableRow: Row<T> }
row-overlay{ row: T; tableRow: Row<T>; index: number }
loading-state없음
empty-state없음

행 오버레이 (Row Overlay)

row-overlay 슬롯을 사용하여 각 행의 우측에 오버레이 콘텐츠를 표시할 수 있습니다. 이 기능은 행별 액션 버튼이나 드롭다운 메뉴를 구현할 때 유용합니다.

관련 props:

  • rowOverlayWidth: 오버레이 영역의 너비(px)를 지정합니다. 이 값만큼 테이블 컬럼 영역이 줄어듭니다.
  • rowOverlayPlacement: 오버레이의 수직 정렬 위치를 지정합니다. 'top', 'center'(기본값), 'bottom' 중 선택할 수 있습니다.
vue
<script setup lang="ts">
import { DataTable, Button, Dropdown } from '@jennifersoft/vue-components-v2';

const handleEdit = (user: User) => {
    console.log('Edit:', user);
};

const handleDelete = (user: User) => {
    console.log('Delete:', user);
};
</script>

<template>
    <DataTable
        :data="data"
        :columns="columns"
        :row-overlay-width="120"
        row-overlay-placement="center"
    >
        <template #row-overlay="{ row }">
            <div style="display: flex; gap: 4px;">
                <Button size="small" @click="handleEdit(row)">편집</Button>
                <Button size="small" variant="danger" @click="handleDelete(row)"
                    >삭제</Button
                >
            </div>
        </template>
    </DataTable>
</template>

TIP

row-overlay 슬롯 내의 버튼 클릭은 자동으로 행 선택 이벤트로 전파되지 않습니다.

컬럼 표시 제어 (Column Visibility)

column-visibility prop을 사용하여 특정 컬럼만 표시할 수 있습니다. VisibilityState 객체 ({ [columnId]: boolean })를 전달해야 합니다.

이름
이메일
권한
부서
상태
마지막 접속
vue
<script setup lang="ts">
import { ref } from 'vue';
import { DataTable } from '@jennifersoft/vue-components-v2';
import type { VisibilityState } from '@tanstack/vue-table';

const allColumnIds = ['select', 'name', 'email', 'role', 'status'];
const visibleCols = ref<VisibilityState>({});

const data = ref([
    /* ... */
]);
const columns = [
    /* ... */
];
</script>

<template>
    <div style="display: flex; gap: 8px;">
        <label v-for="col in allColumnIds" :key="col">
            <input
                type="checkbox"
                :checked="visibleCols[col] !== false"
                @change="
                    (e) =>
                        (visibleCols = {
                            ...visibleCols,
                            [col]: (e.target as HTMLInputElement).checked,
                        })
                "
            />
            {{ col }}
        </label>
    </div>

    <DataTable
        :data="data"
        :columns="columns"
        :column-visibility="visibleCols"
    />
</template>

스켈레톤 로딩 (Skeleton Loading)

skeleton prop을 사용하여 데이터 로딩 중임을 나타내는 스켈레톤 UI를 표시할 수 있습니다.

Toggle Skeleton
이름
이메일
권한
부서
상태
마지막 접속
vue
<script setup lang="ts">
import { ref } from 'vue';
import { DataTable, ToggleSwitch } from '@jennifersoft/vue-components-v2';

const showSkeleton = ref(true);

const allColumnIds = ['select', 'name', 'email', 'role', 'status'];
const visibleCols = ref(['select', 'name', 'email', 'role', 'status']);

const data = ref([
    /* ... */
]);
const columns = [
    /* ... */
];
</script>

<template>
    <div style="display: flex; align-items: center; gap: 8px;">
        <span>Toggle Skeleton:</span>
        <ToggleSwitch v-model="showSkeleton" />
    </div>

    <DataTable :data="data" :columns="columns" :skeleton="showSkeleton" />
</template>

스타일링 (Styling)

이 컴포넌트는 유연성을 확보하고 리사이즈 핸들의 정확한 정렬을 보장하기 위해 native <table> 요소 대신 div 기반의 구조와 CSS Grid 레이아웃을 사용합니다.

  • CSS Grid & Variables: 성능 최적화를 위해 CSS Grid를 사용하며, --grid-template-columns CSS 변수를 통해 컬럼 너비를 효율적으로 관리합니다.
  • 클래스 명명 (Class naming): BEM 컨벤션을 따릅니다 (예: js-data-table, js-data-table__header).
  • 리사이징 (Resizing): 리사이즈 핸들은 헤더 셀 경계에서만 표시되며, 클릭 가능한 핸들 영역은 8px입니다. 드래그 중에는 바디 영역에 2px 세로 가이드 라인이 표시됩니다.

컬럼 리사이징 동작 (Column Resizing Behavior)

이 테이블은 전체 너비가 고정된 상태에서 컬럼의 비율을 조정하는 방식을 사용합니다. 사용자는 테이블 헤더의 컬럼 경계에 있는 리사이즈 핸들을 드래그하여 컬럼 너비를 변경할 수 있습니다. 바디 영역에서는 리사이즈 조작이 불가능하며, 드래그 중인 경계를 확인할 수 있도록 바디 영역에 세로 가이드 라인만 표시됩니다.

사용자가 컬럼의 리사이즈 핸들을 드래그하면 다음과 같이 동작합니다:

  1. 그룹 분할: 리사이즈 핸들을 기준으로 좌측 그룹(핸들이 속한 컬럼 포함)과 우측 그룹으로 나뉩니다.
  2. 비율 유지: 핸들을 이동하여 변경된 너비만큼, 각 그룹 내의 컬럼들이 현재 비율을 유지하며 동시에 늘어나거나 줄어듭니다.
  3. 전체 너비 고정: 테이블 전체의 너비는 변하지 않습니다.

예를 들어, 3개의 컬럼 A | B | C가 있을 때 B의 오른쪽 핸들을 우측으로 드래그하면:

  • 좌측 그룹 (A, B): 너비가 증가하며, A와 B가 기존 비율대로 커집니다.
  • 우측 그룹 (C): 너비가 감소하며, C가 작아집니다.

이 방식은 반응형 레이아웃에서 컬럼 간의 상대적인 크기 균형을 유지하는 데 유리합니다.

가상 스크롤 (Virtual Scrolling)

대량의 데이터를 효율적으로 렌더링하기 위해 가상 스크롤(Virtual Scrolling)을 지원합니다. @tanstack/vue-virtual을 내부적으로 사용하여 뷰포트에 표시되는 행만 렌더링하므로, 수만 개의 행이 있어도 높은 성능을 유지합니다.

가상 스크롤을 사용하려면 테이블의 부모 컨테이너나 테이블 자체에 높이(height) 가 지정되어 있어야 합니다.

selection prop이 외부에서 변경되면 가상 스크롤 상태에서도 선택된 행의 현재 위치를 찾아 자동 스크롤합니다. 기본값인 smoothScroll=true에서는 부드럽게 이동하며, smoothScroll=false에서는 즉시 이동합니다. 키보드로 행을 이동할 때 선택된 행이 뷰포트의 가장 아래쪽에 있으면, 아래 방향키 입력 시 다음 선택 행이 뷰포트의 위쪽에 오도록 뷰포트 크기만큼 이동합니다.

이름
이메일
권한
부서
상태
마지막 접속
vue
<script setup lang="ts">
import { ref } from 'vue';
import { DataTable } from '@jennifersoft/vue-components-v2';

const virtualData = ref(
    Array.from({ length: 10000 }).map((_, i) => ({
        id: i,
        name: `User ${i}`,
        status: i % 2 === 0 ? 'Active' : 'Inactive',
        lastLogin: new Date().toISOString().split('T')[0],
    }))
);
</script>

<template>
    <DataTable
        :data="virtualData"
        :columns="columns"
        virtual-scroll
        :style="{ height: '400px' }"
        selection-mode="single"
    >
        <template #expanded-row="{ row }">
            <div class="expanded-content">
                <p>
                    <strong>상세 정보:</strong> 가상 스크롤 데이터
                    {{ row.name }}님의 상세 내용입니다.
                </p>
            </div>
        </template>
    </DataTable>
</template>

<style scoped>
.expanded-content {
    padding: 16px;
    background-color: var(--gray-50);
    border-bottom: 1px solid var(--gray-200);
}
</style>

Props

PropTypeDefaultDescription
dataT[]Required표시할 데이터 객체들의 배열입니다.
columnsColumnDef<T>[]Required컬럼 정의 설정입니다.
selectionT | T[]undefined선택된 행 데이터(v-model 지원). 외부에서 값이 변경되면 선택 행으로 자동 스크롤합니다.
selectionMode'none' | 'single' | 'checkbox''none'행 선택 모드를 설정합니다.
defaultSort{ id: string; desc: boolean }undefined처음 표시할 단일 정렬 조건입니다. id는 컬럼의 id 또는 accessorKey와 일치해야 하며, desctrue이면 내림차순입니다.
columnVisibilityVisibilityState{}컬럼의 표시 상태를 정의하는 객체입니다.
hideHeaderbooleanfalsetrue일 때 테이블의 컬럼 헤더를 숨깁니다.
skeletonbooleanfalsetrue일 때 로딩 스켈레톤(Skeleton) 상태를 표시합니다.
emptyTextstring'No Data'데이터 배열이 비어있을 때 표시할 텍스트입니다.
size'mini' | 'small' | 'normal' | 'large''normal'테이블의 크기(행 높이 및 폰트)를 설정합니다.
showColumnLinesbooleanfalsetrue일 때 데이터 셀의 세로 구분선을 표시합니다.
showHeaderSideBordersbooleanfalsetrue일 때 attached variant 헤더의 좌우 테두리를 표시합니다.
showRowLinesbooleantruetrue일 때 데이터 행의 가로 구분선을 표시합니다.
stripedRowsbooleanfalsetrue일 때 홀수 행에 배경색을 적용합니다.
variant'inset' | 'attached''inset'테이블의 시각적 스타일을 설정합니다.
smoothScrollbooleantrueselection 변경으로 선택 행까지 자동 스크롤할 때 부드러운 스크롤 애니메이션을 사용할지 설정합니다. false이면 즉시 스크롤하며, 키보드 이동 중 선택 행이 뷰포트 아래쪽 경계에 있을 때 아래 방향키 입력으로 뷰포트 크기만큼 이동하는 동작을 명확하게 보여줄 수 있습니다.
rowHeightMode'fixed' | 'auto''fixed'행 높이 모드를 설정합니다. 'fixed'는 고정 높이, 'auto'는 내용에 따라 자동 조절됩니다.
rowOverlayWidthnumber0행 오버레이 영역의 너비(px)입니다. 이 값만큼 테이블 컬럼 영역이 줄어듭니다.
rowOverlayPlacement'top' | 'center' | 'bottom''center'행 오버레이의 수직 정렬 위치입니다.

Events

EventPayloadDescription
update:selectionT | T[]행 선택 상태가 변경될 때 발생합니다.
update:columnVisibilityVisibilityState컬럼 표시 상태가 변경될 때 발생합니다.

Slots

Slot NamePropsDescription
loading-state없음로딩 오버레이 영역에 표시할 커스텀 콘텐츠입니다.
empty-state없음데이터가 없을 때 표시할 커스텀 콘텐츠입니다.
cell-{id}{ row: T; cell: Cell<T, any>; value: any; index: number }특정 컬럼의 셀 내용을 커스터마이징합니다.
expanded-row{ row: T; tableRow: Row<T> }선택된 행 다시 클릭시 보여지는 확장 콘텐츠입니다.
row-overlay{ row: T; tableRow: Row<T>; index: number }각 행의 우측에 표시되는 오버레이 콘텐츠입니다. rowOverlayWidth와 함께 사용합니다.