Index of every page on this site: llms.txt
All skills
nuxt avatar

/nuxt-ui

@bcc09c0 official
by nuxtnuxt/ui7k stars
1,152
Run it yourself

Build UIs with @nuxt/ui v4 — 125+ accessible Vue components with Tailwind CSS theming. Use when creating interfaces, customizing themes to match a brand, building forms, or composing layouts like dashboards, docs sites, and chat interfaces.

Use this Skill: https://skilld.dev/gh/nuxt/ui/nuxt-ui

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

referencesguidelinesconventions.md

≈2.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Conventions

Coding patterns specific to Nuxt UI.

Auto-registered modules

Nuxt UI automatically registers @nuxt/icon, @nuxt/fonts, and @nuxtjs/color-mode. Do not add them to your modules array. Configure them via root-level keys in nuxt.config.ts:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui'],
  icon: { /* @nuxt/icon options */ },
  fonts: { /* @nuxt/fonts options */ },
  colorMode: { /* @nuxtjs/color-mode options */ }
})

Disable any of them: ui: { fonts: false }, ui: { colorMode: false }.

Content module integration

When using @nuxt/content, it must come after @nuxt/ui in the modules array — otherwise prose components won't be available:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui', '@nuxt/content']
})

Add @source in your CSS so Tailwind generates classes used in markdown/MDC:

/* app/assets/css/main.css */
@import "tailwindcss";
@import "@nuxt/ui";

@source "../../../content/**/*";

Use mapContentNavigation to transform content navigation for components like UBreadcrumb:

import { mapContentNavigation } from '@nuxt/ui/utils/content'
import { findPageBreadcrumb } from '@nuxt/content/utils'

const breadcrumb = computed(() =>
  mapContentNavigation(findPageBreadcrumb(navigation.value, page.value?.path))
)

IDE setup

Recommended .vscode/settings.json for Tailwind IntelliSense autocomplete with Nuxt UI:

{
  "files.associations": { "*.css": "tailwindcss" },
  "editor.quickSuggestions": { "strings": "on" },
  "tailwindCSS.classAttributes": ["class", "ui"],
  "tailwindCSS.classFunctions": ["defineAppConfig"]
}

UApp wrapper

Always wrap your app in UApp — it provides:

  • Toast container (useToast)
  • Tooltip provider
  • Programmatic overlay context (useOverlay)
  • i18n locale support
<UApp :locale="fr">
  <NuxtPage /> <!-- or <RouterView /> for Vue -->
</UApp>

Icons

Nuxt UI registers @nuxt/icon automatically. Format: i-{collection}-{name}. Prefer lucide collection.

<UIcon name="i-lucide-sun" class="size-5" />
<UButton icon="i-lucide-plus" label="Add" />
<UAlert icon="i-lucide-info" title="Heads up" />

Install collections locally for reliable SSR and best performance:

pnpm i @iconify-json/lucide
pnpm i @iconify-json/simple-icons

Custom local collections (Nuxt only):

// nuxt.config.ts
export default defineNuxtConfig({
  icon: {
    customCollections: [{
      prefix: 'custom',
      dir: './app/assets/icons'
    }]
  }
})

Default icon overrides

Components like Modal, Select, Accordion, etc. use default icons from appConfig.ui.icons. Override them globally:

// app.config.ts
export default defineAppConfig({
  ui: {
    icons: {
      loading: 'i-lucide-refresh-cw',
      close: 'i-lucide-x',
      check: 'i-lucide-check',
      chevronDown: 'i-lucide-chevron-down',
      chevronRight: 'i-lucide-chevron-right',
      arrowLeft: 'i-lucide-arrow-left',
      arrowRight: 'i-lucide-arrow-right'
    }
  }
})

Slot patterns

Most components follow consistent slot naming:

