跳至主要內容

Nuxt UI 元件庫完整使用指南

Nuxt UI 元件庫完整使用指南

Nuxt UI 是由 Nuxt 官方團隊開發的 UI 元件庫,基於 Tailwind CSS 和 Headless UI 打造。它提供了豐富的高品質元件,設計上注重可客製化性與無障礙性,是 Nuxt 3 專案的最佳搭檔。

安裝設定

# 安裝 Nuxt UI
npx nuxi module add ui

# 或手動安裝
npm install @nuxt/ui
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui'],
});

Nuxt UI 會自動配置 Tailwind CSS 和 Nuxt Color Mode,無需額外設定。

主題系統

Nuxt UI 基於 CSS 自訂屬性建立主題,支援深淺色模式:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui'],
  ui: {
    primary: 'blue',      // 主色
    gray: 'cool',         // 灰色系
  },
});

自訂主題色

// tailwind.config.ts
import type { Config } from 'tailwindcss';

export default {
  theme: {
    extend: {
      colors: {
        primary: {
          50: '#eff6ff',
          100: '#dbeafe',
          // ...
          900: '#1e3a5f',
          950: '#172554',
        },
      },
    },
  },
} satisfies Config;

常用元件

UButton

<template>
  <div class="flex gap-3 flex-wrap">
    <!-- 基本按鈕 -->
    <UButton label="確認" />
    <UButton label="取消" color="gray" variant="ghost" />
    <UButton label="危險操作" color="red" />

    <!-- 帶圖示 -->
    <UButton icon="i-heroicons-plus" label="新增" />
    <UButton trailing-icon="i-heroicons-arrow-right" label="下一步" />

    <!-- 載入狀態 -->
    <UButton :loading="isLoading" label="儲存中" />

    <!-- 連結按鈕 -->
    <UButton to="/dashboard" label="前往儀表板" />
  </div>
</template>

UInput 與 UForm

<script setup lang="ts">
import { z } from 'zod';
import type { FormSubmitEvent } from '#ui/types';

const schema = z.object({
  email: z.string().email('請輸入有效的 Email'),
  password: z.string().min(8, '密碼至少 8 個字元'),
});

type Schema = z.output<typeof schema>;

const state = reactive({
  email: '',
  password: '',
});

async function onSubmit(event: FormSubmitEvent<Schema>) {
  console.log(event.data);
  // 送出登入請求
}
</script>

<template>
  <UForm :schema="schema" :state="state" @submit="onSubmit" class="space-y-4">
    <UFormGroup label="Email" name="email">
      <UInput v-model="state.email" type="email" placeholder="you@example.com" />
    </UFormGroup>

    <UFormGroup label="密碼" name="password">
      <UInput v-model="state.password" type="password" />
    </UFormGroup>

    <UButton type="submit" label="登入" block />
  </UForm>
</template>

UTable

<script setup lang="ts">
const columns = [
  { key: 'name', label: '姓名', sortable: true },
  { key: 'email', label: 'Email' },
  { key: 'role', label: '角色' },
  { key: 'status', label: '狀態' },
  { key: 'actions', label: '操作' },
];

const users = ref([
  { id: 1, name: 'Alice', email: 'alice@example.com', role: '管理員', status: 'active' },
  { id: 2, name: 'Bob', email: 'bob@example.com', role: '編輯', status: 'inactive' },
]);
</script>

<template>
  <UTable :columns="columns" :rows="users">
    <template #status-data="{ row }">
      <UBadge
        :color="row.status === 'active' ? 'green' : 'gray'"
        :label="row.status === 'active' ? '啟用' : '停用'"
      />
    </template>

    <template #actions-data="{ row }">
      <div class="flex gap-2">
        <UButton icon="i-heroicons-pencil" size="xs" variant="ghost" @click="editUser(row)" />
        <UButton icon="i-heroicons-trash" size="xs" variant="ghost" color="red" @click="deleteUser(row)" />
      </div>
    </template>
  </UTable>
</template>

UModal

<script setup lang="ts">
const isOpen = ref(false);

async function confirmDelete() {
  await deleteItem();
  isOpen.value = false;
}
</script>

<template>
  <UButton label="刪除" color="red" @click="isOpen = true" />

  <UModal v-model="isOpen">
    <UCard>
      <template #header>
        <h3 class="text-lg font-semibold">確認刪除</h3>
      </template>

      <p>確定要刪除這筆資料嗎?此操作無法復原。</p>

      <template #footer>
        <div class="flex justify-end gap-3">
          <UButton label="取消" color="gray" variant="ghost" @click="isOpen = false" />
          <UButton label="確認刪除" color="red" @click="confirmDelete" />
        </div>
      </template>
    </UCard>
  </UModal>
</template>

UNotifications(Toast 通知)

<script setup lang="ts">
const toast = useToast();

function handleSave() {
  try {
    // 儲存邏輯
    toast.add({
      title: '儲存成功',
      description: '你的變更已成功儲存。',
      icon: 'i-heroicons-check-circle',
      color: 'green',
    });
  } catch (error) {
    toast.add({
      title: '儲存失敗',
      description: error.message,
      icon: 'i-heroicons-x-circle',
      color: 'red',
    });
  }
}
</script>

<template>
  <!-- 在 app.vue 中加入 UNotifications 元件 -->
  <UNotifications />
  <UButton label="儲存" @click="handleSave" />
</template>

覆寫元件樣式(app.config.ts)

Nuxt UI 的所有元件樣式都可以透過 app.config.ts 覆寫,無需修改元件原始碼:

// app.config.ts
export default defineAppConfig({
  ui: {
    button: {
      rounded: 'rounded-full',  // 所有按鈕改為圓角
      default: {
        size: 'md',
        variant: 'solid',
        color: 'primary',
      },
    },
    card: {
      rounded: 'rounded-xl',
      shadow: 'shadow-lg',
    },
    input: {
      rounded: 'rounded-lg',
    },
  },
});

useColorMode 深淺色切換

<script setup lang="ts">
const colorMode = useColorMode();

function toggleColorMode() {
  colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark';
}
</script>

<template>
  <UButton
    :icon="colorMode.value === 'dark' ? 'i-heroicons-sun' : 'i-heroicons-moon'"
    variant="ghost"
    @click="toggleColorMode"
  />
</template>

總結

Nuxt UI 提供了一套高品質、高度可客製化的元件庫,完美整合 Nuxt 3 生態系。它的設計哲學是:合理的預設值 + 完整的客製化空間,讓你既能快速起步,又不被框架限制。對於新的 Nuxt 3 專案,Nuxt UI 是值得優先考慮的 UI 解決方案。

分享這篇文章