DashboardPanel
A responsive and resizable panel to build multi-column layouts.
Usage
The DashboardPanel
component is the building block to create a multi-column layout.
<script setup lang="ts">
const links = [{
label: 'Home',
icon: 'i-heroicons-home'
}, {
label: 'Inbox',
icon: 'i-heroicons-inbox',
badge: '4'
}, {
label: 'Users',
icon: 'i-heroicons-user-group'
}, {
label: 'Settings',
icon: 'i-heroicons-cog-8-tooth',
children: [{
label: 'General'
}, {
label: 'Members'
}, {
label: 'Notifications'
}]
}]
</script>
<template>
<UDashboardPanel :width="300" :resizable="{ min: 200, max: 400 }">
<UDashboardNavbar>
<template #left>
<Logo class="w-auto h-5" />
</template>
</UDashboardNavbar>
<UDashboardSidebar>
<UDashboardSidebarLinks :links="links" />
</UDashboardSidebar>
</UDashboardPanel>
</template>
Width
By default, the DashboardPanel
will take its content's width. You can use the width
prop to set a fixed one.
<template>
<UDashboardPanel :width="250" />
</template>
Grow
You can use the grow
prop to make the DashboardPanel
take the remaining space. It can be useful for the last panel on the right side of the layout.
<template>
<UDashboardPanel grow />
</template>
grow
prop, the right border will be removed to make the layout look seamless.Resizable
You can use the resizable
prop to make the DashboardPanel
resizable and set the min
and max
values to limit the resizing.
<template>
<UDashboardPanel :width="300" :resizable="{ min: 200, max: 400 }" />
</template>
The width will be stored in a cookie to keep the layout consistent on refresh. We use the useId
composable to generate a unique id. When you have multiple resizable panels, it can be useful to set a custom one through the id
prop.
<template>
<UDashboardPanel id="inbox" :width="400" :resizable="{ min: 300, max: 500 }" />
</template>
When the resizable
prop is used, a bar will be displayed on hover at the right of the panel. You can use the #handle
slot to customize it as described in DashboardPanelHandle.
Collapsible
A two or three column layout will not be very usable on mobile. You can use the collapsible
prop to transform the DashboardPanel
into a Slideover on mobile.
<template>
<UDashboardPanel collapsible />
</template>
In the useUIState
composable, we store a isDashboardSidebarSlidoverOpen
ref to control the state of the slideover on mobile. The DashboardPanel
will inject this to the DashboardNavbar inside to display a toggle button.
If you want to control the state of the slideover yourself or if you have multiple panels, you can pass a v-model
to the DashboardPanel
.
<script setup lang="ts">
const selected = ref(null)
const isOpen = computed({
get () {
return !!selected.value
},
set (value: boolean) {
if (!value) {
selected.value = null
}
}
})
</script>
<template>
<UDashboardPanel v-model="isOpen" collapsible />
</template>
Side
When using the collapsible
prop, you can use the side
prop to set the side of the panel. The default value is left
.
<template>
<UDashboardPanel v-model="isOpen" collapsible side="right" />
</template>
The DashboardPanel
can be placed inside a DashboardLayout or a DashboardPage.
You can put a DashboardNavbar at the top followed by a DashboardSidebar, a DashboardToolbar or a DashboardPanelContent to display scrollable content for example.
<template>
<UDashboardLayout>
<UDashboardPanel :width="250" :resizable="{ min: 200, max: 300 }" collapsible>
<UDashboardNavbar />
<UDashboardSidebar />
</UDashboardPanel>
<slot />
</UDashboardLayout>
</template>
<script setup lang="ts">
const isOpen = ref(false)
</script>
<template>
<UDashboardPage>
<UDashboardPanel id="inbox" :width="400" :resizable="{ min: 300, max: 500 }">
<UDashboardNavbar title="Inbox" />
<UDashboardPanelContent />
</UDashboardPanel>
<UDashboardPanel v-model="isOpen" collapsible grow side="right">
<UDashboardNavbar />
<UDashboardToolbar />
<UDashboardPanelContent />
</UDashboardPanel>
</UDashboardPage>
</template>
Props
{}
undefined
"left"
false
undefined
undefined
false
false
Config
{
wrapper: 'flex-col items-stretch relative w-full',
border: 'border-b lg:border-b-0 lg:border-r border-gray-200 dark:border-gray-800 lg:w-[--width] flex-shrink-0',
grow: 'flex-1'
}