Skip to content

Table

Tables display a structured set of data made up of rows and columns (tabular data) that's easy to scan and make connections across data points. Table and its components map to native <table> elements.

Table is designed to work with DataView (link once available) for handling of large amounts of data, which provides more powerful data table features like search, sorting, filtering, and pagination.

The Table component supports two layouts, scroll and stack. Both layouts are the same for larger viewports. The differences come in at smaller viewports, see below.

Scroll layout

Maintains the same table layout across all breakpoints. The user is required to scroll horizontally to see other columns.

INFO

To control the width of an entire column, the min-width and max-width CSS properties can be applied to specific TableHeaderCell or TableCell components.

Product Name
Brand
Category
Price per unit
Strain
Citrus Splash 2x50mg THC Gummies
True North CollectiveEdibles & Ingestibles$2.50
Rabbit Hole 1 lb bag
MJ VerdantFlower$2,800.00Hybrid
THC-A Crystalline Rings | GMO
Kola FarmsConcentrates$10.00
Seed Junky Purple Push Pop 3.5g
Seed JunkyFlower$20.00Hybrid
GUSH-MINTS 19-23% 1.4% TERPENES
AgronomosFlower$1,400.00Indica Hybrid
template
<Table>
  <template #head>
    <TableHeaderRow>
      <TableHeaderCell class="tw-min-w-[300px]">
        Product Name
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[140px]">
        Brand
      </TableHeaderCell>
      <TableHeaderCell>
        Category
      </TableHeaderCell>
      <TableHeaderCell>
        Price per unit
      </TableHeaderCell>
      <TableHeaderCell>
        Strain
      </TableHeaderCell>
    </TableHeaderRow>
  </template>
  <template #body>
    <TableRow v-for="product in data" :key="product.id">
      <TableCell>
        <div class="tw-flex tw-items-center">
          <img :src="product.featured_image" width="60" class="tw-rounded tw-mr-3" />
          {{ product.name }}
        </div>
      </TableCell>
      <TableCell>
        {{ product.brand.name }}
      </TableCell>
      <TableCell>
        {{ product.category.name }}
      </TableCell>
      <TableCell>
        {{ money(product.price_per_unit) }}
      </TableCell>
      <TableCell class="show-empty">
        {{ product.strain_classification }}
      </TableCell>
    </TableRow>
  </template>
</Table>

Stack layout

Switches to a card layout for smaller viewports. All the data for a row (card) is contained and available for the user to read without having to scroll horizontally, at the cost of not being able to easily scan or compare tabular data across other rows.

TIP

Resize the screen until the table switches to the stack layout.

Product Name
Brand
Category
Price per unit
Strain
Product Name
Citrus Splash 2x50mg THC Gummies
Brand
True North Collective
Category
Edibles & Ingestibles
Price per unit
$2.50
Strain
Product Name
Rabbit Hole 1 lb bag
Brand
MJ Verdant
Category
Flower
Price per unit
$2,800.00
Strain
Hybrid
Product Name
THC-A Crystalline Rings | GMO
Brand
Kola Farms
Category
Concentrates
Price per unit
$10.00
Strain
Product Name
Seed Junky Purple Push Pop 3.5g
Brand
Seed Junky
Category
Flower
Price per unit
$20.00
Strain
Hybrid
Product Name
GUSH-MINTS 19-23% 1.4% TERPENES
Brand
Agronomos
Category
Flower
Price per unit
$1,400.00
Strain
Indica Hybrid
template
<Table layout="stack">
  <template #head>
    <TableHeaderRow>
      <TableHeaderCell class="tw-min-w-[300px]">
        Product Name
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[140px]">
        Brand
      </TableHeaderCell>
      <TableHeaderCell>
        Category
      </TableHeaderCell>
      <TableHeaderCell>
        Price per unit
      </TableHeaderCell>
      <TableHeaderCell>
        Strain
      </TableHeaderCell>
    </TableHeaderRow>
  </template>
  <template #body>
    <TableRow v-for="product in data" :key="product.id">
      <TableCell class="tw-col-span-12 md:tw-col-span-8" mobile-header="Product Name">
        <div class="tw-flex tw-items-center">
          <img :src="product.featured_image" width="60" class="tw-rounded tw-mr-3" />
          {{ product.name }}
        </div>
      </TableCell>
      <TableCell class="tw-col-span-6 md:tw-col-span-4" mobile-header="Brand">
        {{ product.brand.name }}
      </TableCell>
      <TableCell class="tw-col-span-6 md:tw-col-span-5" mobile-header="Category">
        {{ product.category.name }}
      </TableCell>
      <TableCell class="tw-col-span-3 md:tw-col-span-4" mobile-header="Price per unit">
        {{ money(product.price_per_unit) }}
      </TableCell>
      <TableCell class="tw-col-span-9 md:tw-col-span-3" mobile-header="Strain">
        {{ product.strain_classification }}
      </TableCell>
    </TableRow>
  </template>
