N
Nuxt2mo ago
RainyDev

Content within <DashboardLayout> not scrollable

Hi there, I have a weird issue. When I use the <DashboardLayout> to create a sidebar and then have content within the <Slot /> the content is not scrollable (eg. my table). When I dont use <DashboardLayout> it works. Why? Code:
<template>
<UDashboardLayout>
<UDashboardPanel :width="250" :resizable="{ min: 200, max: 300 }" collapsible>
<UDashboardNavbar>
<template #right>
<UAvatar :src="user.avatar.src" :alt="user.avatar.alt" size="md" class="mr-2" />
<UDropdown
:items="items"
:content="{ align: 'center', collisionPadding: 12 }"
:ui="{ content: 'w-48' }"
>
<UButton
v-bind="{
...user.avatar,
label: user.name,
trailingIcon: 'i-lucide-chevrons-up-down',
}"
variant="ghost"
block
class="data-[state=open]:bg-(--ui-bg-elevated)"
:ui="{
trailingIcon: 'text-(--ui-text-dimmed)',
}"
/>
</UDropdown>
</template>
</UDashboardNavbar>

<UDashboardSidebar>
<UDashboardSidebarLinks :links="[
{ label: 'Home', icon: 'i-lucide-home', to: '/admin' },
{ label: 'Licenses', icon: 'i-lucide-key', to: '/admin/licenses' },
{ label: 'Settings', icon: 'i-lucide-settings', to: '/admin/settings' },
]" />
</UDashboardSidebar>
</UDashboardPanel>

<slot />

</UDashboardLayout>
</template>
<template>
<UDashboardLayout>
<UDashboardPanel :width="250" :resizable="{ min: 200, max: 300 }" collapsible>
<UDashboardNavbar>
<template #right>
<UAvatar :src="user.avatar.src" :alt="user.avatar.alt" size="md" class="mr-2" />
<UDropdown
:items="items"
:content="{ align: 'center', collisionPadding: 12 }"
:ui="{ content: 'w-48' }"
>
<UButton
v-bind="{
...user.avatar,
label: user.name,
trailingIcon: 'i-lucide-chevrons-up-down',
}"
variant="ghost"
block
class="data-[state=open]:bg-(--ui-bg-elevated)"
:ui="{
trailingIcon: 'text-(--ui-text-dimmed)',
}"
/>
</UDropdown>
</template>
</UDashboardNavbar>

<UDashboardSidebar>
<UDashboardSidebarLinks :links="[
{ label: 'Home', icon: 'i-lucide-home', to: '/admin' },
{ label: 'Licenses', icon: 'i-lucide-key', to: '/admin/licenses' },
{ label: 'Settings', icon: 'i-lucide-settings', to: '/admin/settings' },
]" />
</UDashboardSidebar>
</UDashboardPanel>

<slot />

</UDashboardLayout>
</template>
11 Replies
kapa.ai
kapa.ai2mo ago
Hi @RainyDev. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- I understand your issue with content not being scrollable within the <DashboardLayout> component. This is happening because of how the layout structure works in Nuxt UI Pro. The <DashboardLayout> component applies a fixed positioning to create a consistent layout between all panels:
{
wrapper: 'fixed inset-0 flex overflow-hidden'
}
{
wrapper: 'fixed inset-0 flex overflow-hidden'
}
As mentioned in the DashboardLayout documentation, this component is meant to be the root component of your layout and ensures consistent placement between all panels. To make your content scrollable, you need to wrap the content in your <slot /> with a <UDashboardPage> and a <UDashboardPanel> with <UDashboardPanelContent> inside it. This structure ensures proper scrolling behavior:
<template>
<UDashboardLayout>
<!-- Your sidebar panel -->
<UDashboardPanel :width="250" :resizable="{ min: 200, max: 300 }" collapsible>
<!-- Sidebar content -->
</UDashboardPanel>

<!-- Content panel -->
<UDashboardPage>
<UDashboardPanel grow>
<UDashboardNavbar title="Your Title" />
<UDashboardPanelContent>
<!-- Your scrollable content (table, etc.) goes here -->
<slot />
</UDashboardPanelContent>
</UDashboardPanel>
</UDashboardPage>
</UDashboardLayout>
</template>
<template>
<UDashboardLayout>
<!-- Your sidebar panel -->
<UDashboardPanel :width="250" :resizable="{ min: 200, max: 300 }" collapsible>
<!-- Sidebar content -->
</UDashboardPanel>

