DashboardSidebar

GitHub
A resizable and collapsible sidebar to display in a dashboard.

Usage

The DashboardSidebar component is used to display a sidebar. Its state (size, collapsed, etc.) will be saved based on the storage and storage-key props you provide to the DashboardGroup component.

Use it inside the default slot of the DashboardGroup component:

layouts/dashboard.vue
<template>
  <PDashboardGroup>
    <PDashboardSidebar />

    <slot />
  </PDashboardGroup>
</template>
This component does not have a single root element when using the resizable prop, so wrap it in a container (e.g., <div class="flex flex-1">) if you use page transitions or require a single root for layout.

Use the left, default and right slots to customize the sidebar and the body or content slots to customize the sidebar menu.

<script setup lang="ts">
import type { PNavigationMenuItem } from 'pohon-ui';

const items: Array<Array<PNavigationMenuItem>> = [[{
  label: 'Home',
  icon: 'i-lucide:house',
  active: true,
}, {
  label: 'Inbox',
  icon: 'i-lucide:inbox',
  badge: '4',
}, {
  label: 'Contacts',
  icon: 'i-lucide:users',
}, {
  label: 'Settings',
  icon: 'i-lucide:settings',
  defaultOpen: true,
  children: [{
    label: 'General',
  }, {
    label: 'Members',
  }, {
    label: 'Notifications',
  }],
}], [{
  label: 'Feedback',
  icon: 'i-lucide:message-circle',
  to: 'https://github.com/nuxt-ui-templates/dashboard',
  target: '_blank',
}, {
  label: 'Help & Support',
  icon: 'i-lucide:info',
  to: 'https://github.com/nuxt/ui',
  target: '_blank',
}]];
</script>

<template>
  <PDashboardSidebar
    collapsible
    resizable
    :pohon="{ footer: 'border-t border-border' }"
  >
    <template #header="{ collapsed }">
      <BaseLogo
        v-if="!collapsed"
        class="shrink-0 h-5 w-auto"
      />
      <PIcon
        v-else
        name="i-simple-icons:nuxtdotjs"
        class="text-primary mx-auto size-5"
      />
    </template>

    <template #default="{ collapsed }">
      <PButton
        :label="collapsed ? undefined : 'Search...'"
        icon="i-lucide:search"
        color="neutral"
        variant="outline"
        block
        :square="collapsed"
      >
        <template
          v-if="!collapsed"
          #trailing
        >
          <div class="ms-auto flex gap-0.5 items-center">
            <PKbd
              value="meta"
              variant="subtle"
            />
            <PKbd
              value="K"
              variant="subtle"
            />
          </div>
        </template>
      </PButton>

      <PNavigationMenu
        :collapsed="collapsed"
        :items="items[0]"
        orientation="vertical"
      />

      <PNavigationMenu
        :collapsed="collapsed"
        :items="items[1]"
        orientation="vertical"
        class="mt-auto"
      />
    </template>

    <template #footer="{ collapsed }">
      <PButton
        :avatar="{
          src: 'https://github.com/praburangki.png',
        }"
        :label="collapsed ? undefined : 'Benjamin'"
        color="neutral"
        variant="ghost"
        class="w-full"
        :block="collapsed"
      />
    </template>
  </PDashboardSidebar>
</template>
Drag the sidebar near the left edge of the screen to collapse it.

Resizable

Use the resizable prop to make the sidebar resizable.

<template>
  <PDashboardSidebar resizable>
    <CorePlaceholder class="h-96" />
  </PDashboardSidebar>
</template>

Collapsible

Use the collapsible prop to make the sidebar collapsible when dragging near the edge of the screen.

The DashboardSidebarCollapse component will have no effect if the sidebar is not collapsible.
<template>
  <PDashboardSidebar resizable collapsible>
    <CorePlaceholder class="h-96" />
  </PDashboardSidebar>
</template>
You can access the collapsed state in the slot props to customize the content of the sidebar when it is collapsed.

Size

Use the min-size, max-size, default-size and collapsed-size props to customize the size of the sidebar.

<template>
  <PDashboardSidebar
    resizable
    collapsible
    :min-size="22"
    :default-size="35"
    :max-size="40"
    :collapsed-size="0"
  >
    <CorePlaceholder class="h-96" />
  </PDashboardSidebar>
