navigation menu custom slot

when i want to customise the navigation menu with a custom slot to the left of the links I need to basically recreate the entire menu for that parent link right?
<!-- Events custom slot -->
<template #events-content="{ item }">
<ul class="grid gap-2 p-4 lg:w-[500px] lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)]">
<li class="row-span-3">
<p>Left side content</p>
</li>

<li v-for="child in item.children" :key="child.label">
<ULink
class="text-sm text-left rounded-md p-3 transition-colors w-full hover:bg-elevated/50"
>
<p class="font-medium text-highlighted">
{{ child.label }}
</p>
<p class="text-muted line-clamp-2">
{{ child.description }}
</p>
</ULink>
</li>
</ul>
</template>
<!-- Events custom slot -->
<template #events-content="{ item }">
<ul class="grid gap-2 p-4 lg:w-[500px] lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)]">
<li class="row-span-3">
<p>Left side content</p>
</li>

<li v-for="child in item.children" :key="child.label">
<ULink
class="text-sm text-left rounded-md p-3 transition-colors w-full hover:bg-elevated/50"
>
<p class="font-medium text-highlighted">
{{ child.label }}
</p>
<p class="text-muted line-clamp-2">
{{ child.description }}
</p>
</ULink>
</li>
</ul>
</template>
I found this in the docs but this doesn't show the icons I have for each child element so how can i fix that and the links don't take up the full remaining width like they usually do
23 Replies
kapa.ai
kapa.ai2w ago
Hi @WiFi Plug. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- You're correct that when you use a custom slot like #events-content to customize the content of a parent item in the Nuxt UI Navigation Menu, you are responsible for rendering the entire submenu content for that parent, including icons, labels, and any other details for each child. The default rendering (including icons and layout) is bypassed in favor of your custom template. To show the icons for each child item:
You need to manually render the icon in your slot template. The child objects have an icon property, so you can use a component like <UIcon :name="child.icon" /> (assuming you have the Nuxt UI Icon component available). To make the links take up the full remaining width:
You should ensure your layout classes (e.g., w-full, flex, items-center) are applied to the correct elements. The default menu uses a flex layout for links, so you may want to mimic that. Example:
<template #events-content="{ item }">
<ul class="grid gap-2 p-4 lg:w-[500px] lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)]">
<li class="row-span-3">
<p>Left side content</p>
</li>
<li v-for="child in item.children" :key="child.label">
<ULink
class="flex items-center gap-2 text-sm text-left rounded-md p-3 transition-colors w-full hover:bg-elevated/50"
>
<UIcon v-if="child.icon" :name="child.icon" class="size-5 shrink-0" />
<div class="flex-1">
<p class="font-medium text-highlighted">
{{ child.label }}
</p>
<p class="text-muted line-clamp-2">
{{ child.description }}
</p>
</div>
</ULink>
</li>
</ul>
</template>
<template #events-content="{ item }">
<ul class="grid gap-2 p-4 lg:w-[500px] lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)]">
<li class="row-span-3">
<p>Left side content</p>
</li>
<li v-for="child in item.children" :key="child.label">
<ULink
class="flex items-center gap-2 text-sm text-left rounded-md p-3 transition-colors w-full hover:bg-elevated/50"
>
<UIcon v-if="child.icon" :name="child.icon" class="size-5 shrink-0" />
<div class="flex-1">
<p class="font-medium text-highlighted">
{{ child.label }}
</p>
<p class="text-muted line-clamp-2">
{{ child.description }}
</p>
</div>
</ULink>
</li>
</ul>
</template>
- This renders the icon (if present) for each child. - The flex and flex-1 classes help the link content fill the available space, similar to the default menu layout. Reference:
This approach is based on the official documentation's example for custom content slots, which requires you to handle the rendering of all child properties yourself, including icons and layout. You can see a similar pattern in the Navigation Menu custom slot example and the default slot structure. If you want to match the default look and feel more closely, you can inspect the default classes used in the menu and apply them to your custom template as needed. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP2w ago
@kapa.ai im using nuxt ui pro for my site but i see inspira ui has some cool effects i want to pick and choose to include in my project. they have a dependency on shadcn-vue so if i install shadcn but only use it for a single background tree shaking should occur and not bloat my sites size right?
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I'm sorry, but the knowledge sources provided do not contain information about using shadcn-vue or Inspira UI with Nuxt UI Pro, nor do they discuss tree-shaking behavior when mixing these libraries. The documentation focuses on Nuxt UI, Nuxt UI Pro, and their integration with Nuxt and Vue projects, but does not address interoperability or bundle optimization with third-party UI libraries like shadcn-vue or Inspira UI. If you need details about tree-shaking and bundle size when combining these libraries, I recommend consulting the documentation for shadcn-vue and your build tool (such as Vite or Webpack) to understand how unused code is handled. For Nuxt UI and Nuxt UI Pro, tree-shaking is supported for their own components, but there is no explicit information about how this interacts with other UI libraries in the knowledge sources provided. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP2w ago
@kapa.ai where should tailwind.config.ts and tailwind.css files go in nuxt 3 compat v4
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- In Nuxt 3 with Tailwind CSS v4 (compatibility version 4), the configuration approach has changed: - You no longer need a tailwind.config.ts file for most theme customizations. Tailwind CSS v4 and Nuxt UI v3 use a CSS-first configuration approach, so you define your theme (colors, fonts, etc.) directly in your main CSS file using the @theme directive. The documentation recommends deleting the tailwind.config.ts file and moving your customizations to CSS variables inside your main CSS file (commonly assets/css/main.css or app/assets/css/main.cssGetting-started Theme UI Pro Docs Migration. - Your main CSS file (e.g., assets/css/main.css or app/assets/css/main.css) should include:
@import "tailwindcss";
@import "@nuxt/ui"; /* or "@nuxt/ui-pro" if using Pro */

@theme static {
/* Your custom theme variables here */
}

@import "tailwindcss";
@import "@nuxt/ui"; /* or "@nuxt/ui-pro" if using Pro */

@theme static {
/* Your custom theme variables here */
}

- If you still need a tailwind.config.ts file (for advanced use cases), it should be placed in the root of your project, but for most Nuxt UI v3 and Tailwind v4 projects, you can remove it and rely on the CSS-first approach Getting-started Migration. Summary:
- Place your main CSS file in assets/css/main.css or app/assets/css/main.css. - You generally do not need a tailwind.config.ts file with Nuxt UI v3 and Tailwind CSS v4; use the @theme directive in your CSS file instead. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP2w ago
@kapa.ai select menu, app language selector color mode select how do i make them take up full width?
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To make components like USelect, app language selector, or UColorModeSelect take up the full width in Nuxt UI, you should apply the w-full class to the component. This is a standard Tailwind CSS utility that sets the width to 100%. For example:
<USelect v-model="value" :items="items" class="w-full" />
<UColorModeSelect class="w-full" />
<USelect v-model="value" :items="items" class="w-full" />
<UColorModeSelect class="w-full" />
This approach is shown in the Nuxt UI documentation, where the class prop is used to control the width of the select components. By default, these components do not take up the full width unless you specify it with a class like w-full Select usage ColorModeSelect usage. If you are using a language selector component based on USelect, the same method applies: add class="w-full" to make it expand to the container's width. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP2w ago
@kapa.ai i have a layout with two slots inside how do i use it in a page properly
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To use a layout with two slots in a Nuxt 3 page, you need to: 1. Define the layout with named slots in your layouts/ directory. For example, in layouts/custom.vue:
<template>
<div>
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
</div>
</template>
<template>
<div>
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
</div>
</template>
2. Use the layout in your page by setting the layout meta and providing content for each slot using the <NuxtLayout> component and its named slots. In your page (e.g., pages/index.vue):
<script setup lang="ts">
definePageMeta({
layout: false, // Disable default layout to use NuxtLayout directly
})
</script>

<template>
<div>
<NuxtLayout name="custom">
<template #header>
<!-- Content for the header slot -->
<h1>Header Content</h1>
</template>
<!-- Default slot content -->
<p>Main page content goes here.</p>
</NuxtLayout>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: false, // Disable default layout to use NuxtLayout directly
})
</script>