<!-- Content panel -->
<UDashboardPage>
<UDashboardPanel grow>
<UDashboardNavbar title="Your Title" />
<UDashboardPanelContent>
<!-- Your scrollable content (table, etc.) goes here -->
<slot />
</UDashboardPanelContent>
</UDashboardPanel>
</UDashboardPage>
</UDashboardLayout>
</template>
The <UDashboardPanelContent> component is specifically designed to provide a scrollable container with padding for your content as mentioned in the DashboardPanelContent documentation. You can also use the grow prop on the content panel to make it take the remaining space, which is useful for the panel on the right side of the layout as described in the DashboardPanel documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@994277952390971412> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
RainyDev
RainyDevOP2mo ago
Lifesaver! Thanks ❤️ How can I make the sidebar collapsible and mobile friendly? @kapa.ai
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Based on your previous question about the <DashboardLayout> and your current question about making the sidebar collapsible and mobile-friendly, I can provide you with the solution using Nuxt UI Pro components. You're already on the right track with your code! The collapsible prop that you're using on your <UDashboardPanel> is exactly what makes the sidebar responsive and mobile-friendly. Let me explain how it works: Making the Sidebar Collapsible and Mobile-Friendly The collapsible prop on the <UDashboardPanel> component automatically transforms the panel into a Slideover on mobile devices:
<UDashboardPanel :width="250" :resizable="{ min: 200, max: 300 }" collapsible>
<!-- Sidebar content -->
</UDashboardPanel>
<UDashboardPanel :width="250" :resizable="{ min: 200, max: 300 }" collapsible>
<!-- Sidebar content -->
</UDashboardPanel>
When you use the collapsible prop: 1. On desktop, the sidebar appears as a normal panel 2. On mobile (below the breakpoint, which defaults to "lg"), the panel transforms into a slideover 3. A toggle button is automatically added to the <UDashboardNavbar> component inside the panel As mentioned in the DashboardPanel documentation, the component uses the useUIState composable to store a isDashboardSidebarSlideoverOpen ref that controls the state of the slideover on mobile. Controlling the Slideover State If you need more control over the slideover state, you can use v-model with the DashboardPanel:
<script setup>
const isOpen = ref(false)
</script>

<template>
<UDashboardPanel v-model="isOpen" collapsible>
<!-- Sidebar content -->
</UDashboardPanel>
</template>
<script setup>
const isOpen = ref(false)
</script>

<template>
<UDashboardPanel v-model="isOpen" collapsible>
<!-- Sidebar content -->
</UDashboardPanel>
</template>
Customizing the Toggle Button You can also customize the toggle button that appears in the navbar by using the #toggle slot in the <UDashboardNavbar> component:
<UDashboardNavbar>
<template #toggle>
<UDashboardNavbarToggle icon="i-heroicons-x-mark" />
</template>
<!-- Other navbar content -->
</UDashboardNavbar>
<UDashboardNavbar>
<template #toggle>
<UDashboardNavbarToggle icon="i-heroicons-x-mark" />
</template>
<!-- Other navbar content -->
</UDashboardNavbar>
The toggle icon defaults to i-heroicons-bars-3-20-solid but can be changed as shown above, as mentioned in the DashboardNavbarToggle documentation. Changing the Side of the Panel By default, the collapsible panel appears from the left side. If you need it to appear from the right, you can use the side prop:
<UDashboardPanel collapsible side="right">
<!-- Sidebar content -->
</UDashboardPanel>
<UDashboardPanel collapsible side="right">
<!-- Sidebar content -->
</UDashboardPanel>
Your current implementation already has the necessary structure to make the sidebar collapsible and mobile-friendly. The collapsible prop you're using takes care of the responsive behavior automatically. I hope this helps clarify how to make your sidebar collapsible and mobile-friendly with Nuxt UI Pro! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@994277952390971412> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
RainyDev
RainyDevOP2mo ago
This is my code now but it doesn't get displayed. Neither on mobile nor Desktop @kapa.ai
<template>
<UDashboardLayout>
<UDashboardPanel v-model="isOpen" :width="250" collapsible>
<UDashboardNavbar>
<template #toggle>
<UDashboardNavbarToggle icon="i-heroicons-x-mark" />
</template>
<template #right>
<UAvatar :src="user.avatar.src" :alt="user.avatar.alt" size="md" class="mr-2" />
<UDropdown
:items="items"
:content="{ align: 'center', collisionPadding: 12 }"
:ui="{ content: 'w-48' }"
>
<UButton
v-bind="{
...user.avatar,
label: user.name,
trailingIcon: 'i-lucide-chevrons-up-down',
}"
variant="ghost"
block
class="data-[state=open]:bg-(--ui-bg-elevated)"
:ui="{
trailingIcon: 'text-(--ui-text-dimmed)',
}"
/>
</UDropdown>
</template>
</UDashboardNavbar>

