Skip to content

UiDataTable ​

La tabla central del sistema — renderiza cualquier AppVueTable de TanStack con skeleton, empty state y error state integrados.

Props ​

PropTipoDefaultDescripción
tableAppVueTable<AppFeatures, TData>RequeridoInstancia creada con useAppTable o useTableView
loadingbooleanfalseMuestra filas skeleton
skeletonRowsnumber5Número de filas skeleton
errorstring | nullnullMensaje de error
errorTitlestring'No se pudieron cargar los datos'Título en el error state
emptyTitlestring'Sin resultados'Título en el empty state
emptyDescriptionstring''Descripción en el empty state
stickybooleanfalseCabecera fija con scroll interno

Emits ​

EventoDescripción
retryCuando el usuario hace clic en "Reintentar"

Slots ​

SlotScopeDescripción
#cell-{columnId}{ row, index, cell, value }Renderizado de una celda específica
#empty—Reemplaza todo el empty state
#empty-icon—Solo el ícono del empty state
#empty-action—Solo la acción del empty state

Naming del slot de celda

El ID del slot coincide con el id definido en las columnas de TanStack. Si la columna tiene accessor('name', ...), el slot es #cell-name.

Comportamiento según estado ​

EstadoComportamiento
loading=true + sin datosMuestra filas skeleton
error + sin datosMuestra UiErrorState con botón de reintentar
error + con datosMuestra banner de advertencia encima de la tabla (sin ocultar datos)
Sin datos, sin errorMuestra UiEmptyState
Con datosRenderiza la tabla normalmente

Ejemplo completo ​

vue
<UiDataTable
  :table="memberTable"
  :loading="isInitialLoading"
  :error="memberStore.error"
  error-title="No pudimos cargar los miembros"
  :empty-title="memberStore.items.length === 0 ? 'No hay miembros todavía' : 'Sin resultados'"
  empty-description="Invita a tu primera persona al equipo."
  @retry="memberStore.fetchMembers()"
>
  <!-- Celda de nombre con avatar -->
  <template #cell-name="{ row }">
    <div class="user-cell">
      <UiAvatar :src="row.avatar_url" :name="row.name" size="sm" />
      <span>{{ row.name }}</span>
    </div>
  </template>

  <!-- Celda de estado con badge -->
  <template #cell-status="{ row }">
    <UiBadge :variant="row.status === 'active' ? 'success' : 'danger'">
      {{ row.status === 'active' ? 'Activo' : 'Inactivo' }}
    </UiBadge>
  </template>

  <!-- Ícono del empty state -->
  <template #empty-icon>
    <IconUsers :size="48" stroke-width="1.5" />
  </template>

  <!-- Acción del empty state -->
  <template #empty-action>
    <UiButton @click="openAddModal" width="auto">Invitar miembro</UiButton>
  </template>
</UiDataTable>

Nota crítica: data debe ser computed ​

TanStack Table solo reacciona a valores reactivos (refs o computed). Si se pasa el array directamente desde un store de Pinia (que desenvuelve los refs), la tabla queda congelada con los datos del mount inicial.

ts
// ❌ La tabla no se actualiza
data: memberStore.members

// ✅ Correcto — reactivo
data: computed(() => memberStore.members)

useTableView maneja esto automáticamente.

Layout responsive ​

En mobile (< 768px), la tabla se transforma en tarjetas verticales usando meta.label de cada columna como etiqueta. Define label en el meta de tus columnas para habilitar esto.

Documentación de Kaleo — plataforma SaaS multi-tenant