</template>
Sizes are calculated as percentages by default. You can change this using the unit prop on the DashboardGroup component.
The collapsed-size prop is set to 0 by default but the sidebar has a min-w-16 to make sure it is visible.

Side

Use the side prop to change the side of the sidebar. Defaults to left.

<template>
  <PDashboardSidebar side="right" resizable collapsible>
    <CorePlaceholder class="h-96" />
  </PDashboardSidebar>
</template>

Mode

Use the mode prop to change the mode of the sidebar menu. Defaults to slideover.

Use the body slot to fill the menu body (under the header) or the content slot to fill the entire menu.

You can use the menu prop to customize the menu of the sidebar, it will adapt depending on the mode you choose.
<script setup lang="ts">
import type { PNavigationMenuItem } from 'pohon-ui';

defineProps<{
  mode: 'drawer' | 'slideover' | 'dialog';
}>();

const items: Array<PNavigationMenuItem> = [{
  label: 'Home',
  icon: 'i-lucide:house',
  active: true,
}, {
  label: 'Inbox',
  icon: 'i-lucide:inbox',
}, {
  label: 'Contacts',
  icon: 'i-lucide:users',
}];
</script>

<template>
  <PDashboardGroup>
    <PDashboardSidebar :mode="mode">
      <template #header="{ collapsed }">
        <BaseLogo
          v-if="!collapsed"
          class="h-5 w-auto"
        />
        <PIcon
          v-else
          name="i-simple-icons:nuxtdotjs"
          class="text-primary mx-auto size-5"
        />
      </template>

      <PNavigationMenu
        :items="items"
        orientation="vertical"
      />
    </PDashboardSidebar>

    <PDashboardPanel>
      <template #header>
        <PDashboardNavbar title="Dashboard" />
      </template>
    </PDashboardPanel>
  </PDashboardGroup>
</template>
These examples contain the DashboardGroup, DashboardPanel and DashboardNavbar components as they are required to demonstrate the sidebar on mobile.

Toggle

Use the toggle prop to customize the DashboardSidebarToggle component displayed on mobile.

You can pass any property from the Button component to customize it.

<script setup lang="ts">
import type { PNavigationMenuItem } from 'pohon-ui';

const items: Array<PNavigationMenuItem> = [{
  label: 'Home',
  icon: 'i-lucide:house',
  active: true,
}, {
  label: 'Inbox',
  icon: 'i-lucide:inbox',
}, {
  label: 'Contacts',
  icon: 'i-lucide:users',
}];
</script>

<template>
  <PDashboardGroup>
    <PDashboardSidebar
      open
      :toggle="{
        color: 'primary',
        variant: 'subtle',
        class: 'rounded-full',
      }"
    >
      <template #header>
        <BaseLogo class="h-5 w-auto" />
      </template>

      <PNavigationMenu
        :items="items"
        orientation="vertical"
      />
    </PDashboardSidebar>

    <PDashboardPanel>
      <template #header>
        <PDashboardNavbar title="Dashboard" />
      </template>
    </PDashboardPanel>
  </PDashboardGroup>
</template>

Toggle Side

Use the toggle-side prop to change the side of the toggle button. Defaults to left.

<script setup lang="ts">
import type { PNavigationMenuItem } from 'pohon-ui';

const items: Array<PNavigationMenuItem> = [{
  label: 'Home',
  icon: 'i-lucide:house',
  active: true,
}, {
  label: 'Inbox',
  icon: 'i-lucide:inbox',
}, {
  label: 'Contacts',
  icon: 'i-lucide:users',
}];
</script>

<template>
  <PDashboardGroup>
    <PDashboardSidebar
      open
      toggle-side="right"
    >
      <template #header>
        <BaseLogo class="h-5 w-auto" />
      </template>

      <PNavigationMenu
        :items="items"
        orientation="vertical"
      />
    </PDashboardSidebar>

    <PDashboardPanel>
      <template #header>
        <PDashboardNavbar title="Dashboard" />
      </template>
    </PDashboardPanel>
  </PDashboardGroup>
