Columns

View source
Data column configuration — fixed columns, sorting, column pinning, column resize, text truncation, tooltips, visibility and functional per-column configuration.

fixed Fixed Columns

column.fixed pins a column to either side of the table, keeping it visible during horizontal scrolling:

工号姓名岗位地址邮箱薪资
P0001
李勇
UI 设计师
北京市海淀区中关村大街 27 号中关村大厦 A 座 1502
user1@movk.dev
¥8,257
P0002
王超
运营专员
深圳市南山区科技园南区高新南九道 9 号深圳湾科技生态园 10 栋 B 座 2301
user2@movk.dev
¥8,514
P0003
陈娜
全栈工程师
广州市天河区珠江新城华夏路 16 号富力盈凯广场 38 楼
user3@movk.dev
¥8,771
P0004
刘丽
数据分析师
杭州市余杭区文一西路 969 号阿里巴巴西溪园区 6 号楼 318
user4@movk.dev
¥9,028
P0005
杨军
后端工程师
成都市高新区天府大道中段 1199 号天府软件园 D 区 5 号楼 1207
user5@movk.dev
¥9,285
P0006
黄涛
产品经理
南京市建邺区江东中路 222 号高科荣域大厦 19 层
user6@movk.dev
¥9,542
P0007
赵伟
前端工程师
武汉市洪山区光谷大道 70 号光谷国际企业中心 3 期 B 座 1808
user7@movk.dev
¥9,799
P0008
吴敏
UI 设计师
上海市浦东新区张江高科技园区博云路 2 号 IBM 大厦 7 层 708
user8@movk.dev
¥10,056
<script setup lang="ts">
import type { DataTableColumn, DataTableDataColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(8)
const moneyCell: DataTableDataColumn<Person>['cell'] = ({ getValue }) => `¥${getValue<number>().toLocaleString()}`

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'id', header: '工号', fixed: 'left', size: 100 },
  { accessorKey: 'name', header: '姓名', fixed: 'left', size: 120 },
  { accessorKey: 'role', header: '岗位' },
  { accessorKey: 'address', header: '地址' },
  { accessorKey: 'email', header: '邮箱' },
  { accessorKey: 'salary', header: '薪资', fixed: 'right', align: 'right', cell: moneyCell }
]
</script>

<template>
  <MDataTable :columns="columns" :data="data" :ui="{ root: 'max-w-2xl' }" />
</template>

children Grouped Headers

Define grouped columns (DataTableGroupColumn) using children to create multi-level headers:

员工信息薪酬
工号姓名部门岗位职级薪资
P0001
李勇
产品
UI 设计师
P8
¥8,257
P0002
王超
市场
运营专员
P7
¥8,514
P0003
陈娜
设计
全栈工程师
P6
¥8,771
P0004
刘丽
运营
数据分析师
P5
¥9,028
P0005
杨军
研发
后端工程师
P8
¥9,285
P0006
黄涛
产品
产品经理
P7
¥9,542
<script setup lang="ts">
import type { DataTableColumn, DataTableDataColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(6)
const moneyCell: DataTableDataColumn<Person>['cell'] = ({ getValue }) => `¥${getValue<number>().toLocaleString()}`

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'id', header: '工号' },
  {
    header: '员工信息',
    children: [
      { accessorKey: 'name', header: '姓名' },
      { accessorKey: 'department', header: '部门' },
      { accessorKey: 'role', header: '岗位' }
    ]
  },
  {
    header: '薪酬',
    children: [
      { accessorKey: 'level', header: '职级' },
      { accessorKey: 'salary', header: '薪资', align: 'right', cell: moneyCell }
    ]
  }
]
</script>

<template>
  <MDataTable :columns="columns" :data="data" bordered />
</template>

sortable Column Sorting

The global sortable enables click-to-sort on all data column headers; a per-column sortable overrides the global setting in the opposite direction (e.g. sortable: false locks a column as non-sortable):

工号
姓名
职级
地址
薪资
P0001
李勇
P8
北京市海淀区中关村大街 27 号中关村大厦 A 座 1502
¥8,257
P0002
王超
P7
深圳市南山区科技园南区高新南九道 9 号深圳湾科技生态园 10 栋 B 座 2301
¥8,514
P0003
陈娜
P6
广州市天河区珠江新城华夏路 16 号富力盈凯广场 38 楼
¥8,771
P0004
刘丽
P5
杭州市余杭区文一西路 969 号阿里巴巴西溪园区 6 号楼 318
¥9,028
P0005
杨军
P8
成都市高新区天府大道中段 1199 号天府软件园 D 区 5 号楼 1207
¥9,285
P0006
黄涛
P7
南京市建邺区江东中路 222 号高科荣域大厦 19 层
¥9,542
P0007
赵伟
P6
武汉市洪山区光谷大道 70 号光谷国际企业中心 3 期 B 座 1808
¥9,799
P0008
吴敏
P5
上海市浦东新区张江高科技园区博云路 2 号 IBM 大厦 7 层 708
¥10,056
<script setup lang="ts">
import type { DataTableColumn, DataTableDataColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(8)
const moneyCell: DataTableDataColumn<Person>['cell'] = ({ getValue }) => `¥${getValue<number>().toLocaleString()}`

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'id', header: '工号', sortable: true },
  { accessorKey: 'name', header: '姓名' },
  { accessorKey: 'level', header: '职级', sortable: false },
  { accessorKey: 'address', header: '地址' },
  { accessorKey: 'salary', header: '薪资', align: 'right', cell: moneyCell }
]
</script>

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