<UDashboardSidebar>
<UDashboardSidebarLinks :links="[
{ label: 'Home', icon: 'i-lucide-home', to: '/admin' },
{ label: 'Licenses', icon: 'i-lucide-key', to: '/admin/licenses' },
{ label: 'Settings', icon: 'i-lucide-settings', to: '/admin/settings' },
]" />
</UDashboardSidebar>
</UDashboardPanel>

<UDashboardPanelContent>
<slot />

</UDashboardPanelContent>

</UDashboardLayout>
</template>
<template>
<UDashboardLayout>
<UDashboardPanel v-model="isOpen" :width="250" collapsible>
<UDashboardNavbar>
<template #toggle>
<UDashboardNavbarToggle icon="i-heroicons-x-mark" />
</template>
<template #right>
<UAvatar :src="user.avatar.src" :alt="user.avatar.alt" size="md" class="mr-2" />
<UDropdown
:items="items"
:content="{ align: 'center', collisionPadding: 12 }"
:ui="{ content: 'w-48' }"
>
<UButton
v-bind="{
...user.avatar,
label: user.name,
trailingIcon: 'i-lucide-chevrons-up-down',
}"
variant="ghost"
block
class="data-[state=open]:bg-(--ui-bg-elevated)"
:ui="{
trailingIcon: 'text-(--ui-text-dimmed)',
}"
/>
</UDropdown>
</template>
</UDashboardNavbar>

<UDashboardSidebar>
<UDashboardSidebarLinks :links="[
{ label: 'Home', icon: 'i-lucide-home', to: '/admin' },
{ label: 'Licenses', icon: 'i-lucide-key', to: '/admin/licenses' },
{ label: 'Settings', icon: 'i-lucide-settings', to: '/admin/settings' },
]" />
</UDashboardSidebar>
</UDashboardPanel>

<UDashboardPanelContent>
<slot />

</UDashboardPanelContent>