Slot Used by Purpose
#header Card, Modal, Slideover, DashboardPanel Top section
#body DashboardPanel Scrollable content area
#footer Card, Modal, Slideover, DashboardPanel Bottom section
#left Page, DashboardNavbar Left sidebar or content
#right Page, DashboardNavbar, Header Right sidebar or content
#leading Input, Button, Alert Before main content (icon area)
#trailing Input, Button After main content (icon area)
#content Modal, Slideover, Popover, Tooltip Full content override
#default Most components Main content area

Items arrays

Many components accept an items prop. Two patterns:

Flat array — plain list:

const items = [
  { label: 'Edit', icon: 'i-lucide-pencil' },
  { label: 'Delete', icon: 'i-lucide-trash', color: 'error' }
]

Nested array — groups with automatic separators between them:

const items = [
  [
    { label: 'Edit', icon: 'i-lucide-pencil' },
    { label: 'Duplicate', icon: 'i-lucide-copy' }
  ],
  [
    { label: 'Delete', icon: 'i-lucide-trash', color: 'error' }
  ]
]

Components supporting nested arrays: UDropdownMenu, UContextMenu, UNavigationMenu. UCommandPalette uses a groups prop instead, with an items array on each group.

Composables

useToast

const toast = useToast()

toast.add({
  title: 'Success',
  description: 'Item saved',
  color: 'success',
  icon: 'i-lucide-check-circle',
  duration: 5000,
  actions: [{ label: 'Undo', onClick: () => {} }]
})

toast.remove('toast-id')
toast.clear()

useOverlay

Programmatic modals, slideovers, drawers — no template v-model needed. See overlays recipe for full patterns.

const overlay = useOverlay()
const modal = overlay.create(MyComponent)
const instance = modal.open({ title: 'Confirm?' })
if (await instance.result) { /* confirmed */ }

defineShortcuts

defineShortcuts({
  meta_k: () => openSearch(),
  escape: () => close(),
  meta_enter: {
    handler: () => submit(),
    whenever: [isFormValid]
  }
})

Keys: meta (Cmd/Ctrl), ctrl, alt, shift. Separator: _.

extractShortcuts

Wire up keyboard shortcuts from menu items:

const items = [
  { label: 'New file', kbds: ['meta', 'n'], onSelect: () => newFile() },
  { label: 'Save', kbds: ['meta', 's'], onSelect: () => save() }
]

defineShortcuts(extractShortcuts(items))

Internationalization (i18n)

Nuxt UI supports 50+ locales. Set the locale on UApp — all components inherit it.

Static locale
<script setup lang="ts">
import { fr } from '@nuxt/ui/locale'
</script>

<template>
  <UApp :locale="fr">
    <NuxtPage />
  </UApp>
</template>
Extend a built-in locale

extendLocale is auto-imported. Override specific messages or the code (affects date/time formatting in Calendar, InputDate, InputTime):

import { en } from '@nuxt/ui/locale'

const locale = extendLocale(en, {
  code: 'en-AU',
  messages: {
    commandPalette: { placeholder: 'Search a component...' }
  }
})
Custom locale from scratch
import type { Messages } from '@nuxt/ui'

const locale = defineLocale<Messages>({
  name: 'My locale',
  code: 'en',
  dir: 'ltr',
  messages: {
    // all component message keys
  }
})
Dynamic locale with @nuxtjs/i18n
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui', '@nuxtjs/i18n'],
  i18n: {
    locales: [
      { code: 'en', language: 'en', name: 'English' },
      { code: 'fr', language: 'fr', name: 'Français' },
      { code: 'ar', language: 'ar', dir: 'rtl', name: 'العربية' }
    ]
  }
})
<script setup lang="ts">
const head = useLocaleHead()

useHead(() => ({
  htmlAttrs: head.value.htmlAttrs
}))
</script>

<template>
  <UApp>
    <NuxtPage />
  </UApp>
</template>

With @nuxtjs/i18n installed, UApp follows the current i18n locale and only bundles the Nuxt UI locales matching i18n.locales. Don't use import * as locales from '@nuxt/ui/locale': it bundles every locale. Use useLocaleHead to propagate lang and dir to the <html> element.

Color mode

