@vueye-table/styled

Styled, themeable Vue components for vueye-table, built on the headless layer.
2,606 111
Install
npm install @vueye-table/styled
Latest Version:3.0.0-beta.3
Vue:3
License:MIT
Last Updated:Oct 18, 2026
Links: GitHub  ·  npm
Maintainer: boussadjra

vueye-table

A Vue framework for data, data tables, and spreadsheets.

vueye-table began as a single table component. Version 3 is a rewrite around one idea: a table is data plus state plus operations, and rendering is a separate concern. A framework-independent engine owns searching, filtering, sorting, pagination, selection, column visibility, editing, undo, clipboard, and export. Vue layers sit on top of it, and you pick the one that fits:

Layer Package Use it when
Full UI vueye-table You want a complete table or spreadsheet in one tag.
Styled components @vueye-table/styled You want the look, arranged your own way.
Headless components @vueye-table/headless You want accessible behavior with your own markup and CSS.
Vue composables @vueye-table/vue You want reactive state and nothing rendered.
Engine @vueye-table/core You are outside Vue, on a server, or writing a binding.
Nuxt module @vueye-table/nuxt You use Nuxt 4.

Each layer depends only on the layers beneath it, and vueye-table re-exports all of them, so one install covers every level.

Status: 3.0.0-beta.3, published on npm's beta channel. The beta is for application feedback: documented import paths, options, events and slot scopes are kept stable, and a necessary breaking change ships with an ADR and migration notes. It is not production ready. See the beta contract. The 2.x component lives on the legacy branch; see Upgrading from 2.x.

Install

pnpm add vueye-table@beta

Install @beta or an exact version such as 3.0.0-beta.3: a plain pnpm add vueye-table still resolves to the last alpha. Vue 3.5 or newer is a peer dependency.

What the beta covers

  • Tables and spreadsheets: search, column filters, multi-column sorting, pagination, selection, column visibility, CSV/TSV export, and a spreadsheet grid with clipboard and undo.
  • Editing and validation: inline cell and row editing in VueyeTable, typed and custom editors, validation issues, dirty rows, revert, and a saved baseline you acknowledge.
  • Expansion and trees: detail rows, nested and lazy-loaded children, tree search that keeps matching branches.
  • Large data: opt-in row and column virtualization for tables and grids, and incremental streams, cursor loading, and cancellable sources.
  • Language and themes: every word shown or announced comes from messages, numbers and ordering follow locale, search ignores case and accents, and host design tokens win over the defaults.
  • Server data: manual mode hands searching, sorting and paging to your API.

Full table

<script setup lang="ts">
import "vueye-table/style.css";
import { ref } from "vue";
import { VueyeTable, defineColumns, type RowKey } from "vueye-table";

interface User {
  id: number;
  name: { first: string; last: string };
  age: number;
  city: string;
}

const users: User[] = [
  { id: 1, name: { first: "Ada", last: "Lovelace" }, age: 36, city: "London" },
  { id: 2, name: { first: "Alan", last: "Turing" }, age: 41, city: "Wilmslow" },
];

const columns = defineColumns<User>([
  { id: "name.first", header: "First name" },
  { id: "name.last", header: "Last name" },
  { id: "age", align: "end", format: (age) => `${age} years` },
  { id: "city" },
]);

const selected = ref<readonly RowKey[]>([]);
</script>

<template>
  <VueyeTable v-model:selected="selected" :data="users" :columns="columns" selectable striped>
    <template #cell.city="{ value }">
      <strong>{{ value }}</strong>
    </template>
  </VueyeTable>
</template>

Column ids are typed paths into your rows, so format above receives a number. Without columns, columns are inferred from the data.

Every piece of state has a v-model: page, pageSize, sorting, search, filters, hiddenColumns, and selected. Add manual and row-count to let a server search, sort, and page, with the table presenting whatever page it returns.

Spreadsheet

<VueyeGrid v-model:data="lines" :columns="columns" column-letters />

Cells edit in place. Arrows, Tab, Home, and End move; Shift extends the range; Enter or typing starts an edit; Delete clears; and copy, cut, paste, undo, and redo behave like a spreadsheet application. Each edit emits a new array; the one you passed in is never mutated. Text is parsed by the column's type, and a value that cannot be read is refused and reported through edit-error.

Headless

<script setup lang="ts">
import { DataTableRoot, DataTablePagination, DataTableSearch, useDataTable } from "vueye-table";

const table = useDataTable({ data: users, columns });
</script>

<template>
  <DataTableRoot :table="table" as="div">
    <DataTableSearch />
    <article v-for="row in table.rows" :key="row.key">{{ row.getDisplay("name.first") }}</article>
    <DataTablePagination />
  </DataTableRoot>
</template>

Headless components render semantic, accessible markup (aria-sort, aria-selected, aria-rowindex, a polite live status, grid keyboard navigation) with data-* state attributes and no styles. Every one accepts as and exposes its state through slot props.

Engine

import { createTable } from "@vueye-table/core";

const table = createTable({ data: users, columns: [{ id: "age" }, { id: "city" }] });
table.search("lon");
table.toggleSort("age");
table.getSnapshot().rows; // the current page
table.exportRows(); // CSV of every filtered row

The state is plain serializable data, so it can be saved, restored, sent to a server, or kept in the URL.

Nuxt

export default defineNuxtConfig({
  modules: ["@vueye-table/nuxt"],
});

The module auto-imports <VueyeTable>, <VueyeGrid>, useDataTable, useDataGrid, and defineColumns, and adds the stylesheet. Set vueyeTable: { layers: true } to also register the headless and styled components.

Theming

The styled layer is driven by CSS custom properties on .vt-surface:

.vt-surface {
  --vt-accent: #0f766e;
  --vt-radius: 4px;
  --vt-font-size: 0.8125rem;
}

Dark colors follow prefers-color-scheme; theme="dark" or theme="light" forces one, and theme="inherit" declares no colors so the host's own tokens apply. The defaults have zero specificity, so your tokens always win. Density is compact, comfortable, or spacious.

Language

<VueyeTable :data="rows" :columns="columns" locale="fr" :messages="{ columns: 'Colonnes' }" />

Every word a table shows or announces comes from TableMessages; whatever you leave out keeps its English default. app.use(VueyeTablePlugin, { locale, messages }) sets them for the whole application. Arrow keys and chevrons mirror in right-to-left layouts.

Development

pnpm install
pnpm playground      # every layer, side by side
pnpm docs:dev        # the documentation site
pnpm test            # every Vitest project
pnpm check           # format, lint, types, tests with coverage, build, boundaries, packages

Architecture lives in ARCHITECTURE.md and decisions in docs/adr.

License

MIT

Related Packages

@vueye-table/vue

Vue composables that bind the vueye-table engine to reactive state.

2,828 111
@vueye-table/headless

Unstyled, accessible Vue components for vueye-table: tables, controls, and sprea...

2,762 111
@vueye-table/nuxt

Nuxt module for vueye-table: auto-imported components, composables, and styles.

2,348 111
@libraz/formulon-cell-vue

Vue 3 component + composables for @libraz/formulon-cell.

2,307 0
@trapezium/vue

A data table for Vue 3 that looks right out of the box: zero-config columns, fil...

257 2

Version History

Pre-releases (15)
Version Released License
3.0.0-beta.3 MIT
3.0.0-beta.2 MIT
3.0.0-beta.1 MIT
3.0.0-alpha.12 MIT
3.0.0-alpha.11 MIT