pinable Column Pinning

The global pinable lets users click the pin icon on a header to cycle through left, right and none; a per-column pinable has higher priority and can force a fixed position:

工号
姓名
部门
岗位
薪资
P0001
李勇
产品
UI 设计师
¥8,257
P0002
王超
市场
运营专员
¥8,514
P0003
陈娜
设计
全栈工程师
¥8,771
P0004
刘丽
运营
数据分析师
¥9,028
P0005
杨军
研发
后端工程师
¥9,285
P0006
黄涛
产品
产品经理
¥9,542
P0007
赵伟
市场
前端工程师
¥9,799
P0008
吴敏
设计
UI 设计师
¥10,056
<script setup lang="ts">
import type { DataTableColumn, DataTableDataColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(8)
const moneyCell: DataTableDataColumn<Person>['cell'] = ({ getValue }) => `¥${getValue<number>().toLocaleString()}`

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'id', header: '工号', fixed: 'left', pinable: true },
  { accessorKey: 'name', header: '姓名' },
  { accessorKey: 'department', header: '部门', pinable: false },
  { accessorKey: 'role', header: '岗位' },
  { accessorKey: 'salary', header: '薪资', align: 'right', cell: moneyCell }
]
</script>

<template>
  <MDataTable :columns="columns" :data="data" :ui="{ root: 'max-w-3xl' }" />
</template>

resizable Column Resize

The global resizable adds a drag handle to all data columns; resizable: false on a column locks its width. columnResizeMode controls whether reflow happens onChange (live during drag) or onEnd (after release):

工号
姓名
职级
地址
个人简介
P0001
李勇
P8
北京市海淀区中关村大街 27 号中关村大厦 A 座 1502
负责自研低代码平台与 BFF 中间层,输出过若干内部脚手架与 CLI 工具,关注研发效率与可维护性。
P0002
王超
P7
深圳市南山区科技园南区高新南九道 9 号深圳湾科技生态园 10 栋 B 座 2301
负责风控与反作弊算法工程化,搭建过实时特征平台与规则引擎,覆盖支付、营销、社交多场景。
P0003
陈娜
P6
广州市天河区珠江新城华夏路 16 号富力盈凯广场 38 楼
长期投入大数据平台与离线计算调度,搭建过 PB 级数据仓库与数据治理体系,对数据质量与权限治理有较强经验。
P0004
刘丽
P5
杭州市余杭区文一西路 969 号阿里巴巴西溪园区 6 号楼 318
深耕实时音视频与 WebRTC 互动场景,主导过千万级直播间的延迟优化与弱网降级方案。
P0005
杨军
P8
成都市高新区天府大道中段 1199 号天府软件园 D 区 5 号楼 1207
聚焦移动端性能优化与跨端渲染框架,主导过启动耗时、内存与包体积的全链路治理。
P0006
黄涛
P7
南京市建邺区江东中路 222 号高科荣域大厦 19 层
聚焦设计系统与组件库建设,推动跨产品视觉一致性,主导多次 Design Tokens 与暗色主题落地。
P0007
赵伟
P6
武汉市洪山区光谷大道 70 号光谷国际企业中心 3 期 B 座 1808
在 To B SaaS 团队负责权限、计费与多租户体系,对 RBAC、ABAC 与审计合规有完整落地经验。
P0008
吴敏
P5
上海市浦东新区张江高科技园区博云路 2 号 IBM 大厦 7 层 708
在跨境电商团队负责供应链与履约链路建设,主导过日均百万单的实时调度系统重构,关注稳定性与成本平衡。
<script setup lang="ts">
import type { DataTableColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(8)

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'id', header: '工号' },
  { accessorKey: 'name', header: '姓名', minSize: 80 },
  { accessorKey: 'level', header: '职级', resizable: false },
  { accessorKey: 'address', header: '地址', size: 120 },
  { accessorKey: 'bio', header: '个人简介', size: 150, resizable: true }
]
</script>