Nuxt UI registers @nuxtjs/color-mode automatically. Built-in components for switching:

  • UColorModeButton — single button toggle (light/dark)
  • UColorModeSwitch — toggle switch
  • UColorModeSelect — dropdown with system/light/dark options
  • UColorModeAvatar — displays different avatar per mode
  • UColorModeImage — displays different image per mode

For custom color mode UI, use useColorMode with ClientOnly to avoid hydration mismatch:

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

const isDark = computed({
  get: () => colorMode.value === 'dark',
  set: (v) => { colorMode.preference = v ? 'dark' : 'light' }
})
</script>

<template>
  <ClientOnly>
    <USwitch v-model="isDark" />
    <template #fallback>
      <div class="size-8" />
    </template>
  </ClientOnly>
</template>

Official templates

Bootstrap a project from a template instead of starting from scratch:

npm create nuxt@latest -- -t ui            # Starter
npm create nuxt@latest -- -t ui/dashboard  # Dashboard
npm create nuxt@latest -- -t ui/docs       # Docs (Nuxt Content)
npm create nuxt@latest -- -t ui/landing    # Landing page
npm create nuxt@latest -- -t ui/saas       # SaaS (landing + pricing + docs + blog)
npm create nuxt@latest -- -t ui/chat       # AI chat (Vercel AI SDK)
npm create nuxt@latest -- -t ui/editor     # Rich text editor
npm create nuxt@latest -- -t ui/portfolio  # Portfolio
npm create nuxt@latest -- -t ui/changelog  # Changelog
npm create nuxt@latest -- -t ui/calendar   # Calendar

Responsive patterns

  • Dashboard sidebar hides on mobile, shows a slideover/drawer via UDashboardSidebar mode prop
  • UHeader body slot is the mobile menu content (shown when hamburger is tapped)
  • Most components handle responsiveness automatically — avoid manual breakpoint classes unless needed
  • Use UPageAside for sidebars that should hide below lg breakpoint

Source: SKILL.md on GitHub

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

No alerts10d5 checks · Risk SAFE
  • Gen Agent Trust Hub10d

    The skill provides comprehensive documentation and development patterns for the Nuxt UI v4 component library. It includes configurations for official MCP servers and code recipes for common UI tasks using standard, well-known web technologies.

  • Socket10d

    No alerts

  • Snyk10d

    Risk: LOW · No issues

  • Runlayer8mo

    9 files scanned · No issues

  • ZeroLeaks6mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at bcc09c0. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 5 days ago.

Activeupdated 3 months ago
  • Nuxt
  • Vue
  • tailwindcss
  • components
  • ui
  • forms
  • theming
  • accessibility

README badge

README badge for nuxt/ui

Provides 125+ accessible Vue components built on Tailwind CSS and Reka UI, with semantic color tokens and theming support. Use for building interfaces in Nuxt, Vue, Laravel Inertia, or AdonisJS — forms, dashboards, documentation sites, and chat UIs.

Generated from the current SKILL.md.

Does this work with Vue outside of Nuxt?
Yes. @nuxt/ui v4 works with Vue (Vite), Laravel (Vite + Inertia), and AdonisJS (Vite + Inertia). Installation differs slightly but uses the same component library.
How do I find out what props and slots a component accepts?
Use the Nuxt UI MCP server with the `get_component` tool for full documentation, or `get_component_metadata` for a lightweight props/slots/events reference. The skill also points you to generated theme files in `.nuxt/ui/<component>.ts`.
Can I customize the theme to match my brand?
Yes. The skill includes a design-system reference that covers semantic colors, theming, and brand customization. Components use semantic color names like `text-default` and `bg-elevated` rather than raw Tailwind colors.
What if I need help building a specific layout like a dashboard or docs site?
The skill includes full layout references for dashboards, docs sites, landing pages, chat interfaces, and editors. Load the relevant reference file before coding to follow the established patterns.
Does this include form validation?
Yes. The forms reference covers validation, field layout, error handling, and Standard Schema integration for both client and server-side validation.

Generated from the current SKILL.md. These answers refresh after source changes.