Appearance
ui Component Style Overrides
The ui prop accepts a slot-class map that deep-merges with the theme, allowing you to customize root, th, td, tbody and other partial styles:
| 姓名 | 部门 | 岗位 | 职级 |
|---|---|---|---|
李勇 | 产品 | UI 设计师 | P8 |
王超 | 市场 | 运营专员 | P7 |
陈娜 | 设计 | 全栈工程师 | P6 |
刘丽 | 运营 | 数据分析师 | P5 |
杨军 | 研发 | 后端工程师 | P8 |
黄涛 | 产品 | 产品经理 | P7 |
<script setup lang="ts">
import type { DataTableColumn, DataTableProps } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'
const data = makePeople(6)
const columns: DataTableColumn<Person>[] = [
{ accessorKey: 'name', header: '姓名' },
{ accessorKey: 'department', header: '部门' },
{ accessorKey: 'role', header: '岗位' },
{ accessorKey: 'level', header: '职级' }
]
const customUi: DataTableProps<Person>['ui'] = {
root: 'rounded-xl shadow-sm',
th: 'bg-primary/10 text-primary font-semibold',
td: 'py-3 text-default',
tbody: 'divide-y divide-default'
}
</script>
<template>
<MDataTable :data="data" :columns="columns" :ui="customUi" />
</template>
paginationUi Pagination Style Overrides
paginationUi.ui accepts Pagination theme slots and can override root, summary, actions, selectedCount and other partial classes. paginationUi also supports configuring show and pageSizes:
| 姓名 | 部门 | 岗位 | |
|---|---|---|---|
李勇 | 产品 | UI 设计师 | |
王超 | 市场 | 运营专员 | |
陈娜 | 设计 | 全栈工程师 | |
刘丽 | 运营 | 数据分析师 |
<script setup lang="ts">
import type { DataTableColumn, PaginationState, RowSelectionState } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'
const data = makePeople(8)
const selection = ref<RowSelectionState>({ P0002: true })
const pagination = ref<PaginationState>({ pageIndex: 0, pageSize: 4 })
const columns: DataTableColumn<Person>[] = [
{ type: 'selection', mode: 'multiple' },
{ accessorKey: 'name', header: '姓名' },
{ accessorKey: 'department', header: '部门' },
{ accessorKey: 'role', header: '岗位' }
]
</script>
<template>
<MDataTable
v-model:row-selection="selection"
v-model:pagination="pagination"
:data="data"
:columns="columns"
row-key="id"
:pagination-ui="{
show: true,
pageSizes: [4, 8],
ui: {
root: 'border-t border-default pt-3 mt-1',
summary: 'text-primary font-medium',
actions: 'gap-4',
selectedCount: 'text-success'
}
}"
/>
</template>
Stripe and Borders
stripe controls the background color of even rows; bordered supports both boolean and object forms — the object form lets you customize vertical borders via color, width and style:
| 姓名 | 部门 | 岗位 | 职级 |
|---|---|---|---|
李勇 | 产品 | UI 设计师 | P8 |
王超 | 市场 | 运营专员 | P7 |
陈娜 | 设计 | 全栈工程师 | P6 |
刘丽 | 运营 | 数据分析师 | P5 |
杨军 | 研发 | 后端工程师 | P8 |
黄涛 | 产品 | 产品经理 | P7 |
<script setup lang="ts">
import type { DataTableColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'
const data = makePeople(6)
const columns: DataTableColumn<Person>[] = [
{ accessorKey: 'name', header: '姓名' },
{ accessorKey: 'department', header: '部门' },
{ accessorKey: 'role', header: '岗位' },
{ accessorKey: 'level', header: '职级' }
]
</script>
<template>
<MDataTable :data="data" :columns="columns" />
</template>
density Visual Density
density switches between three cell-padding presets: compact, normal and comfortable:
| 姓名 | 部门 | 岗位 | 职级 |
|---|---|---|---|
李勇 | 产品 | UI 设计师 | P8 |
王超 | 市场 | 运营专员 | P7 |
陈娜 | 设计 | 全栈工程师 | P6 |
刘丽 | 运营 | 数据分析师 | P5 |
杨军 | 研发 | 后端工程师 | P8 |
黄涛 | 产品 | 产品经理 | P7 |
<script setup lang="ts">
import type { DataTableColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'
const data = makePeople(6)
const columns: DataTableColumn<Person>[] = [
{ accessorKey: 'name', header: '姓名' },
{ accessorKey: 'department', header: '部门' },
{ accessorKey: 'role', header: '岗位' },
{ accessorKey: 'level', header: '职级' }
]
</script>
<template>
<MDataTable :data="data" :columns="columns" />
</template>
fitContent Fit-Content Width
fitContent makes the table width determined by column widths rather than stretching to fill the parent container — suitable for compact utility tables:
| 工号 | 姓名 | 部门 | 职级 |
|---|---|---|---|
P0001 | 李勇 | 产品 | P8 |
P0002 | 王超 | 市场 | P7 |
P0003 | 陈娜 | 设计 | P6 |
P0004 | 刘丽 | 运营 | P5 |
<script setup lang="ts">
import type { DataTableColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'
const data = makePeople(4)
const columns: DataTableColumn<Person>[] = [
{ accessorKey: 'id', header: '工号' },
{ accessorKey: 'name', header: '姓名' },
{ accessorKey: 'department', header: '部门' },
{ accessorKey: 'level', header: '职级' }
]
</script>
<template>
<MDataTable :data="data" :columns="columns" bordered />
</template>
emptyCell Empty-Value Placeholder
emptyCell supports a string, a function template (returning a VNode) and false, respectively for custom text, a custom node and disabling the placeholder entirely. A per-column emptyCell takes precedence over the global setting:
| 姓名 | 住址 | 简介 |
|---|---|---|
李勇 | — | 暂无 |
王超 | 深圳市南山区科技园南区高新南九道 9 号深圳湾科技生态园 10 栋 B 座 2301 | 负责风控与反作弊算法工程化,搭建过实时特征平台与规则引擎,覆盖支付、营销、社交多场景。 |
陈娜 | 广州市天河区珠江新城华夏路 16 号富力盈凯广场 38 楼 | 暂无 |
<script setup lang="ts">
import type { DataTableColumn, DataTableProps } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'
import { UBadge, UIcon } from '#components'
const vnodeCell: DataTableProps<Person>['emptyCell'] = () =>
h(UBadge, { color: 'neutral', variant: 'subtle', size: 'sm' }, () => [
h(UIcon, { name: 'i-lucide-minus', class: 'size-3' }),
' 暂无'
])
const columns: DataTableColumn<Person>[] = [
{ accessorKey: 'name', header: '姓名' },
{ accessorKey: 'address', header: '住址', size: 200 },
{ accessorKey: 'bio', header: '简介', size: 220, emptyCell: vnodeCell }
]
const data: Person[] = makePeople(3).map((p, i) => ({
...p,
bio: i % 2 === 0 ? '' : p.bio,
address: i % 3 === 0 ? '' : p.address
}))
</script>
<template>
<MDataTable :data="data" :columns="columns" />
</template>
sticky Sticky Header
sticky is enabled by default; disabling it makes the header scroll with the content. It requires a scroll container with a constrained height (e.g. ui.root: 'max-h-[40vh]'):
| 姓名 | 部门 | 岗位 | 职级 |
|---|---|---|---|
李勇 | 产品 | UI 设计师 | P8 |
王超 | 市场 | 运营专员 | P7 |
陈娜 | 设计 | 全栈工程师 | P6 |
刘丽 | 运营 | 数据分析师 | P5 |
杨军 | 研发 | 后端工程师 | P8 |
黄涛 | 产品 | 产品经理 | P7 |
赵伟 | 市场 | 前端工程师 | P6 |
吴敏 | 设计 | UI 设计师 | P5 |
周强 | 运营 | 运营专员 | P8 |
徐洋 | 研发 | 全栈工程师 | P7 |
孙明 | 产品 | 数据分析师 | P6 |
张芳 | 市场 | 后端工程师 | P5 |
李静 | 设计 | 产品经理 | P8 |
王磊 | 运营 | 前端工程师 | P7 |
陈勇 | 研发 | UI 设计师 | P6 |
刘超 | 产品 | 运营专员 | P5 |
杨娜 | 市场 | 全栈工程师 | P8 |
黄丽 | 设计 | 数据分析师 | P7 |
赵军 | 运营 | 后端工程师 | P6 |
吴涛 | 研发 | 产品经理 | P5 |
周伟 | 产品 | 前端工程师 | P8 |
徐敏 | 市场 | UI 设计师 | P7 |
孙强 | 设计 | 运营专员 | P6 |
张洋 | 运营 | 全栈工程师 | P5 |
李明 | 研发 | 数据分析师 | P8 |
王芳 | 产品 | 后端工程师 | P7 |
陈静 | 市场 | 产品经理 | P6 |
刘磊 | 设计 | 前端工程师 | P5 |
杨勇 | 运营 | UI 设计师 | P8 |
黄超 | 研发 | 运营专员 | P7 |
<script setup lang="ts">
import type { DataTableColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'
const columns: DataTableColumn<Person>[] = [
{ accessorKey: 'name', header: '姓名' },
{ accessorKey: 'department', header: '部门' },
{ accessorKey: 'role', header: '岗位' },
{ accessorKey: 'level', header: '职级' }
]
</script>
<template>
<MDataTable :data="makePeople(30)" :columns="columns" :ui="{ root: 'max-h-[40vh]' }" />
</template>
Introduction
A declarative data table based on TanStack Table, with column configuration, selection, expansion, tree data, pagination, load more and complete API reference.
Columns
Data column configuration — fixed columns, sorting, column pinning, column resize, text truncation, tooltips, visibility and functional per-column configuration.