N
Nuxt3mo ago
WiFi Plug

nuxt ui utable using slots in template to render each column

with the utable i want to use my own components and i would prefer to just build that in the template tag in the slots of the utable can you give ma an example to properly do this
17 Replies
kapa.ai
kapa.ai3mo ago
Hi @WiFi Plug. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- You can use slots in the UTable component to customize the rendering of cells with your own components. The UTable component from Nuxt UI provides slot customization for both header and cell content. Here's an example of how to use slots in the template to render your own components for each column:
<script setup lang="ts">
import type { TableColumn } from '@nuxt/ui'

// Your data
const data = ref([
{
id: '4600',
date: '2024-03-11T15:30:00',
status: 'paid',
email: 'example@example.com',
amount: 594
},
{
id: '4599',
date: '2024-03-11T10:10:00',
status: 'failed',
email: 'another@example.com',
amount: 276
}
// More data...
])

// Define your columns
const columns = [
{
accessorKey: 'id',
header: '#'
},
{
accessorKey: 'date',
header: 'Date'
},
{
accessorKey: 'status',
header: 'Status'
},
{
accessorKey: 'email',
header: 'Email'
},
{
accessorKey: 'amount',
header: 'Amount'
},
{
id: 'action',
header: 'Actions'
}
]
</script>
<template>
<UTable :data="data" :columns="columns" class="flex-1">
<!-- Custom header slot example -->
<template #amount-header="{ column }">
<div class="text-right">{{ column.header }}</div>
</template>

<!-- Custom cell slots for each column -->
<template #id-cell="{ row }">
<span class="font-bold">#{{ row.original.id }}</span>
</template>

<template #date-cell="{ row }">
<UTime :datetime="row.original.date" format="MMM D, HH:mm" />
</template>

<template #status-cell="{ row }">
<UBadge
:label="row.original.status"
:color="row.original.status === 'paid' ? 'success' : row.original.status === 'failed' ? 'error' : 'neutral'"
variant="subtle"
class="capitalize"
/>
</template>

<template #amount-cell="{ row }">
<div class="text-right font-medium">
{{ new Intl.NumberFormat('en-US', { style: 'currency', currency: 'EUR' }).format(row.original.amount) }}
</div>
</template>

<template #action-cell="{ row }">
<UDropdownMenu :items="[
[
{
label: 'Edit',
icon: 'i-lucide-edit'
},
{
label: 'Delete',
icon: 'i-lucide-trash',
color: 'error'
}
]
]">
<UButton
icon="i-lucide-ellipsis-vertical"
color="neutral"
variant="ghost"
aria-label="Actions"
/>
</UDropdownMenu>
</template>
</UTable>
</template>
<script setup lang="ts">
import type { TableColumn } from '@nuxt/ui'

// Your data
const data = ref([
{
id: '4600',
date: '2024-03-11T15:30:00',
status: 'paid',
email: 'example@example.com',
amount: 594
},
{
id: '4599',
date: '2024-03-11T10:10:00',
status: 'failed',
email: 'another@example.com',
amount: 276
}
// More data...
])

// Define your columns
const columns = [
{
accessorKey: 'id',
header: '#'
},
{
accessorKey: 'date',
header: 'Date'
},
{
accessorKey: 'status',
header: 'Status'
},
{
accessorKey: 'email',
header: 'Email'
},
{
accessorKey: 'amount',
header: 'Amount'
},
{
id: 'action',
header: 'Actions'
}
]
</script>
<template>
<UTable :data="data" :columns="columns" class="flex-1">
<!-- Custom header slot example -->
<template #amount-header="{ column }">
<div class="text-right">{{ column.header }}</div>
</template>

<!-- Custom cell slots for each column -->
<template #id-cell="{ row }">
<span class="font-bold">#{{ row.original.id }}</span>
</template>

<template #date-cell="{ row }">
<UTime :datetime="row.original.date" format="MMM D, HH:mm" />
</template>

<template #status-cell="{ row }">
<UBadge
:label="row.original.status"
:color="row.original.status === 'paid' ? 'success' : row.original.status === 'failed' ? 'error' : 'neutral'"
variant="subtle"
class="capitalize"
/>
</template>

<template #amount-cell="{ row }">
<div class="text-right font-medium">
{{ new Intl.NumberFormat('en-US', { style: 'currency', currency: 'EUR' }).format(row.original.amount) }}
</div>
</template>

