Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Reference for Nuxt UI v4 (125+ components built on Reka UI + Tailwind CSS v4) including forms, overlays, and theming.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/overlays.md
1# Overlays23**Prerequisite**: All overlays require `<UApp>` wrapper in app root.45**Important:** v4.4.0 includes security fixes for XSS vulnerabilities in Banner and CommandPalette components. Upgrade recommended.67## Toast (Notifications)89### Basic Usage1011```vue12<script setup>13const toast = useToast()1415function showToast() {16toast.add({17title: 'Success!',18description: 'Your changes have been saved.',19color: 'success',20icon: 'i-heroicons-check-circle'21})22}23</script>2425<template>26<UButton @click="showToast">Show Toast</UButton>27</template>28```2930### Toast Options3132```ts33toast.add({34id: 'unique-id', // Custom ID (auto-generated if omitted)35title: 'Title', // Toast title36description: 'Details', // Toast body37color: 'success', // primary, success, error, warning, info38icon: 'i-heroicons-check', // Left icon39avatar: { src: '...' }, // Avatar instead of icon40timeout: 5000, // Auto-dismiss (0 = never)41actions: [{ // Action buttons42label: 'Undo',43click: () => {}44}],45callback: () => {} // Called on dismiss46})47```4849### Toast Types5051```ts52// Success53toast.add({ title: 'Saved', color: 'success', icon: 'i-heroicons-check-circle' })5455// Error56toast.add({ title: 'Error', color: 'error', icon: 'i-heroicons-x-circle' })5758// Warning59toast.add({ title: 'Warning', color: 'warning', icon: 'i-heroicons-exclamation-triangle' })6061// Info62toast.add({ title: 'Info', color: 'info', icon: 'i-heroicons-information-circle' })6364// Remove toast65toast.remove('toast-id')6667// Clear all68toast.clear()69```7071## Modal7273### Basic Modal7475```vue76<script setup>77const isOpen = ref(false)78</script>7980<template>81<UButton @click="isOpen = true">Open Modal</UButton>8283<UModal v-model:open="isOpen">84<template #header>85<h3>Modal Title</h3>86</template>8788<p>Modal content goes here...</p>8990<template #footer>91<UButton variant="ghost" @click="isOpen = false">Cancel</UButton>92<UButton @click="save">Save</UButton>93</template>94</UModal>95</template>96```9798### Modal Props99100```vue101<UModal102v-model:open="isOpen"103title="Modal Title" <!-- Alternative to #header slot -->104description="Subtitle" <!-- Below title -->105:close="true" <!-- Show close button -->106:close-icon="'i-heroicons-x-mark'"107:overlay="true" <!-- Show backdrop -->108:transition="true" <!-- Enable animation -->109:prevent-close="false" <!-- Prevent close on overlay click -->110fullscreen <!-- Full screen mode -->111>112```113114### Programmatic Modal (useOverlay)115116```vue117<script setup>118const overlay = useOverlay()119120async function openConfirm() {121const modal = overlay.create(ConfirmModal, {122props: { title: 'Confirm action?' },123events: {124confirm: () => modal.close(true),125cancel: () => modal.close(false)126}127})128129const result = await modal.result130if (result) {131// User confirmed132}133}134</script>135```136137## Slideover138139Side panel overlay (from edge of screen).140141```vue142<script setup>143const isOpen = ref(false)144</script>145146<template>147<UButton @click="isOpen = true">Open Slideover</UButton>148149<USlideover v-model:open="isOpen" title="Settings" side="right">150<div class="p-4">151Settings content...152</div>153</USlideover>154</template>155```156157### Slideover Props158159```vue160<USlideover161v-model:open="isOpen"162title="Title"163description="Subtitle"164side="right" <!-- left, right, top, bottom -->165:overlay="true"166:transition="true"167:prevent-close="false"168>169```170171## Drawer172173Bottom sheet overlay (vaul-vue).174175```vue176<script setup>177const isOpen = ref(false)178</script>179180<template>181<UButton @click="isOpen = true">Open Drawer</UButton>182183<UDrawer v-model:open="isOpen">184<div class="p-4">185Drawer content...186</div>187</UDrawer>188</template>189```190191### Drawer Props192193```vue194<UDrawer195v-model:open="isOpen"196title="Drawer Title"197description="Subtitle"198handle <!-- Show drag handle -->199:should-scale-background="true"200:close-threshold="0.25" <!-- Swipe threshold to close -->201>202```203204## Popover205206```vue207<UPopover>208<UButton>Open Popover</UButton>209210<template #content>211<div class="p-4">212Popover content213</div>214</template>215</UPopover>216```217218### Popover Props219220```vue221<UPopover222:open="isOpen"223side="bottom" <!-- top, right, bottom, left -->224align="center" <!-- start, center, end -->225:arrow="true"226:delay="{ open: 0, close: 0 }"227>228```229230## Tooltip231232```vue233<UTooltip text="Helpful tip">234<UButton icon="i-heroicons-question-mark-circle" />235</UTooltip>236237<!-- With slot content -->238<UTooltip>239<UButton>Hover me</UButton>240<template #content>241<p>Rich tooltip content</p>242</template>243</UTooltip>244```245246## DropdownMenu247248```vue249<script setup>250const items = [251{ label: 'Edit', icon: 'i-heroicons-pencil', click: () => {} },252{ label: 'Duplicate', icon: 'i-heroicons-document-duplicate' },253{ type: 'separator' },254{ label: 'Delete', icon: 'i-heroicons-trash', color: 'error' }255]256</script>257258<template>259<UDropdownMenu :items="items">260<UButton icon="i-heroicons-ellipsis-vertical" variant="ghost" />261</UDropdownMenu>262</template>263```264265### Nested Items266267```vue268<script setup>269const items = [270{ label: 'New', children: [271{ label: 'File', click: () => {} },272{ label: 'Folder', click: () => {} }273]},274{ label: 'Delete' }275]276</script>277```278279## ContextMenu280281Right-click menu.282283```vue284<UContextMenu :items="items">285<div class="h-40 border rounded flex items-center justify-center">286Right-click here287</div>288</UContextMenu>289```290291## CommandPalette292293Search-driven command menu (Fuse.js powered).294295```vue296<script setup>297const isOpen = ref(false)298299const groups = [{300key: 'actions',301label: 'Actions',302items: [303{ label: 'New file', icon: 'i-heroicons-document-plus', click: () => {} },304{ label: 'New folder', icon: 'i-heroicons-folder-plus', click: () => {} }305]306}, {307key: 'navigation',308label: 'Navigation',309items: [310{ label: 'Home', to: '/' },311{ label: 'Settings', to: '/settings' }312]313}]314</script>315316<template>317<UCommandPalette318v-model:open="isOpen"319:groups="groups"320placeholder="Search..."321size="md"322/>323</template>324```325326### CommandPalette Props (v4.4+)327328```vue329<UCommandPalette330v-model:open="isOpen"331:groups="groups"332placeholder="Search..."333size="md" <!-- Size: sm, md, lg (v4.4+) -->334:input="{ /* props */ }" <!-- Custom input props (v4.4+) -->335/>336```337338### Keyboard Shortcut339340```vue341<script setup>342defineShortcuts({343meta_k: () => { isOpen.value = true }344})345</script>346```347348## Best Practices349350| Do | Don't |351| -------------------------------------- | --------------------------- |352| Use useToast for notifications | Build custom toast systems |353| Use UModal for dialogs | Use alerts for complex UI |354| Use Slideover for panels | Use modals for side content |355| Use Drawer for mobile sheets | Use slideover on mobile |356| Use CommandPalette for search | Build custom search UI |357| Use programmatic overlays for confirms | Create confirm components |358