</Table>

Compact table

A simple example of a compact table.

Product Name
Brand
Category
Price per unit
Strain
Citrus Splash 2x50mg THC Gummies
True North CollectiveEdibles & Ingestibles$2.50
Rabbit Hole 1 lb bag
MJ VerdantFlower$2,800.00Hybrid
THC-A Crystalline Rings | GMO
Kola FarmsConcentrates$10.00
Seed Junky Purple Push Pop 3.5g
Seed JunkyFlower$20.00Hybrid
GUSH-MINTS 19-23% 1.4% TERPENES
AgronomosFlower$1,400.00Indica Hybrid
template
<Table density="compact">
  ...
</Table>

Selection

An example of row selection.

Selection is enabled via the isSelectable property, and adds a checkbox column for selecting rows. Selection is intended for use with the useSelection composable.

Selected count: 0

Product Name
Brand
Category
Price per unit
Strain
Citrus Splash 2x50mg THC Gummies
True North CollectiveEdibles & Ingestibles$2.50
Rabbit Hole 1 lb bag
MJ VerdantFlower$2,800.00Hybrid
THC-A Crystalline Rings | GMO
Kola FarmsConcentrates$10.00
Seed Junky Purple Push Pop 3.5g
Seed JunkyFlower$20.00Hybrid
GUSH-MINTS 19-23% 1.4% TERPENES
AgronomosFlower$1,400.00Indica Hybrid
vue
<script setup lang="ts">
  import { computed, ref } from 'vue';

  import Table from '../../src/components/Table/Table.vue';
  import TableHeaderRow from '../../src/components/TableHeaderRow/TableHeaderRow.vue';
  import TableHeaderCell from '../../src/components/TableHeaderCell/TableHeaderCell.vue';
  import TableRow from '../../src/components/TableRow/TableRow.vue';
  import TableCell from '../../src/components/TableCell/TableCell.vue';
  import { getProducts } from '../../src/components/Table/Table.fixtures';
  import useSelection from '../../src/composables/useSelection/useSelection';
  import { money } from '../../src/utils/i18n';

  const data = computed(() => getProducts().slice(0, 5));
  const dataRef = ref(data);
  const { 
    isSelected, 
    selectToggle, 
    selectToggleAll, 
    allSelected, 
    someSelected, 
    selectedItems, 
  } = useSelection({ items: dataRef }); 
</script>
template
<template>
  <Table is-selectable>
    <template #head>
      <TableHeaderRow
        :all-rows-selected="allSelected" // [!code ++]
        :some-rows-selected="someSelected" // [!code ++]
        @select="selectToggleAll" // [!code ++]
      >
        ...
      </TableHeaderRow>
    </template>
    <template #body>
      <TableRow
        v-for="product in data"
        :key="product.id"
        :is-selected="isSelected(product)" // [!code ++]
        @update:is-selected="selectToggle(product)" // [!code ++]
      >
        ...
      </TableRow>
    </template>
  </Table>
</template>

Accent Color

The TableRow component accepts an accent-color to highlight important information. Any color of the type StashCommonColor can be used.