<template>
<div>
<NuxtLayout name="custom">
<template #header>
<!-- Content for the header slot -->
<h1>Header Content</h1>
</template>
<!-- Default slot content -->
<p>Main page content goes here.</p>
</NuxtLayout>
</div>
</template>
Key points: - Use definePageMeta({ layout: false }) to disable the default layout if you want to use <NuxtLayout> directly in your page. - Use <template #slotName> to provide content for named slots in your layout. - The unnamed <slot /> in your layout will receive the default content inside <NuxtLayout>. This approach is documented in the Nuxt 3 guide for overriding a layout on a per-page basis and in the NuxtLayout API docs. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP2w ago
@kapa.ai nuxt ui pro color mode selector how do i manually set the icons for system, dark and light. as sometimes when loading the wrong icon is loaded for dark more
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To manually set the icons for system, dark, and light modes in the Nuxt UI Pro color mode selector (UColorModeSelect), you should configure the ui.icons property in your app.config.ts file. This ensures the correct icons are used for each mode, even during loading or hydration. Here’s how you can do it:
// app.config.ts
export default defineAppConfig({
ui: {
icons: {
system: 'i-ph-desktop', // Icon for system mode
light: 'i-ph-sun', // Icon for light mode
dark: 'i-ph-moon' // Icon for dark mode
}
}
})
// app.config.ts
export default defineAppConfig({
ui: {
icons: {
system: 'i-ph-desktop', // Icon for system mode
light: 'i-ph-sun', // Icon for light mode
dark: 'i-ph-moon' // Icon for dark mode
}
}
})
This configuration will ensure that the UColorModeSelect component uses your specified icons for each mode. If you notice the wrong icon being loaded, explicitly setting these values as above should resolve the issue ColorModeSelect usage. You can also set these icons in your Vite config if you are using Nuxt UI in a Vite-based project, but for most Nuxt 3 projects, app.config.ts is the recommended place ColorModeSelect usage. Reference from docs:
Use the app.config.ts to customize the icon with the ui.icons property:
export default defineAppConfig({
ui: {
icons: {
system: 'i-ph-desktop',
light: 'i-ph-sun',
dark: 'i-ph-moon'
}
}
})
export default defineAppConfig({
ui: {
icons: {
system: 'i-ph-desktop',
light: 'i-ph-sun',
dark: 'i-ph-moon'
}
}
})
ColorModeSelect usage
This should resolve issues with incorrect icons being shown for dark mode or other modes. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP7d ago
@kapa.ai "<script setup lang="ts"> const value = ref(0) </script> <template> <UFormField label="Price"> <UInputNumber v-model="value" :format-options="{ style: 'currency', currency: 'USD', currencyDisplay: 'code', currencySign: 'accounting', }" /> </UFormField> </template> " I want to show a dollar sign instead of "USD" at the start, and set a minimum amount of 0 so you can't go below that
kapa.ai
kapa.ai7d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To display a dollar sign ($) instead of "USD" at the start, you should set currencyDisplay: 'symbol' in the format-options prop. To prevent the value from going below 0, use the :min="0" prop on UInputNumber. Here’s how you can update your code:
<script setup lang="ts">
const value = ref(0)
</script>