</template>

Examples

Control open state

You can control the open state by using the open prop or the v-model:open directive.

<script setup lang="ts">
import type { PNavigationMenuItem } from 'pohon-ui';
import { defineShortcuts } from '#imports';
import { ref } from 'vue';

const items: Array<PNavigationMenuItem> = [{
  label: 'Home',
  icon: 'i-lucide:house',
  active: true,
}, {
  label: 'Inbox',
  icon: 'i-lucide:inbox',
}, {
  label: 'Contacts',
  icon: 'i-lucide:users',
}];

const open = ref(true);

defineShortcuts({
  o: () => {
    open.value = !open.value;
  },
});
</script>

<template>
  <PDashboardSidebar v-model:open="open">
    <template #header="{ collapsed }">
      <BaseLogo
        v-if="!collapsed"
        class="h-5 w-auto"
      />
      <PIcon
        v-else
        name="i-simple-icons:nuxtdotjs"
        class="text-primary mx-auto size-5"
      />
    </template>

    <PNavigationMenu
      :items="items"
      orientation="vertical"
    />
  </PDashboardSidebar>
</template>
In this example, leveraging defineShortcuts, you can toggle the open state of the DashboardSidebar by pressing O.

Control collapsed state

You can control the collapsed state by using the collapsed prop or the v-model:collapsed directive.

<script setup lang="ts">
import type { PNavigationMenuItem } from 'pohon-ui';
import { defineShortcuts } from '#imports';
import { ref } from 'vue';

const items: Array<PNavigationMenuItem> = [{
  label: 'Home',
  icon: 'i-lucide:house',
  active: true,
}, {
  label: 'Inbox',
  icon: 'i-lucide:inbox',
}, {
  label: 'Contacts',
  icon: 'i-lucide:users',
}];

const collapsed = ref(false);

defineShortcuts({
  c: () => {
    collapsed.value = !collapsed.value;
  },
});
</script>

<template>
  <PDashboardSidebar
    v-model:collapsed="collapsed"
    collapsible
  >
    <template #header>
      <BaseLogo
        v-if="!collapsed"
        class="h-5 w-auto"
      />
      <PIcon
        v-else
        name="i-simple-icons:nuxtdotjs"
        class="text-primary mx-auto size-5"
      />
    </template>

    <PNavigationMenu
      :collapsed="collapsed"
      :items="items"
      orientation="vertical"
    />
  </PDashboardSidebar>
</template>
In this example, leveraging defineShortcuts, you can toggle the collapsed state of the DashboardSidebar by pressing C.

API

Props

Prop Default Type

Slots

Slot Type

Theme

We use unocss-variants to customize the theme. Read more about it in the theming guide.

Below is the theme configuration skeleton for the PDashboardSidebar. Since the component is provided unstyled by default, you will need to fill in these values to apply your own custom look and feel. If you prefer to use our pre-built, opinionated styling, you can instead use our UnoCSS preset, this docs is using it as well.

app.config.ts
export default defineAppConfig({
  pohon: {
    dashboardSidebar: {
      slots: {
        root: '',
        header: '',
        body: '',
        footer: '',
        toggle: '',
        handle: '',
        content: '',
        overlay: ''
      },
      variants: {
        menu: {
          true: {
            header: '',
            body: '',
            footer: ''
          }
        },
        side: {
          left: {
            root: ''
          },
          right: {
            root: ''
          }
        },
        toggleSide: {
          left: {
            toggle: ''
          },
          right: {
            toggle: ''
          }
        }
      }
    }
  }
};
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import pohon from 'pohon-ui/vite'

export default defineAppConfig({
  pohon: {
    dashboardSidebar: {
      slots: {
        root: '',
        header: '',
        body: '',
        footer: '',
        toggle: '',
        handle: '',
        content: '',
        overlay: ''
      },
      variants: {
        menu: {
          true: {
            header: '',
            body: '',
            footer: ''
          }
        },
        side: {
          left: {
            root: ''
          },
          right: {
            root: ''
          }
        },
        toggleSide: {
          left: {
            toggle: ''
          },
          right: {
            toggle: ''
          }
        }
      }
    }
  }
};

Changelog

No recent changes