Table
Basic Usage
Role Name | Date | Status |
---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | Success |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
<template>
<spr-table action :headers="headers" :data-table="data">
<div>Customize your content here!</div>
<template #action="{ row }">
<spr-lozenge :label="row.status.title" :tone="row.status.title.toLowerCase()" />
</template>
<template #action-name> Status </template>
</spr-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const headers = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: true, hasSubtext: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false },
]);
const data = ref([
{
name: {
title: 'Shift',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 30, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Success',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
]);
</script>
No Slot and Action
Role Name | Date |
---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
<template>
<spr-table :headers="headers" :data-table="data" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const headers = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: true, hasSubtext: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false },
]);
const data = ref([
{
name: {
title: 'Shift',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 30, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Success',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
]);
</script>
Table Actions
The implementation for the search field here is to emit and trigger an API call to update the data-table
Role Name | Date | |
---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
<template>
<spr-table
action
:headers="headers"
:data-table="data"
:table-actions="tableActions"
v-model:searchModel="searchModel"
/>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const headers = ref([
// Fill this with your headers
]);
const data = ref([
// Fill this with your data
]);
const tableActions = ref({
// Toggle this to true if you need search field
search: true,
// Toggle this to t rue if you need filter field
filter: true,
// Toggle this to true if you need option field
option: true,
});
const searchModel = ref('');
watch(searchModel, (newValue) => {
console.log(newValue);
// On change of the search variable trigger a fetch
// fetchApiHere();
});
</script>
Table Action Slot
Role Name | Date | |
---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
<template>
<spr-table
action
:headers="headers"
:data-table="data"
:table-actions="tableActions"
v-model:searchModel="searchModel"
>
<div>
<div class="spr-text-color-strong spr-font-size-400 spr-font-weight-medium">Table Name</div>
<div>table description</div>
</div>
<template #tableActionSection>
<spr-button>Button</spr-button>
</template>
</spr-table>
</template>
Multi Select
Allows the selection of multiple or all rows in the table.
WARNING
- If table is paginated, only the rows on the current page will be selected.
- selectedKeyId prop must be provided.
- title value of the table data object mapped with selectedKeyId in the table data must be unique.
TIP
Set the prop returnCompleteSelectedProperties to false to return the selected data as an array of objects with the selectedKeyId value only.
[]
Role Name | Date | Status | |
---|---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | Success | |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending | |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending | |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending | |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending | |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
<template>
<spr-table
action
:headers="headers"
:data-table="data"
variant="white"
:is-multi-select="true"
:selected-key-id="'name'"
:return-complete-selected-properties="false"
@update:selectedData="handleSelectedData"
>
<template #action="{ row }">
<spr-lozenge :label="row.status.title" :tone="row.status.title.toLowerCase()" />
</template>
<template #action-name> Status </template>
</spr-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const selectedTableData = ref([]);
const headers = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: true, hasSubtext: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false },
]);
const data = ref([
{
name: {
title: 'Shift',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 30, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Success',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
{
name: {
title: 'Shift 1',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 01, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Pending',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
{
name: {
title: 'Shift 2',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 01, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Pending',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
{
name: {
title: 'Shift 3',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 01, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Pending',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
{
name: {
title: 'Shift 4',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 01, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Pending',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
{
name: {
title: 'Shift 5',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 01, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Pending',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
]);
const handleSelectedData = (data) => {
// do anything with the selected data
selectedTableData.value = [...data];
}
</script>
Custom Column
You can customize the column of the table by using the dynamically named slot column field (the field property in the headers object).
Role Name | Date | |
---|---|---|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis autem minus fugiat culpa ad magnam nisi ex facilis ducimus sit neque modi porro optio cupiditate iusto, blanditiis asperiores aperiam veritatis mollitia laboriosam? Consectetur, deserunt? Reprehenderit ipsa, debitis eaque accusamus ducimus quasi deserunt laborum asperiores ea, nemo, optio corporis rerum! Veniam ex voluptatibus eveniet consequuntur saepe doloribus sint laboriosam eligendi sequi esse vero, quam consectetur iste inventore aliquam soluta quibusdam at perferendis ratione, voluptatum accusantium amet dignissimos perspiciatis. Aspernatur, voluptate amet. | Nov 30, 2025 | |
Shift 1 | Nov 01, 2025 |
<template>
<spr-table
action
:headers="headers"
:data-table="data"
>
<template #name="{ row }"> //slot name is the field property value in the headers object
<spr-tooltip :has-max-width="true" :text="String(row.name.title)">
<div
ref="rowTitleRef"
class="spr-truncate spr-text-sm"
:style="`max-width: ${getCellMaxWidth}`"
>
{{ row.name.title }}
</div>
</spr-tooltip>
<span class="spr-text-color-base spr-text-xs spr-font-normal">{{ row.name.subtext }}</span>
</template>
<template #action>
<div class="spr-flex spr-flex-auto spr-justify-end spr-gap-2">
<spr-button variant="primary" tone="success" size="small"> Action 1 </spr-button>
<spr-button variant="primary" tone="danger" size="small"> Action 2 </spr-button>
</div>
</template>
</spr-table>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
const rowTitleRef = ref<HTMLElement|null>(null);
const cellWidth = ref(0)
const getCellMaxWidth = computed(() => {
return cellWidth.value > 0 ? `${cellWidth.value}px` : '100%'
})
const headers = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: true, hasSubtext: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false },
]);
const data = ref([
{
name: {
title: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis autem minus fugiat culpa ad magnam nisi ex facilis ducimus sit neque modi porro optio cupiditate iusto, blanditiis asperiores aperiam veritatis mollitia laboriosam? Consectetur, deserunt? Reprehenderit ipsa, debitis eaque accusamus ducimus quasi deserunt laborum asperiores ea, nemo, optio corporis rerum! Veniam ex voluptatibus eveniet consequuntur saepe doloribus sint laboriosam eligendi sequi esse vero, quam consectetur iste inventore aliquam soluta quibusdam at perferendis ratione, voluptatum accusantium amet dignissimos perspiciatis. Aspernatur, voluptate amet.',
subtext: 'Lorem ipsectetur adipiscing elit.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 30, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Success',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
{
name: {
title: 'Shift 1',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 01, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Pending',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
}
]);
</script>
Table Footer
The implementation for the pagination here is to emit and trigger an API call to update the data-table
Role Name | Date | |
---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
<template>
<spr-table action :headers="headers" :data-table="data">
<template #footer>
<spr-table-pagination
v-model:selected-row-count="selectedRowCount"
:total-items="totalItems"
:current-page="currentPage"
:dropdown-selection="dropdownSelection"
@previous="handlePrevious"
@next="handleNext"
:version="'backend'"
/>
</template>
</spr-table>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const headers = ref([
// Fill this with your headers
]);
const data = ref([
// Fill this with your data
]);
const totalItems = ref(100);
const currentPage = ref(2);
const dropdownSelection = [
{ text: 10, value: 10 },
{ text: 20, value: 20 },
{ text: 30, value: 30 },
];
const selectedRowCount = ref(10);
watch(selectedRowCount, (newValue) => {
console.log('Selected Row Count:', newValue);
// On change of the selectedRowCount variable trigger a fetch
// fetchApiHere();
});
const handlePrevious = () => {
console.log('clicked previous');
if (currentPage.value > 1) {
currentPage.value--;
}
fetchItems(currentPage.value);
};
const handleNext = () => {
console.log('clicked next');
if (currentPage.value * selectedRowCount.value < totalItems.value) {
currentPage.value++;
}
fetchItems(currentPage.value);
};
const fetchItems = computed((page) => {
const response = apiCall(page);
data.value = parse(response);
});
</script>
Cells
Lozenge
You can change the title of a cell to a lozenge
Role Name | Date | |
---|---|---|
![]() Active Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | ![]() Lozenge |
<template>
<spr-table action :headers="headersLozenge" :data-table="dataLozenge" variant="surface" @onSort="handleSort">
<div>Customize your content here!</div>
</spr-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const headersLozenge = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: false, hasSubtext: true, hasLozengeTitle: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false, hasLozengeTitle: true },
]);
const lozengeTitle = {
title: 'Active',
tone: 'success',
avatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
fill: true,
lozengeIcon: 'ph:building'
}
const lozengeSecondTitle = {
title: 'Lozenge',
avatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
}
const dataLozenge = [
{
name: {
title: lozengeTitle,
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
lozengeIcon: 'ph:user',
},
lastUpdate: {
title: lozengeSecondTitle,
subtext: 'Lorem ipsum dolor ',
lozengeFill: true,
lozengeAvatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
];
</script>
Chips
You can change the title of a cell to a chip
Role Name | Date | |
---|---|---|
![]() Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | ![]() 2 |
<template>
<spr-table action :headers="headersChips" :data-table="dataChips" variant="surface" @onSort="handleSort">
<div>
Customize your content here!
</div>
</spr-table>
</template>
<script setup lang='ts'>
import { ref } from 'vue';
const headersChips = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: false, hasSubtext: true, hasChipTitle: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false, hasChipTitle: true },
])
const chipsTitle = {
title: 'Active',
icon: 'ph:building',
iconWeight: 'regular',
avatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
avatarVariant: 'image',
}
const chipsSecondTitle = {
title: 'Second Title',
icon: 'ph:users-three',
iconWeight: 'regular',
badge: true,
badgeText: '2',
badgeVariant: 'brand',
avatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
avatarVariant: 'image',
}
const dataChips = [
{
name: {
title: chipsTitle,
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
lozengeIcon: 'ph:user'
},
lastUpdate: {
title: chipsSecondTitle,
subtext: 'Lorem ipsum dolor ',
lozengeFill: true,
lozengeAvatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg'
},
},
]
</script>
Multiple Chips and Lozenges
You can change the title to multiple chips and lozenges
Role Name | Date | |
---|---|---|
![]() First ![]() Second Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | ![]() 2 ![]() |
<template>
<spr-table action :headers="headersMultiple" :data-table="dataMultiple" variant="surface" @onSort="handleSort">
<div>
Customize your content here!
</div>
</spr-table>
</template>
<script setup lang='ts'>
import { ref } from 'vue';
const headersMultiple = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: false, hasSubtext: true, hasLozengeTitle: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false, hasChipTitle: true },
])
const lozengeCell = {
title: 'Active',
tone: 'success',
avatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
fill: true,
lozengeIcon: 'ph:building',
};
const chipCell = [
{
title: 'Active',
icon: 'ph:building',
iconWeight: 'regular',
badge: true,
badgeText: '2',
badgeVariant: 'brand',
avatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
avatarVariant: 'image',
},
{
title: 'Active',
icon: 'ph:building',
iconWeight: 'regular',
badge: true,
badgeText: '2',
badgeVariant: 'brand',
avatarUrl: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
avatarVariant: 'image',
}
]
const dataMultiple = [
{
name: {
title: lozengeCell,
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: chipCell,
subtext: 'Lorem ipsum dolor ',
chipTitle: chipCell
},
},
]
</script>
Variant
You can customize the header background of the table using the variant
attribute. The available options are white
and surface
.
Role Name | Date | |
---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 |
<template>
<spr-table action :headers="headers" :data-table="data">
<div>Customize your content here!</div>
</spr-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const headers = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: true, hasSubtext: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false },
]);
const data = ref([
{
name: {
title: 'Shift',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 30, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Success',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
]);
const handleSort = (e) => {
console.log('sort', e);
};
</script>
Sorting
Role Name | Date | Status |
---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | Success |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
<template>
<spr-table action :headers="headers" :data-table="data" variant="white" @onSort="getSortOrder()" sortOrder>
<div>Customize your content here!</div>
<template #action="{ row }">
<spr-lozenge :label="row.status.title" :tone="row.status.title.toLowerCase()" />
</template>
<template #action-name> Status </template>
</spr-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const headers = ref([
{ field: 'name', name: 'Role Name', sort: true, hasAvatar: true, hasSubtext: true },
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false },
]);
const data = ref([
{
name: {
title: 'Shift',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 30, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Success',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
]);
const sortOrder = ref('asc');
const getSortOrder = () => {
sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc';
console.log(sortOrder.value);
return sortOrder.value;
};
</script>
Badge
Badges can have different color schemes to indicate various statuses, such as disabled
, brand
, danger
, or information
.
Role Name 1 | Date 2 | Status |
---|---|---|
S Shift Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 30, 2025 | Success |
S1 Shift 1 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S2 Shift 2 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S3 Shift 3 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S4 Shift 4 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
S5 Shift 5 Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam. | Nov 01, 2025 | Pending |
<template>
<spr-table action :headers="headersWithBadge" :data-table="data">
<div>Customize your content here!</div>
<template #action="{ row }">
<spr-lozenge :label="row.status.title" :tone="row.status.title.toLowerCase()" />
</template>
<template #action-name> Status </template>
</spr-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const headersWithBadge = ref([
{
field: 'name',
name: 'Role Name',
sort: true,
hasAvatar: true,
hasSubtext: true,
badgeText: '1',
badgeVariant: 'brand',
},
{ field: 'lastUpdate', name: 'Date', sort: true, hasAvatar: false, hasSubtext: false },
]);
const data = ref([
{
name: {
title: 'Shift',
subtext: 'Lorem ipsectetur adipiscing elit. Sed etiam, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
lastUpdate: {
title: 'Nov 30, 2025',
subtext: 'Lorem ipsum dolor ',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
status: {
title: 'Success',
subtext: 'Lorem ipsum dolor sit amet, consectetur, sed etiam.',
image: 'https://media.sproutsocial.com/uploads/2022/06/profile-picture.jpeg',
},
},
]);
</script>
API Reference
Name | Description | Type | Value |
---|---|---|---|
action | Slot for for table data | boolean | false |
dataTable | For table values | Object | TableData { [key: string]: { title: string | LozengeTitle | ChipTitle | LozengeTitle[] | ChipTitle[]; subtext: string; image: string; icon: string; lozengeFill: boolean; lozengeAvatarUrl: string; lozengeTone: string; lozengeIcon: string; } | string | number; } |
Lozenge Title | For use of Lozenges in titles | Object | interface LozengeTitle { title: string; fill?: boolean; avatarUrl?: string; tone?: (typeof LOZENGE_TONE)[number]; icon?: string; } |
Chip Title | For use of Lozenges in titles | Object | interface ChipTitle { title: string; icon: string; iconWeight: string; badgeText: string; badgeVariant: string; avatarUrl: string; avatarVariant: (typeof AVATAR_VARIANT)[number]; } |
headers | define your table headers | Object | Header { field: string; name: string; sort: boolean; hasAvatar: boolean; hasIcon: boolean; hasSubtext: boolean; hasLozengeTitle: boolean; badgeText: string; badgeVariant: string; } |
emptyState | Customize table empty state | Object | { description: 'No results found', subDescription: 'Try a different search term', image: 'location', size: 'large', } |
tableActions | Customize table actions | Object | { search: boolean; filter: boolean; option: boolean; } |
tableFooter | Customize table footer | Object | { totalItems: number; currentPage: number; dropdownSelection: { text: string; value: string }[]; } |
variant | Change background color of header | surface, white | surface |
isRowClickable | Make table row clickable and emits onRowClick | boolean | false |
@onSort | Emits when sorting is triggered | function | - |
@onRowClick | Emits table data and row index when table row is clicked | function | - |
@onHover | Emits triggered when hovered | function | { active: true, data: item } |
hasLozengeTitle | Allows the use of lozenge for title attribute of data | boolean | false |
removeHeaderOnEmpty | Removes the headers when table is empty | boolean | false |
isMultiSelect | Allows the use of checkbox to multiselect from the table | boolean | false |
selectedKeyId | Specifies which key in the table data object will be used as an identifier and acts as a reference to a specific property within each row of the table's data. | string | '' |
@update:selectedData | Emits selected data on select | boolean | false |
returnCompleteSelectedProperties | Determines the structure of the data emitted when rows are selected in the table. If set to true, will emit the entire table data object of the selected row. Else, will emit the value of the property specified by the selectedKeyId prop. | boolean | false |