<template>
<UFormField label="Price">
<UInputNumber
v-model="value"
:min="0"
:format-options="{
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol', // Shows "$" instead of "USD"
currencySign: 'accounting'
}"
/>
</UFormField>
</template>
<script setup lang="ts">
const value = ref(0)
</script>

<template>
<UFormField label="Price">
<UInputNumber
v-model="value"
:min="0"
:format-options="{
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol', // Shows "$" instead of "USD"
currencySign: 'accounting'
}"
/>
</UFormField>
</template>
- currencyDisplay: 'symbol' will show the dollar sign ($) instead of the currency code. - :min="0" ensures the value cannot go below zero. This usage is supported as shown in the UInputNumber documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7d ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP7d ago
@kapa.ai and allowing decimal points up to 2 decimal points instead of it being rounded to the nearest whole number?
kapa.ai
kapa.ai7d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To allow decimal points up to 2 decimal places in UInputNumber, you should use the step prop set to 0.01 and set minimumFractionDigits: 2 and maximumFractionDigits: 2 in the format-options prop. This ensures the input accepts and displays values with up to two decimal places. Here’s how you can update your code:
<script setup lang="ts">
const value = ref(0)
</script>

<template>
<UFormField label="Price">
<UInputNumber
v-model="value"
:min="0"
:step="0.01"
:format-options="{
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol',
currencySign: 'accounting',
minimumFractionDigits: 2,
maximumFractionDigits: 2
}"
/>
</UFormField>
</template>
<script setup lang="ts">
const value = ref(0)
</script>

<template>
<UFormField label="Price">
<UInputNumber
v-model="value"
:min="0"
:step="0.01"
:format-options="{
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol',
currencySign: 'accounting',
minimumFractionDigits: 2,
maximumFractionDigits: 2
}"
/>
</UFormField>
</template>
This configuration is supported and demonstrated in the UInputNumber documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7d ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?