Theming

UI Customization

Fine-tune the NuGrid appearance with the UI prop.

The ui prop provides granular control over NuGrid's appearance, allowing you to customize specific elements without creating a full theme.

UI Prop Structure

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :ui="{
      root: 'custom-root-class',
      base: 'custom-table-class',
      thead: 'custom-thead-class',
      tbody: 'custom-tbody-class',
      th: 'custom-th-class',
      td: 'custom-td-class',
    }"
  />
</template>

Available UI Slots

SlotElementDescription
rootContainer divOutermost wrapper
baseTable elementThe table itself
theadtheadTable header section
tbodytbodyTable body section
tfoottfootTable footer section
trtrAll table rows
ththHeader cells
tdtdData cells
loadingdivLoading overlay
emptydivEmpty state message
separatortrSeparator rows

Common Customizations

Header Styling

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :ui="{
      thead: '[&>tr]:bg-gradient-to-r [&>tr]:from-primary/10 [&>tr]:to-primary/5',
      th: 'font-bold text-primary uppercase tracking-wider',
    }"
  />
</template>

Cell Styling

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :ui="{
      td: 'py-4 px-6 text-sm border-b border-gray-100 dark:border-gray-800',
    }"
  />
</template>

Row Styling

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :ui="{
      tbody: `
        [&>tr]:transition-colors
        [&>tr:hover]:bg-primary/5
        [&>tr:nth-child(even)]:bg-gray-50
        dark:[&>tr:nth-child(even)]:bg-gray-800/30
      `,
    }"
  />
</template>

Data Attributes

NuGrid adds data attributes for state-based styling:

Row Attributes

AttributeValuesDescription
data-selectedtrue/falseRow selection state
data-focusedtrue/falseRow focus state
data-groupedtrue/falseIs a group row
data-expandedtrue/falseGroup expansion state
data-add-rowtrue/falseIs the add-new row

Cell Attributes

AttributeValuesDescription
data-focusedtrue/falseCell focus state
data-editingtrue/falseCell editing state
data-invalidtrue/falseValidation error state
data-pinnedleft/rightColumn pinning

State-Based Styling

Style based on data attributes:

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :ui="{
      tbody: `
        [&>tr[data-selected=true]]:bg-primary/10
        [&>tr[data-focused=true]]:ring-2
        [&>tr[data-focused=true]]:ring-primary
      `,
      td: `
        [&[data-focused=true]]:bg-primary/5
        [&[data-editing=true]]:bg-warning/10
        [&[data-invalid=true]]:bg-error/10
        [&[data-invalid=true]]:ring-1
        [&[data-invalid=true]]:ring-error
      `,
    }"
  />
</template>

Pinned Column Styling

Style pinned columns:

<template>
  <NuGrid
    v-model:column-pinning="columnPinning"
    :data="data"
    :columns="columns"
    :ui="{
      th: `
        [&[data-pinned=left]]:bg-white
        [&[data-pinned=left]]:shadow-[2px_0_5px_-2px_rgba(0,0,0,0.1)]
        dark:[&[data-pinned=left]]:bg-gray-900
        [&[data-pinned=right]]:bg-white
        [&[data-pinned=right]]:shadow-[-2px_0_5px_-2px_rgba(0,0,0,0.1)]
        dark:[&[data-pinned=right]]:bg-gray-900
      `,
      td: `
        [&[data-pinned=left]]:bg-white
        dark:[&[data-pinned=left]]:bg-gray-900
        [&[data-pinned=right]]:bg-white
        dark:[&[data-pinned=right]]:bg-gray-900
      `,
    }"
  />
</template>

Group Row Styling

Style grouped rows:

<template>
  <NuGrid
    v-model:grouping="grouping"
    :data="data"
    :columns="columns"
    :ui="{
      tbody: `
        [&>tr[data-grouped=true]]:bg-gray-100
        dark:[&>tr[data-grouped=true]]:bg-gray-800
        [&>tr[data-grouped=true]]:font-semibold
      `,
    }"
  />
</template>

Add Row Styling

Style the add-new row:

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :add-new-row="true"
    :ui="{
      tbody: `
        [&>tr[data-add-row=true]]:bg-success/5
        [&>tr[data-add-row=true]]:border-dashed
        [&>tr[data-add-row=true]]:border-success/30
      `,
    }"
  />
</template>

Loading State Styling

Style the loading state:

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :loading="isLoading"
    :ui="{
      loading: 'absolute inset-0 bg-white/50 dark:bg-gray-900/50 backdrop-blur-sm flex items-center justify-center',
    }"
  />
</template>

Empty State Styling

Style the empty state:

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :ui="{
      empty: 'py-16 text-center text-gray-400',
    }"
  >
    <template #empty>
      <div class="flex flex-col items-center gap-2">
        <UIcon name="i-lucide-inbox" class="size-12 text-gray-300" />
        <p class="text-lg font-medium">No data available</p>
        <p class="text-sm">Add some items to get started.</p>
      </div>
    </template>
  </NuGrid>
</template>

Combining Theme and UI

The ui prop is merged with the theme:

<script setup lang="ts">
import { nuGridThemeCompact } from '@nu-grid/nuxt/themes'
</script>

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :theme="nuGridThemeCompact"
    :ui="{
      thead: '[&>tr]:bg-primary/10',  <!-- Added to compact theme -->
    }"
  />
</template>

Example: Fully Customized Grid

<template>
  <NuGrid
    v-model:row-selection="rowSelection"
    :data="data"
    :columns="columns"
    selection="multi"
    :editing="{ enabled: true }"
    :ui="{
      root: 'rounded-xl overflow-hidden shadow-lg border border-gray-200 dark:border-gray-700',
      base: 'w-full border-separate border-spacing-0',
      thead: `
        [&>tr]:bg-gradient-to-r
        [&>tr]:from-slate-100
        [&>tr]:to-slate-50
        dark:[&>tr]:from-slate-800
        dark:[&>tr]:to-slate-900
      `,
      th: `
        px-4 py-3
        text-left text-xs font-bold uppercase tracking-wider
        text-slate-600 dark:text-slate-300
        first:rounded-tl-xl last:rounded-tr-xl
      `,
      tbody: `
        [&>tr]:transition-all [&>tr]:duration-150
        [&>tr:hover]:bg-slate-50 dark:[&>tr:hover]:bg-slate-800/50
        [&>tr[data-selected=true]]:bg-primary/10
        [&>tr:last-child>td]:border-b-0
        [&>tr:last-child>td:first-child]:rounded-bl-xl
        [&>tr:last-child>td:last-child]:rounded-br-xl
      `,
      td: `
        px-4 py-3
        text-sm text-slate-700 dark:text-slate-300
        border-b border-slate-100 dark:border-slate-800
        [&[data-focused=true]]:ring-2
        [&[data-focused=true]]:ring-inset
        [&[data-focused=true]]:ring-primary/50
        [&[data-editing=true]]:bg-primary/5
      `,
      empty: 'py-12 text-center text-slate-400',
    }"
  />
</template>

Next Steps

Built-in Themes

Explore available themes.

Custom Themes

Create your own themes.