<template>
  <MDataTable :columns="columns" :data="data" :ui="{ root: 'max-w-3xl' }" />
</template>

size / minSize / maxSize Column Width

size sets a fixed column width (a number or a preset xsxl). When size is not set and only minSize / maxSize are provided, the column width adapts to content: minSize is the lower bound for auto-sizing and dragging; maxSize is the maximum draggable width. A column with size set is constrained in both directions by minSize / maxSize.

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'name', header: 'Name', minSize: 120 },    // auto, min 120
  { accessorKey: 'bio', header: 'Bio', maxSize: 240 },      // auto, drag max 240
  { accessorKey: 'id', header: 'ID', size: 'sm' }           // fixed preset width 120
]
The table uses table-layout: auto and stretches to fill the container; auto-sized column content may exceed maxSize (auto layout ignores cell max-width). Therefore maxSize on an auto-sized column only constrains the drag upper limit. Use size to strictly fix a column width.
Fixed columns (fixed) require a known width to participate in sticky offset calculations, so they default to size. Only when a side has a single fixed column (the innermost fixed column closest to the scroll area) can that column auto-size to content — set minSize / maxSize to allow it to stretch (a typical example is the sole actions column on the right).

Text Truncation and Tooltip

truncate controls pure truncation (true for single-line / number for multi-line / false to disable / a function for dynamic behavior); tooltip applies the same number of truncation lines and shows the full content in a float when it overflows. You do not need to configure both:

姓名个人简介角色地址
李勇
负责自研低代码平台与 BFF 中间层,输出过若干内部脚手架与 CLI 工具,关注研发效率与可维护性。
UI 设计师
北京市海淀区中关村大街 27 号中关村大厦 A 座 1502
王超
负责风控与反作弊算法工程化,搭建过实时特征平台与规则引擎,覆盖支付、营销、社交多场景。
运营专员
深圳市南山区科技园南区高新南九道 9 号深圳湾科技生态园 10 栋 B 座 2301
陈娜
长期投入大数据平台与离线计算调度,搭建过 PB 级数据仓库与数据治理体系,对数据质量与权限治理有较强经验。
全栈工程师
广州市天河区珠江新城华夏路 16 号富力盈凯广场 38 楼
刘丽
深耕实时音视频与 WebRTC 互动场景,主导过千万级直播间的延迟优化与弱网降级方案。
数据分析师
杭州市余杭区文一西路 969 号阿里巴巴西溪园区 6 号楼 318
杨军
聚焦移动端性能优化与跨端渲染框架,主导过启动耗时、内存与包体积的全链路治理。
后端工程师
成都市高新区天府大道中段 1199 号天府软件园 D 区 5 号楼 1207
黄涛
聚焦设计系统与组件库建设,推动跨产品视觉一致性,主导多次 Design Tokens 与暗色主题落地。
产品经理
南京市建邺区江东中路 222 号高科荣域大厦 19 层
赵伟
在 To B SaaS 团队负责权限、计费与多租户体系,对 RBAC、ABAC 与审计合规有完整落地经验。
前端工程师
武汉市洪山区光谷大道 70 号光谷国际企业中心 3 期 B 座 1808
吴敏
在跨境电商团队负责供应链与履约链路建设,主导过日均百万单的实时调度系统重构,关注稳定性与成本平衡。
UI 设计师
上海市浦东新区张江高科技园区博云路 2 号 IBM 大厦 7 层 708
<script setup lang="ts">
import type { DataTableColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(8)

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'name', header: '姓名' },
  { accessorKey: 'bio', header: '个人简介', size: 240, tooltip: 1 },
  { accessorKey: 'role', header: '角色', size: 60 },
  { accessorKey: 'address', header: '地址', size: 200, truncate: true }
]
</script>

<template>
  <MDataTable :columns="columns" :data="data" :ui="{ root: 'max-w-3xl' }" />
</template>

Column Visibility

column.visibility sets the default show/hide state; columnVisibilityKeys (allowlist) and columnVisibilityExcludeKeys (blocklist) are mutually exclusive — when both are provided the allowlist takes precedence:

工号姓名部门岗位职级邮箱薪资
P0001
李勇
产品
UI 设计师
P8
user1@movk.dev
¥8,257
P0002
王超
市场
运营专员
P7
user2@movk.dev
¥8,514
P0003
陈娜
设计
全栈工程师
P6
user3@movk.dev
¥8,771
P0004
刘丽
运营
数据分析师
P5
user4@movk.dev
¥9,028
P0005
杨军
研发
后端工程师
P8
user5@movk.dev
¥9,285
P0006
黄涛
产品
产品经理
P7
user6@movk.dev
¥9,542
<script setup lang="ts">
import type { DataTableColumn, DataTableDataColumn } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(6)
const moneyCell: DataTableDataColumn<Person>['cell'] = ({ getValue }) => `¥${getValue<number>().toLocaleString()}`
const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'id', header: '工号' },
  { accessorKey: 'name', header: '姓名' },
  { accessorKey: 'department', header: '部门' },
  { accessorKey: 'role', header: '岗位' },
  { accessorKey: 'level', header: '职级' },
  { accessorKey: 'email', header: '邮箱' },
  { accessorKey: 'joinedAt', header: '入职日期', visibility: false },
  { accessorKey: 'salary', header: '薪资', align: 'right', cell: moneyCell }
]
</script>

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