<template #action-cell="{ row }">
<UDropdownMenu :items="[
[
{
label: 'Edit',
icon: 'i-lucide-edit'
},
{
label: 'Delete',
icon: 'i-lucide-trash',
color: 'error'
}
]
]">
<UButton
icon="i-lucide-ellipsis-vertical"
color="neutral"
variant="ghost"
aria-label="Actions"
/>
</UDropdownMenu>
</template>
</UTable>
</template>
The slot naming convention follows this pattern: - For header cells: #[column.accessorKey or column.id]-header - For data cells: #[column.accessorKey or column.id]-cell Each slot provides you with relevant properties in the slot scope: - Header slots give you access to { column, header, table } - Cell slots give you access to { cell, column, getValue, renderValue, row, table } This approach allows you to use any of your custom components within the slots while maintaining the table structure provided by UTable. Table Component documentation provides more details on customizing the UTable component with slots. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai so you know how we use template cell for each col basically in the table. what if i want an effect where on hovering over a row the background color changes?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I can help you implement a hover effect for rows in the UTable component. Based on the knowledge sources, the UTable component already has built-in hover functionality through its CSS classes. Looking at the theme configuration for the UTable component, we can see that it includes hover styling in the tbody slot:
tbody: 'divide-y divide-default [&>tr]:data-[selectable=true]:hover:bg-elevated/50 [&>tr]:data-[selectable=true]:focus-visible:outline-primary',
tbody: 'divide-y divide-default [&>tr]:data-[selectable=true]:hover:bg-elevated/50 [&>tr]:data-[selectable=true]:focus-visible:outline-primary',
This shows that rows with the data-selectable="true" attribute will have a hover effect that changes the background color to a semi-transparent elevated color. To enable this hover effect, you need to set the selectable prop on the UTable component:
<template>
<UTable :data="data" :columns="columns" selectable class="flex-1">
<!-- Your custom cell slots here -->
<template #id-cell="{ row }">
<span class="font-bold">#{{ row.original.id }}</span>
</template>

<!-- Other custom cell slots -->
</UTable>
</template>
<template>
<UTable :data="data" :columns="columns" selectable class="flex-1">
<!-- Your custom cell slots here -->
<template #id-cell="{ row }">
<span class="font-bold">#{{ row.original.id }}</span>
</template>

<!-- Other custom cell slots -->
</UTable>
</template>
If you want to customize the hover effect beyond what's provided by default, you can add your own classes to the table or use a wrapper div with custom styles:
<template>
<div class="custom-table-wrapper">
<UTable :data="data" :columns="columns" class="flex-1 [&_tbody_tr:hover]:bg-primary/10">
<!-- Your custom cell slots here -->
</UTable>
</div>
</template>

<style>
.custom-table-wrapper tbody tr:hover {
background-color: var(--your-custom-color);
transition: background-color 0.2s ease;
}
</style>
<template>
<div class="custom-table-wrapper">
<UTable :data="data" :columns="columns" class="flex-1 [&_tbody_tr:hover]:bg-primary/10">
<!-- Your custom cell slots here -->
</UTable>
</div>
</template>

<style>
.custom-table-wrapper tbody tr:hover {
background-color: var(--your-custom-color);
transition: background-color 0.2s ease;
}
</style>
You can also use the tr slot to add custom hover effects to each row:
<template>
<UTable :data="data" :columns="columns" class="flex-1">
<template #tr="{ row }">
<tr class="hover:bg-primary/10 transition-colors duration-200">
<!-- You would need to manually render cells here -->
<td v-for="cell in row.getVisibleCells()" :key="cell.id">
<slot
:name="`${cell.column.id}-cell`"
:row="row"
:cell="cell"
:getValue="cell.getValue"
>
{{ cell.getValue() }}
</slot>
</td>
</tr>
</template>

<!-- Your other custom cell slots -->
</UTable>
</template>
<template>
<UTable :data="data" :columns="columns" class="flex-1">
<template #tr="{ row }">
<tr class="hover:bg-primary/10 transition-colors duration-200">
<!-- You would need to manually render cells here -->
<td v-for="cell in row.getVisibleCells()" :key="cell.id">
<slot
:name="`${cell.column.id}-cell`"
:row="row"
:cell="cell"
:getValue="cell.getValue"
>
{{ cell.getValue() }}
</slot>
</td>
</tr>
</template>

<!-- Your other custom cell slots -->
</UTable>
</template>
The simplest approach is to use the built-in selectable prop, as it's already designed to provide the hover effect you're looking for while maintaining compatibility with your custom cell templates. Table Component provides the theming options that control these behaviors. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai nuxt ui pro i want to use the timeline component but it says soon how can i use it?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Based on the knowledge sources provided, I can see that the Timeline component is already available in Nuxt UI (not just Nuxt UI Pro). The Timeline component allows you to display a sequence of events with dates, titles, icons, or avatars. You can use the Timeline component from Nuxt UI as follows:
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'

const items = ref<TimelineItem[]>([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment.',
icon: 'i-lucide-rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops.',
icon: 'i-lucide-palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development.',
icon: 'i-lucide-code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization.',
icon: 'i-lucide-check-circle'
}
])
</script>

<template>
<UTimeline :items="items" :default-value="2" class="w-96" />
</template>
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'

const items = ref<TimelineItem[]>([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment.',
icon: 'i-lucide-rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops.',
icon: 'i-lucide-palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development.',
icon: 'i-lucide-code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization.',
icon: 'i-lucide-check-circle'
}
])
</script>