Product Name
Brand
Category
Price per unit
Strain
Actions
Citrus Splash 2x50mg THC Gummies
True North CollectiveEdibles & Ingestibles$2.50
Rabbit Hole 1 lb bag
MJ VerdantFlower$2,800.00Hybrid
THC-A Crystalline Rings | GMO
Kola FarmsConcentrates$10.00
Seed Junky Purple Push Pop 3.5g
Seed JunkyFlower$20.00Hybrid
GUSH-MINTS 19-23% 1.4% TERPENES
AgronomosFlower$1,400.00Indica Hybrid
template
<Table has-actions>
  <template #head>
    <TableHeaderRow
      :all-rows-selected="allSelected"
      :some-rows-selected="someSelected"
      @select="selectToggleAll"
    >
      <TableHeaderCell class="tw-min-w-[300px]">
        Product Name
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[140px]">
        Brand
      </TableHeaderCell>
      <TableHeaderCell>
        Category
      </TableHeaderCell>
      <TableHeaderCell>
        Price per unit
      </TableHeaderCell>
      <TableHeaderCell>
        Strain
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[120px]">
        Actions
      </TableHeaderCell>
    </TableHeaderRow>
  </template>
  <template #body>
    <TableRow
      v-for="product in data"
      :key="product.id"
      :is-selected="isSelected(product)"
      @update:is-selected="selectToggle(product)"
    >
      <TableCell>
        <div class="tw-flex tw-items-center">
          <img :src="product.featured_image" width="60" class="tw-rounded tw-mr-3" />
          {{ product.name }}
        </div>
      </TableCell>
      <TableCell>
        {{ product.brand.name }}
      </TableCell>
      <TableCell>
        {{ product.category.name }}
      </TableCell>
      <TableCell>
        {{ money(product.price_per_unit) }}
      </TableCell>
      <TableCell>
        {{ product.strain_classification }}
      </TableCell>
      <TableCell>
        <Button icon-label>
          <IconLabel stacked icon="trashcan">Delete</IconLabel>
        </Button>
        <Button icon-label>
          <IconLabel stacked icon="edit">Edit</IconLabel>
        </Button>
      </TableCell>
    </TableRow>
  </template>
</Table>

Expansion

An example of row expansion.

Expansion is enabled via the isExpandable property on Table and the existence of the expansion slot in TableRow. By default, it adds a checkbox column for selecting rows.

Product Name
Brand
Category
Price per unit
Strain
Product Name
Citrus Splash 2x50mg THC Gummies
Brand
True North Collective
Category
Edibles & Ingestibles
Price per unit
$2.50
Strain
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
Product Name
Rabbit Hole 1 lb bag
Brand
MJ Verdant
Category
Flower
Price per unit
$2,800.00
Strain
Hybrid
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
Product Name
THC-A Crystalline Rings | GMO
Brand
Kola Farms
Category
Concentrates
Price per unit
$10.00
Strain
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
Product Name
Seed Junky Purple Push Pop 3.5g
Brand
Seed Junky
Category
Flower
Price per unit
$20.00
Strain
Hybrid
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
Product Name
GUSH-MINTS 19-23% 1.4% TERPENES
Brand
Agronomos
Category
Flower
Price per unit
$1,400.00
Strain
Indica Hybrid
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
template
<Table is-expandable>
  <template #head>
    ...
  </template>
  <template #body>
    <TableRow v-for="product in data" :key="product.id">
      <template #default>
        <TableCell>
          ...
        </TableCell>
      </template>
      <template #expansion>
        <Table class="tw-shadow-none tw-px-6 tw-py-3">
          <template #head>
            <TableHeaderRow>
              <TableHeaderCell class="tw-bg-ice-100">Subheading 1</TableHeaderCell>
              <TableHeaderCell class="tw-bg-ice-100">Subheading 2</TableHeaderCell>
              <TableHeaderCell class="tw-bg-ice-100">Subheading 3</TableHeaderCell>
            </TableHeaderRow>
          </template>
          <template #body>
            <TableRow>
              <TableCell>Value 1</TableCell>
              <TableCell>Value 2</TableCell>
              <TableCell>Value 3</TableCell>
            </TableRow>
          </template>
        </Table>
      </template>
    </TableRow>
  </template>
</Table>

Custom toggle

For custom placement of the expansion toggle, you can apply the hasCustomExpandToggle prop on Table. This will hide the dedicated expansion toggle column.

The default slot provides helpers for managing the expanded state of the row.

  • isRowExpanded - a boolean for indicating whether the row is expanded.
  • toggleExpand - a method toggling the expanded state of the row.
