Skip to content

DataTable Component

The DataTable component is a flexible and customizable table component built with Vue 3. It supports a sort-by event, custom headers and custom items.

Basic Usage

Import and use DataTable in your Vue components:

vue
<template>
  <DataTable :headers="headers" :items="items" />
</template>

<script setup>
import { DataTable } from '@robuust-digital/vue-components';

const headers = [
  { id: 1, key: 'name', label: 'Name', sortable: true },
  { id: 2, key: 'age', label: 'Age', sortable: true, align: 'right' },
  { id: 3, key: 'email', label: 'Email', sortable: false, align: 'left' },
];

const items = [
  { id: 1, name: 'John Doe', age: 28, email: 'john@example.com' },
  { id: 2, name: 'Jane Smith', age: 34, email: 'jane@example.com' },
  { id: 3, name: 'Sam Green', age: 45, email: 'sam@example.com' },
];
</script>
Email
John Doejohn@example.com
Jane Smithjane@example.com
Sam Greensam@example.com

Props

PropTypeDefaultDescription
headersArray[]Array of header objects defining the table columns
itemsArray[]Array of item objects representing the table rows
noResultsTextString'No results found.'Text to display when no items are available
loadingTextString'Loading content...'Text to display when the table is in a loading state
stripedBooleanfalseApply striped rows style
spinningBooleanfalseDisplay a loading spinner

Slots

Headers Slot

Customize the table headers.

vue
<template>
  <DataTable :headers="headers" :items="items">
    <template #headers="{ headers }">
      <th v-for="header in headers" :key="header.id">
        {{ header.label }}
      </th>
    </template>
  </DataTable>
</template>

Header Label Slot

Customize the header labels.

vue
<template>
  <DataTable :headers="headers" :items="items">
    <template #header-label="{ header, sortBy }">
      <span class="custom-class-styling">{{ header.label }}</span>
      <button type="button" v-if="header.sortable" @click="sortBy(header.key)">
        <ArrowUpIcon />
        <ArrowDownIcon />
      </button>
    </template>
  </DataTable>
</template>

Items Slot

Customize the table rows.

vue
<template>
  <DataTable :headers="headers" :items="items">
    <template #items="{ item, index }">
      <td v-for="(value, key) in item" :key="key">
        {{ value }}
      </td>
    </template>
  </DataTable>
</template>

Spinner Slot

Customize the loading spinner.

vue
<template>
  <DataTable :headers="headers" :items="items" :spinning="true">
    <template #spinner="{ spinning, label }">
      <div v-if="spinning">
        <CustomSpinnerIcon />
        {{ label }}
      </div>
    </template>
  </DataTable>
</template>

Examples

DataTable with Custom Headers

NameAgeEmail
John Doejohn@example.com
Jane Smithjane@example.com
Sam Greensam@example.com
Show code
vue
<template>
  <DataTable :headers="headers" :items="items">
    <template #headers="{ headers }">
      <th v-for="header in headers" :key="header.id">
        {{ header.label }}
      </th>
    </template>
  </DataTable>
</template>

DataTable with Custom Items

MemberStatusActions
4-uurs arrangement01-01-2024John DoeJohn Doe€ 10,15active
8-uurs arrangement01-05-2024Jane DoeJane Doe€ 15,15pending
12-uurs arrangement01-03-2024Sarah DoeSarah Doe€ 20,15active
24-uurs arrangement01-02-2024Justin DoeJustin Doe€ 25,15active
Show code
vue
<template>
  <DataTable
    :headers="headers"
    :items="items"
    striped
    @table:sort-by="(sortBy) => console.log(sortBy)"
  >
    <template #items="{ item }">
      <td>
        <a
          href="#"
          class="hover:underline block"
        >
          {{ item.package }}
        </a>
      </td>
      <td>
        {{ item.date }}
      </td>
      <td>
        <a
          href="#"
          class="flex gap-x-2 items-center hover:underline"
        >
          <img
            :src="item.member.avatar"
            :alt="item.member.name"
            width="28"
            height="28"
            class="size-7 rounded-full shrink-0"
            loading="lazy"
          />
          <span class="font-medium">{{ item.member.name }}</span>
        </a>
      </td>
      <td class="text-right">
        {{ item.price }}
      </td>
      <td>
        <Badge
          :color="item.status === 'active' ? 'green' : 'yellow'"
          :label="item.status"
          size="sm"
        />
      </td>
      <td class="text-right">
        <ButtonBase
          label="Edit"
          type="button"
          icon-only
          color="clear"
          :icon="PencilSquareIcon"
          size="sm"
        />
        <ButtonBase
          label="Delete"
          type="button"
          icon-only
          color="clear"
          :icon="TrashIcon"
          size="sm"
        />
      </td>
    </template>
  </DataTable>
