Components

Reference guide for all shared and dashboard-specific components with props, slots, and usage examples.

Component Architecture

Components are organized into directories that determine their auto-import prefix. No import statements are needed — Nuxt discovers and registers them automatically.

DirectoryPrefixExample
components/shared/Shared<SharedGlassCard>
components/dashboard/Dashboard<DashboardStatsCard>
components/docs/Docs<DocsCodeBlock>

SharedGlassCard

The primary container component. Renders a card with solid surface background and shadow elevation. Supports an optional title, subtitle, and hover effect.

PropTypeDefaultDescription
titlestringCard heading text
subtitlestringMuted text below the heading
hoverablebooleanfalseEnable shadow elevation on hover
paddingbooleantrueAdd default p-6 padding
classNamestringAdditional CSS classes
vue
<!-- Basic card -->
<SharedGlassCard>
  <p>Card content goes here.</p>
</SharedGlassCard>

<!-- Card with title and hover effect -->
<SharedGlassCard title="Revenue" subtitle="Last 30 days" hoverable>
  <p>$24,500</p>
</SharedGlassCard>

<!-- Card without padding (for tables or charts) -->
<SharedGlassCard title="Orders" :padding="false">
  <table>...</table>
</SharedGlassCard>

SharedPageHeader

Consistent page title with optional description and an actions slot for buttons.

PropTypeDescription
titlestring (required)Page heading text
descriptionstringSubtitle below the heading

Slots:#actions — rendered on the right side, typically for action buttons.

vue
<!-- Basic header -->
<SharedPageHeader title="Orders" description="Manage customer orders" />

<!-- Header with action buttons -->
<SharedPageHeader title="Products" description="Your product catalog">
  <template #actions>
    <UButton icon="i-lucide-plus" label="Add Product" />
    <UButton icon="i-lucide-download" label="Export" variant="outline" />
  </template>
</SharedPageHeader>

SharedDataTable

A feature-rich data table with sorting, pagination, and row selection. Used across all CRUD listing pages.

PropTypeDescription
columnsColumn[]Column definitions with key, label, sortable, and optional cell slot
dataany[]Row data array
vue
<SharedDataTable
  :columns="[
    { key: 'name', label: 'Name', sortable: true },
    { key: 'email', label: 'Email' },
    { key: 'status', label: 'Status' },
  ]"
  :data="users"
/>

SharedStatusBadge

A colored badge that maps status values to appropriate colors automatically.

PropTypeDescription
statusstring (required)Status value that determines badge color

Color mapping:

StatusColor
active, completed, paid, deliveredGreen / Success
pending, processingYellow / Warning
cancelled, overdue, failedRed / Error
draft, inactiveGray / Neutral
vue
<SharedStatusBadge status="active" />
<SharedStatusBadge status="pending" />
<SharedStatusBadge status="cancelled" />

SharedEmptyState

Placeholder for empty data views. Displays an icon, title, description, and optional action slot.

PropTypeDescription
titlestring (required)Main heading text
descriptionstringExplanation text
iconstringLucide icon name
vue
<SharedEmptyState
  title="No orders found"
  description="Try adjusting your search or filters."
  icon="i-lucide-package"
>
  <template #action>
    <UButton label="Create Order" icon="i-lucide-plus" />
  </template>
</SharedEmptyState>

SharedConfirmDialog

A modal dialog for confirming destructive actions like deleting records. Uses v-model:open for visibility control.

PropTypeDescription
titlestringDialog heading
messagestringConfirmation message body
confirmLabelstringConfirm button text (default: "Delete")
vue
<script setup lang="ts">
const showDialog = ref(false)

function handleDelete() {
  // Perform delete action
  showDialog.value = false
}
</script>

<template>
  <UButton label="Delete" color="error" @click="showDialog = true" />

  <SharedConfirmDialog
    v-model:open="showDialog"
    title="Delete Order"
    message="Are you sure? This action cannot be undone."
    confirmLabel="Delete Order"
    @confirm="handleDelete"
  />
</template>

DashboardStatsCard

Displays a key metric with an icon, value, and optional change percentage. Used in the stats rows of all dashboard variants.

PropTypeDescription
labelstringMetric name (e.g., "Total Revenue")
valuestring | numberMetric value (e.g., "$24,500")
changenumberPercentage change (positive = green, negative = red)
iconstringLucide icon name
vue
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
  <DashboardStatsCard
    label="Total Revenue"
    value="$24,500"
    :change="12.5"
    icon="i-lucide-dollar-sign"
  />
  <DashboardStatsCard
    label="Orders"
    value="1,248"
    :change="-3.2"
    icon="i-lucide-shopping-cart"
  />
</div>

DashboardChartCard

A card wrapper designed for charts. Provides a title, optional subtitle, and a content area with a set height for the chart container.

PropTypeDescription
titlestringChart heading
subtitlestringMuted text below the heading
heightnumberChart container height in pixels

DocsCodeBlock

Syntax-highlighted code block powered by Shiki. Includes a copy-to-clipboard button and language label.

PropTypeDefaultDescription
codestring (required)The code to highlight and display
languagestringtypescriptShiki language identifier (vue, css, json, bash, etc.)
vue
<DocsCodeBlock
  language="typescript"
  :code="'const greeting = \'Hello, World!\''"
/>

Tip

All shared components can be used anywhere without imports — Nuxt auto-imports them based on their directory path. Just type <SharedGlassCard> in any template and it works.

Next Steps

Learn about writing tests in the Testing guide, or see how the mock API works in Mock API.