Product Name
Brand
Category
Price per unit
Strain
Product Name
Citrus Splash 2x50mg THC Gummies
123
Brand
True North Collective
Category
Edibles & Ingestibles
Price per unit
$2.50
Strain
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
Product Name
Rabbit Hole 1 lb bag
123
Brand
MJ Verdant
Category
Flower
Price per unit
$2,800.00
Strain
Hybrid
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
template
<Table layout="stack" is-expandable has-custom-expand-toggle>
  <template #head>
    ...
  </template>
  <template #body>
    <TableRow v-for="product in data.slice(0, 2)" :key="product.id">
      <template #default="{ isRowExpanded, toggleExpand }">
        <TableCell class="tw-col-span-12 md:tw-col-span-8" mobile-header="Product Name">
          <div class="tw-flex tw-items-center">
            <img :src="product.featured_image" width="60" class="tw-rounded tw-mr-3" />
            <div>
              <div class="tw-block">{{ product.name }}</div>
              <ChevronToggle :direction="isRowExpanded ? 'up' : 'down'" @click="toggleExpand" /> <Chip color="ice">123</Chip>
            </div>
          </div>
        </TableCell>
        <TableCell class="tw-col-span-6 md:tw-col-span-4" mobile-header="Brand">
          {{ product.brand.name }}
        </TableCell>
        <TableCell class="tw-col-span-6 md:tw-col-span-5" mobile-header="Category">
          {{ product.category.name }}
        </TableCell>
        <TableCell class="tw-col-span-3 md:tw-col-span-4" mobile-header="Price per unit">
          {{ money(product.price_per_unit) }}
        </TableCell>
        <TableCell class="tw-col-span-9 md:tw-col-span-3" mobile-header="Strain">
          {{ product.strain_classification }}
        </TableCell>
      </template>
      <template #expansion>
        ...
      </template>
    </TableRow>
  </template>
</Table>

Hidden divider

To hide the divider between the expanded row and its expanded content, you can apply the hideExpansionDivider prop on the TableRow.

Product Name
Brand
Category
Price per unit
Strain
Product Name
Citrus Splash 2x50mg THC Gummies
Brand
True North Collective
Category
Edibles & Ingestibles
Price per unit
$2.50
Strain
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
Product Name
Rabbit Hole 1 lb bag
Brand
MJ Verdant
Category
Flower
Price per unit
$2,800.00
Strain
Hybrid
Subheading 1
Subheading 2
Subheading 3
Value 1Value 2Value 3
template
<Table is-expandable>
  <template #head>
    <TableHeaderRow>
      ...
    </TableHeaderRow>
  </template>
  <template #body>
    <TableRow v-for="product in data" :key="product.id" hide-expansion-divider>
      ...
    </TableRow>
  </template>
</Table>

Row Actions

The has-actions prop adjust the layout of the last column to accommodate buttons in the column. It looks different on mobile/tablet screens when the "stack" layout is used compared to larger screens.

Scroll Layout

With the "scroll" layout (the default layout), the Table looks the same on on screen sizes with the exception of including a horizontal scrollbar on smaller screens.

Product Name
Brand
Category
Price per unit
Strain
Actions
Citrus Splash 2x50mg THC Gummies
True North CollectiveEdibles & Ingestibles$2.50
Rabbit Hole 1 lb bag
MJ VerdantFlower$2,800.00Hybrid
THC-A Crystalline Rings | GMO
Kola FarmsConcentrates$10.00
Seed Junky Purple Push Pop 3.5g
Seed JunkyFlower$20.00Hybrid
GUSH-MINTS 19-23% 1.4% TERPENES
AgronomosFlower$1,400.00Indica Hybrid
template
<Table has-actions>
  <template #head>
    <TableHeaderRow
      :all-rows-selected="allSelected"
      :some-rows-selected="someSelected"
      @select="selectToggleAll"
    >
      <TableHeaderCell class="tw-min-w-[300px]">
        Product Name
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[140px]">
        Brand
      </TableHeaderCell>
      <TableHeaderCell>
        Category
      </TableHeaderCell>
      <TableHeaderCell>
        Price per unit
      </TableHeaderCell>
      <TableHeaderCell>
        Strain
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[120px]">
        Actions
      </TableHeaderCell>
    </TableHeaderRow>
  </template>
  <template #body>
    <TableRow
      v-for="product in data"
      :key="product.id"
      :is-selected="isSelected(product)"
      @update:is-selected="selectToggle(product)"
    >
      <TableCell>
        <div class="tw-flex tw-items-center">
          <img :src="product.featured_image" width="60" class="tw-rounded tw-mr-3" />
          {{ product.name }}
        </div>
      </TableCell>
      <TableCell>
        {{ product.brand.name }}
      </TableCell>
      <TableCell>
        {{ product.category.name }}
      </TableCell>
      <TableCell>
        {{ money(product.price_per_unit) }}
      </TableCell>
      <TableCell>
        {{ product.strain_classification }}
      </TableCell>
      <TableCell>
        <Button icon-label>
          <IconLabel stacked icon="trashcan">Delete</IconLabel>
        </Button>
        <Button icon-label>
          <IconLabel stacked icon="edit">Edit</IconLabel>
        </Button>
      </TableCell>
    </TableRow>
  </template>
</Table>