Functional Configuration

sortable, pinable and resizable accept (col) => boolean; truncate and tooltip accept (ctx) => boolean | number. A single declaration replaces per-column booleans and can make dynamic decisions based on the field or cell context:

工号
姓名
部门
个人简介
地址
薪资
P0001
李勇
产品
负责自研低代码平台与 BFF 中间层,输出过若干内部脚手架与 CLI 工具,关注研发效率与可维护性。
北京市海淀区中关村大街 27 号中关村大厦 A 座 1502
¥8,257
P0002
王超
市场
负责风控与反作弊算法工程化,搭建过实时特征平台与规则引擎,覆盖支付、营销、社交多场景。
深圳市南山区科技园南区高新南九道 9 号深圳湾科技生态园 10 栋 B 座 2301
¥8,514
P0003
陈娜
设计
长期投入大数据平台与离线计算调度,搭建过 PB 级数据仓库与数据治理体系,对数据质量与权限治理有较强经验。
广州市天河区珠江新城华夏路 16 号富力盈凯广场 38 楼
¥8,771
P0004
刘丽
运营
深耕实时音视频与 WebRTC 互动场景,主导过千万级直播间的延迟优化与弱网降级方案。
杭州市余杭区文一西路 969 号阿里巴巴西溪园区 6 号楼 318
¥9,028
P0005
杨军
研发
聚焦移动端性能优化与跨端渲染框架,主导过启动耗时、内存与包体积的全链路治理。
成都市高新区天府大道中段 1199 号天府软件园 D 区 5 号楼 1207
¥9,285
P0006
黄涛
产品
聚焦设计系统与组件库建设,推动跨产品视觉一致性,主导多次 Design Tokens 与暗色主题落地。
南京市建邺区江东中路 222 号高科荣域大厦 19 层
¥9,542
P0007
赵伟
市场
在 To B SaaS 团队负责权限、计费与多租户体系,对 RBAC、ABAC 与审计合规有完整落地经验。
武汉市洪山区光谷大道 70 号光谷国际企业中心 3 期 B 座 1808
¥9,799
P0008
吴敏
设计
在跨境电商团队负责供应链与履约链路建设,主导过日均百万单的实时调度系统重构,关注稳定性与成本平衡。
上海市浦东新区张江高科技园区博云路 2 号 IBM 大厦 7 层 708
¥10,056
<script setup lang="ts">
import type { DataTableColumn, DataTableDataColumn, DataTableProps } from '@movk/nuxt'
import type { Person } from '~/composables/useTableMock'

const data = makePeople(8)
const moneyCell: DataTableDataColumn<Person>['cell'] = ({ getValue }) => `¥${getValue<number>().toLocaleString()}`

const columns: DataTableColumn<Person>[] = [
  { accessorKey: 'id', header: '工号' },
  { accessorKey: 'name', header: '姓名' },
  { accessorKey: 'department', header: '部门' },
  { accessorKey: 'bio', header: '个人简介' },
  { accessorKey: 'address', header: '地址', size: 200 },
  { accessorKey: 'salary', header: '薪资', align: 'right', cell: moneyCell }
]

const sortableFn: DataTableProps<Person>['sortable'] = col => col.accessorKey !== 'id'
const pinableFn: DataTableProps<Person>['pinable'] = col => !['bio', 'address'].includes(col.accessorKey)
const resizableFn: DataTableProps<Person>['resizable'] = col => col.accessorKey !== 'salary'
const truncateFn: DataTableDataColumn<Person>['truncate'] = ctx =>
  ctx.column.id === 'bio' ? (ctx.row.original.bio.length > 45 ? 3 : 2) : true
const tooltipFn: DataTableDataColumn<Person>['tooltip'] = ctx => ctx.column.id === 'address'
</script>

<template>
  <MDataTable
    :columns="columns"
    :data="data"
    :sortable="sortableFn"
    :pinable="pinableFn"
    :resizable="resizableFn"
    :truncate="truncateFn"
    :tooltip="tooltipFn"
  />
</template>
Per-column props always take precedence over global props. The recommended pattern is "global on + individual off" or "global off + individual on" to express the difference.
Copyright © 2025 - 2026 YiXuan - MIT License