</template>

<script setup>
import { DataTable, Badge, ButtonBase } from '@robuust-digital/vue-components';
import { TrashIcon, PencilSquareIcon } from '@heroicons/vue/16/solid';

const headers = [
  {
    id: 0, label: 'Package', key: 'package', sortable: true,
  },
  {
    id: 1, label: 'Date', key: 'date', sortable: true,
  },
  {
    id: 2, label: 'Member', key: 'member',
  },
  {
    id: 3, label: 'Price', key: 'price', align: 'right', sortable: true,
  },
  {
    id: 4, label: 'Status', key: 'status', align: 'left',
  },
  {
    id: 5, label: 'Actions', key: 'actions', align: 'right',
  },
];

const items = [
  {
    id: 1,
    package: '4-uurs arrangement',
    date: '01-01-2024',
    status: 'active',
    member: {
      name: 'John Doe',
      id: 0,
      avatar: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&auto=format&fit=facearea&facepad=3&q=80',
    },
    price: '€ 10,15',
  },
  {
    id: 2,
    package: '8-uurs arrangement',
    date: '01-05-2024',
    status: 'pending',
    member: {
      name: 'Jane Doe',
      id: 1,
      avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&auto=format&fit=facearea&facepad=3&q=80',
    },
    price: '€ 15,15',
  },
  {
    id: 3,
    package: '12-uurs arrangement',
    date: '01-03-2024',
    status: 'active',
    member: {
      name: 'Sarah Doe',
      id: 1,
      avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=200&h=200&auto=format&fit=facearea&facepad=3&q=80',
    },
    price: '€ 20,15',
  },
  {
    id: 4,
    package: '24-uurs arrangement',
    date: '01-02-2024',
    status: 'active',
    member: {
      name: 'Justin Doe',
      id: 1,
      avatar: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=200&h=200&auto=format&fit=facearea&facepad=3&q=80',
    },
    price: '€ 25,15',
  },
];
</script>

Customization with Tailwind CSS

To customize the DataTable styles globally, extend your Tailwind configuration. Example:

javascript
// tailwind.config.js
export default {
  theme: {
    extend: {
      components: (theme) => ({
        table: {
          // Available variables you can override:
          '--rvc-table-head-border-color': theme('colors.slate.300'),
          '--rvc-table-border-color': theme('colors.slate.200'),
          '--rvc-table-border-style': 'solid',
          '--rvc-table-border-width': theme('borderWidth.DEFAULT'),
          '--rvc-table-head-bg-color': theme('colors.slate.200'),
          '--rvc-table-bg-color': theme('colors.slate.50'),
          '--rvc-table-font-size': '0.875rem',
          '--rvc-table-head-font-size': '0.875rem',
          '--rvc-table-head-font-weight': theme('fontWeight.medium'),
          '--rvc-table-font-weight': theme('fontWeight.normal'),
          '--rvc-table-padding-x': theme('padding.2'),
          '--rvc-table-padding-y': theme('padding.3'),
          '--rvc-table-white-space': 'nowrap',
          '--rvc-table-line-height': '1.1',
          '--rvc-table-spinner-size': theme('size.5'),
        },
      }),
    },
  },
};