Stack Layout

TIP

Resize the screen until the table switches to the stack layout.

Product Name
Brand
Category
Price per unit
Strain
Actions
Product Name
Citrus Splash 2x50mg THC Gummies
Brand
True North Collective
Category
Edibles & Ingestibles
Price per unit
$2.50
Strain
Product Name
Rabbit Hole 1 lb bag
Brand
MJ Verdant
Category
Flower
Price per unit
$2,800.00
Strain
Hybrid
Product Name
THC-A Crystalline Rings | GMO
Brand
Kola Farms
Category
Concentrates
Price per unit
$10.00
Strain
Product Name
Seed Junky Purple Push Pop 3.5g
Brand
Seed Junky
Category
Flower
Price per unit
$20.00
Strain
Hybrid
Product Name
GUSH-MINTS 19-23% 1.4% TERPENES
Brand
Agronomos
Category
Flower
Price per unit
$1,400.00
Strain
Indica Hybrid
template
<Table has-actions layout="stack">
  <template #head>
    <TableHeaderRow
      :all-rows-selected="allSelected"
      :some-rows-selected="someSelected"
      @select="selectToggleAll"
    >
      <TableHeaderCell class="tw-min-w-[300px]">
        Product Name
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[140px]">
        Brand
      </TableHeaderCell>
      <TableHeaderCell>
        Category
      </TableHeaderCell>
      <TableHeaderCell>
        Price per unit
      </TableHeaderCell>
      <TableHeaderCell>
        Strain
      </TableHeaderCell>
      <TableHeaderCell class="tw-min-w-[120px]">
        Actions
      </TableHeaderCell>
    </TableHeaderRow>
  </template>
  <template #body>
    <TableRow
      v-for="product in data"
      :key="product.id"
      :is-selected="isSelected(product)"
      @update:is-selected="selectToggle(product)"
    >
      <TableCell class="tw-col-span-12 md:tw-col-span-8" mobile-header="Product Name">
        <div class="tw-flex tw-items-center">
          <img :src="product.featured_image" width="60" class="tw-rounded tw-mr-3" />
          {{ product.name }}
        </div>
      </TableCell>
      <TableCell class="tw-col-span-6 md:tw-col-span-4" mobile-header="Brand">
        {{ product.brand.name }}
      </TableCell>
      <TableCell class="tw-col-span-6 md:tw-col-span-5" mobile-header="Category">
        {{ product.category.name }}
      </TableCell>
      <TableCell class="tw-col-span-3 md:tw-col-span-4" mobile-header="Price per unit">
        {{ money(product.price_per_unit) }}
      </TableCell>
      <TableCell class="tw-col-span-9 md:tw-col-span-3" mobile-header="Strain">
        {{ product.strain_classification }}
      </TableCell>
      <TableCell>
        <Button icon-label>
          <IconLabel stacked icon="trashcan">Delete</IconLabel>
        </Button>
        <Button icon-label>
          <IconLabel stacked icon="edit">Edit</IconLabel>
        </Button>
      </TableCell>
    </TableRow>
  </template>
</Table>

Sticky Headers

Set the maxHeight prop to make the header sticky.

Product Name
Brand
Category
Price per unit
Strain
Citrus Splash 2x50mg THC Gummies
True North CollectiveEdibles & Ingestibles$2.50
Rabbit Hole 1 lb bag
MJ VerdantFlower$2,800.00Hybrid
THC-A Crystalline Rings | GMO
Kola FarmsConcentrates$10.00
Seed Junky Purple Push Pop 3.5g
Seed JunkyFlower$20.00Hybrid
GUSH-MINTS 19-23% 1.4% TERPENES
AgronomosFlower$1,400.00Indica Hybrid
template
<Table :sticky-header="{ listLength: 5, maxHeight: '400px' }">
  ...
</Table>

Table variant

You can render Table inside of a Module. Visit Module to see how.

Empty State

You can render an empty state in a designated slot with Table. Visit EmptyState to see all options.

Product Name
Brand
Category
Price per unit
Strain

No account linked

Add or link an existing bank account to begin making transactions

template
    <Table is-empty="!isLoading && products.length === 0">
      <template #empty>
        <EmptyState title="No account linked" subtitle="Add or link an existing bank account to begin making transactions" vignette="orders-empty">
        <template #button>
          <Button>Link new account</Button>
        </template>
        </EmptyState>
      </template>
      <template #head>
      ...

API

See the documentation below for a complete reference to all the props and classes available to the components mentioned here.