<template>
<UTimeline :items="items" :default-value="2" class="w-96" />
</template>
The Timeline component offers several features: 1. Orientation: You can set it to vertical (default) or horizontal
<UTimeline orientation="horizontal" :items="items" />

<UTimeline orientation="horizontal" :items="items" />

2. Reverse: You can reverse the direction
<UTimeline reverse :items="items" />

<UTimeline reverse :items="items" />

3. Control active item: You can control which item is active
<UTimeline v-model="active" :items="items" />

<UTimeline v-model="active" :items="items" />

4. Custom slots: You can customize the appearance of items
<UTimeline :items="items">
<template #title="{ item }">
<span>{{ item.title }}</span>
</template>
</UTimeline>

<UTimeline :items="items">
<template #title="{ item }">
<span>{{ item.title }}</span>
</template>
</UTimeline>

The Timeline component is documented at Timeline Component. If you're specifically looking for a Nuxt UI Pro component related to timelines, there doesn't appear to be a specific "Pro" version of the Timeline component in the current documentation, but there is a PageAccordion component in Nuxt UI Pro that might serve a similar purpose for displaying sequential information. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai im not sure it's released yet, i see it on github but the last github release was a month ago and timeline was 2 weeks ago so what should i do
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Based on the knowledge sources, I can see that the Timeline component is indeed available in the current release of Nuxt UI. The component is documented at Timeline Component and has examples showing how to use it. Looking at the documentation, there are multiple examples of the Timeline component in use, including basic usage, customization with slots, and theming options. This indicates that the component is released and available for use. If you're concerned about version compatibility, you can ensure you're using the latest version of Nuxt UI by upgrading your package:
npx nuxt upgrade
npx nuxt upgrade
This will update all Nuxt-related packages to their latest stable versions, including Nuxt UI. If you specifically want to use features that might only be available in the latest commits but not yet in a stable release, you could consider using the nightly release channel as mentioned in the Nightly Release Channel documentation:
{
"devDependencies": {
"nuxt": "npm:nuxt-nightly@3x"
}
}
{
"devDependencies": {
"nuxt": "npm:nuxt-nightly@3x"
}
}
However, for most use cases, the stable release should be sufficient, and the Timeline component appears to be fully available in the current stable release of Nuxt UI. You can start using the Timeline component as shown in the examples from the documentation right away. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai how do i make my whole row clickable in my slot based usage?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To make the whole row clickable when using slot-based rendering with Nuxt UI's UTable, you should use the @select event and the selectable prop. The selectable prop enables row selection and adds the necessary attributes and styles to make rows interactive and visually indicate their clickability. The @select event allows you to handle row clicks. Here’s how you can do it: 1. Add the selectable prop to your <UTable>
This will make rows respond to hover and click events. 2. Listen for the @select event
This event is triggered when a row is clicked. The handler receives the row instance and the event. 3. (Optional) Use the tr slot for custom row rendering
If you need to customize the row further, you can use the tr slot, but for most cases, the above is sufficient. Example:
<template>
<UTable
:data="data"
:columns="columns"
selectable
@select="onRowClick"
class="flex-1"
>
<!-- Your custom cell slots here -->
<template #id-cell="{ row }">
<span class="font-bold">#{{ row.original.id }}</span>
</template>
<!-- ...other cell slots... -->
</UTable>
</template>

<script setup lang="ts">
function onRowClick(row, event) {
// Handle row click, e.g., navigate or open a modal
console.log('Row clicked:', row.original)
}
</script>
<template>
<UTable
:data="data"
:columns="columns"
selectable
@select="onRowClick"
class="flex-1"
>
<!-- Your custom cell slots here -->
<template #id-cell="{ row }">
<span class="font-bold">#{{ row.original.id }}</span>
</template>
<!-- ...other cell slots... -->
</UTable>
</template>

<script setup lang="ts">
function onRowClick(row, event) {
// Handle row click, e.g., navigate or open a modal
console.log('Row clicked:', row.original)
}
</script>
With this setup, the entire row is clickable, and your custom cell slots will still render as expected. The row will also have a hover effect if you use the selectable prop, providing a good user experience. For more details, see the UTable documentation on row selection and the @select event. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai so i have a nuxt website right, could you explain nuxt 3 mobile apps for ios/android? I read about capacitor a little bit. I use nuxt ui, tailwind, supabase auth. so when converting a site to a mobile app can i still use nuxt ui, tailwind and my existing components/design? what changes?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I'm sorry, but the knowledge sources provided do not contain explicit information about building Nuxt 3 mobile apps for iOS/Android, or about using Capacitor with Nuxt 3. There is also no information about the compatibility of Nuxt UI, Tailwind, and Supabase Auth when converting a Nuxt website to a mobile app. The knowledge sources focus on Nuxt UI, Nuxt UI Pro, theming, component usage, and migration between Nuxt UI versions, but do not cover mobile app packaging or integration with tools like Capacitor. Therefore, I cannot provide a confident or detailed answer to your question based on the available information. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?