</UDashboardLayout>
</template>
`
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I see the issue with your current code. You're missing a crucial component in the structure that's causing your content not to display properly. Let me explain the problem and provide a solution. The main issue is that you're placing the <UDashboardPanelContent> directly inside the <UDashboardLayout> without wrapping it in a <UDashboardPanel>. According to the Nuxt UI Pro documentation, the proper structure requires content panels to be wrapped in a <UDashboardPanel>. Here's how you should structure your code:
<template>
<UDashboardLayout>
<!-- Sidebar Panel -->
<UDashboardPanel v-model="isOpen" :width="250" collapsible>
<UDashboardNavbar>
<template #toggle>
<UDashboardNavbarToggle icon="i-heroicons-x-mark" />
</template>
<template #right>
<UAvatar :src="user.avatar.src" :alt="user.avatar.alt" size="md" class="mr-2" />
<UDropdown
:items="items"
:content="{ align: 'center', collisionPadding: 12 }"
:ui="{ content: 'w-48' }"
>
<UButton
v-bind="{
...user.avatar,
label: user.name,
trailingIcon: 'i-lucide-chevrons-up-down',
}"
variant="ghost"
block
class="data-[state=open]:bg-(--ui-bg-elevated)"
:ui="{
trailingIcon: 'text-(--ui-text-dimmed)',
}"
/>
</UDropdown>
</template>
</UDashboardNavbar>
<UDashboardSidebar>
<UDashboardSidebarLinks :links="[
{ label: 'Home', icon: 'i-lucide-home', to: '/admin' },
{ label: 'Licenses', icon: 'i-lucide-key', to: '/admin/licenses' },
{ label: 'Settings', icon: 'i-lucide-settings', to: '/admin/settings' },
]" />
</UDashboardSidebar>
</UDashboardPanel>

<!-- Content Panel -->
<UDashboardPanel grow>
<UDashboardNavbar title="Your Title" />
<UDashboardPanelContent>
<slot />
</UDashboardPanelContent>
</UDashboardPanel>
</UDashboardLayout>
</template>
<template>
<UDashboardLayout>
<!-- Sidebar Panel -->
<UDashboardPanel v-model="isOpen" :width="250" collapsible>
<UDashboardNavbar>
<template #toggle>
<UDashboardNavbarToggle icon="i-heroicons-x-mark" />
</template>
<template #right>
<UAvatar :src="user.avatar.src" :alt="user.avatar.alt" size="md" class="mr-2" />
<UDropdown
:items="items"
:content="{ align: 'center', collisionPadding: 12 }"
:ui="{ content: 'w-48' }"
>
<UButton
v-bind="{
...user.avatar,
label: user.name,
trailingIcon: 'i-lucide-chevrons-up-down',
}"
variant="ghost"
block
class="data-[state=open]:bg-(--ui-bg-elevated)"
:ui="{
trailingIcon: 'text-(--ui-text-dimmed)',
}"
/>
</UDropdown>
</template>
</UDashboardNavbar>
<UDashboardSidebar>
<UDashboardSidebarLinks :links="[
{ label: 'Home', icon: 'i-lucide-home', to: '/admin' },
{ label: 'Licenses', icon: 'i-lucide-key', to: '/admin/licenses' },
{ label: 'Settings', icon: 'i-lucide-settings', to: '/admin/settings' },
]" />
</UDashboardSidebar>
</UDashboardPanel>

<!-- Content Panel -->
<UDashboardPanel grow>
<UDashboardNavbar title="Your Title" />
<UDashboardPanelContent>
<slot />
</UDashboardPanelContent>
</UDashboardPanel>
</UDashboardLayout>
</template>
The key changes I made: 1. Added a second <UDashboardPanel> with the grow prop to make it take the remaining space as mentioned in the DashboardPanel documentation. 2. Added a <UDashboardNavbar> inside this content panel (you can customize or remove this if not needed). 3. Placed the <UDashboardPanelContent> inside this panel, which is the correct structure according to the documentation. The grow prop is particularly important as it makes the content panel take up the remaining space in the layout. Without this second panel properly configured, your content won't display correctly. Also, make sure you have the isOpen ref defined in your script section:
<script setup>
const isOpen = ref(false)
</script>
<script setup>
const isOpen = ref(false)
</script>
This structure follows the pattern shown in the DashboardPanel documentation for creating a responsive dashboard layout with a collapsible sidebar. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@994277952390971412> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
RainyDev
RainyDevOP2mo ago
Well, it does get showed now but still wont open up on mobile... @kapa.ai
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand that your sidebar is now displaying correctly but still won't open on mobile. Let's troubleshoot this specific issue with the collapsible sidebar functionality. Based on the Nuxt UI Pro documentation, there are a few things to check to make sure your mobile sidebar opens correctly: 1. Check your v-model binding: When using the v-model with collapsible, you need to make sure the reactive state is properly initialized and updated. 2. Verify the breakpoint: By default, the mobile behavior activates below the "lg" breakpoint. You can customize this with the breakpoint prop if needed. Here's how to fix the mobile sidebar issue:
<script setup>
// Make sure this is properly defined
const isOpen = ref(false)

// You might need to watch for route changes to close the sidebar
// when navigating on mobile
watch(useRoute(), () => {
isOpen.value = false
})
</script>

<template>
<UDashboardLayout>
<!-- Sidebar Panel -->
<UDashboardPanel
v-model="isOpen"
:width="250"
collapsible
breakpoint="lg" <!-- You can try different breakpoints like "md" -->
>
<!-- Your sidebar content -->
</UDashboardPanel>

<!-- Content Panel -->
<UDashboardPanel grow>
<!-- Your content -->
</UDashboardPanel>
</UDashboardLayout>
</template>
<script setup>
// Make sure this is properly defined
const isOpen = ref(false)

// You might need to watch for route changes to close the sidebar
// when navigating on mobile
watch(useRoute(), () => {
isOpen.value = false
})
</script>

<template>
<UDashboardLayout>
<!-- Sidebar Panel -->
<UDashboardPanel
v-model="isOpen"
:width="250"
collapsible
breakpoint="lg" <!-- You can try different breakpoints like "md" -->
>
<!-- Your sidebar content -->
</UDashboardPanel>

<!-- Content Panel -->
<UDashboardPanel grow>
<!-- Your content -->
</UDashboardPanel>
</UDashboardLayout>
</template>
If you're still having issues, you can try these additional solutions: 1. Use the built-in state management instead of your own v-model:
<UDashboardPanel :width="250" collapsible>
<!-- Remove the v-model and let the component handle the state -->
</UDashboardPanel>

<UDashboardPanel :width="250" collapsible>
<!-- Remove the v-model and let the component handle the state -->
</UDashboardPanel>

2. Check your toggle button: Make sure the toggle button in the navbar is visible on mobile screens. The #toggle slot in your UDashboardNavbar should be rendering correctly. 3. Test with browser dev tools: Use your browser's device emulation to verify the mobile breakpoint is being triggered correctly. If you're still experiencing issues after trying these solutions, it might be helpful to check the Nuxt UI Pro GitHub repository for any known issues or to create a minimal reproduction of your problem to share with the community. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@994277952390971412> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?