DashboardSidebar New

A resizable and collapsible sidebar component for dashboards.

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>
  <B24DashboardGroup>
    <B24DashboardSidebar />

    <slot />
  </B24DashboardGroup>
</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 header, default and footer slots to customize the sidebar and the body or content slots to customize the sidebar menu.

<script setup lang="ts">
import type { NavigationMenuItem } from '@bitrix24/b24ui-nuxt'
import B24Icon from '@bitrix24/b24icons-vue/main/B24Icon'
import HomeIcon from '@bitrix24/b24icons-vue/outline/HomeIcon'
import MailIcon from '@bitrix24/b24icons-vue/outline/MailIcon'
import ContactIcon from '@bitrix24/b24icons-vue/outline/ContactIcon'
import SettingsIcon from '@bitrix24/b24icons-vue/outline/SettingsIcon'
import FeedbackIcon from '@bitrix24/b24icons-vue/outline/FeedbackIcon'
import InfoCircleIcon from '@bitrix24/b24icons-vue/outline/InfoCircleIcon'

const items: NavigationMenuItem[][] = [
  [
    {
      label: 'Home',
      icon: HomeIcon,
      active: true
    },
    {
      label: 'Inbox',
      icon: MailIcon,
      badge: '4'
    },
    {
      label: 'Contacts',
      icon: ContactIcon
    },
    {
      label: 'Settings',
      icon: SettingsIcon,
      defaultOpen: true,
      children: [
        {
          label: 'General'
        },
        {
          label: 'Members'
        },
        {
          label: 'Notifications'
        }
      ]
    }
  ],
  [
    {
      label: 'Feedback',
      icon: FeedbackIcon,
      to: 'https://github.com/bitrix24/b24ui/issues',
      target: '_blank'
    },
    {
      label: 'Help & Support',
      icon: InfoCircleIcon,
      to: 'https://github.com/bitrix24/b24ui',
      target: '_blank'
    }
  ]
]
</script>

<template>
  <B24DashboardSidebar
    collapsible
    resizable
    :b24ui="{ footer: 'border-t border-(--ui-color-divider-default)' }"
  >
    <template #header="{ collapsed }">
      <Logo v-if="!collapsed" class="h-5 w-auto shrink-0 text-(--b24ui-typography-label-color)" />
      <B24Icon v-else class="size-10 text-[#2fc6f6] mx-auto" />
    </template>

    <template #default="{ collapsed }">
      <B24DashboardSearchButton
        :collapsed="collapsed"
        class="ms-4"
      />

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

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

    <template #footer="{ collapsed }">
      <B24Button
        :avatar="{ src: 'https://github.com/bitrix24.png' }"
        :label="collapsed ? undefined : 'Bitrix24'"
        class="w-full"
        :block="collapsed"
      />
    </template>
  </B24DashboardSidebar>
</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>
  <B24DashboardSidebar resizable>
    <Placeholder class="ms-2 h-96" />
  </B24DashboardSidebar>
</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>
  <B24DashboardSidebar resizable collapsible>
    <Placeholder class="ms-2 h-96" />
  </B24DashboardSidebar>
</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 (px) to customize the size of the sidebar.

<template>
  <B24DashboardSidebar
    resizable
    collapsible
    :min-size="200"
    :default-size="240"
    :max-size="250"
    :collapsed-size="66"
  >
    <Placeholder class="ms-2 h-96" />
  </B24DashboardSidebar>
</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>
  <B24DashboardSidebar side="right" resizable collapsible>
    <Placeholder class="ms-2 h-96" />
  </B24DashboardSidebar>
</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 { NavigationMenuItem } from '@bitrix24/b24ui-nuxt'
import B24Icon from '@bitrix24/b24icons-vue/main/B24Icon'
import HomeIcon from '@bitrix24/b24icons-vue/outline/HomeIcon'
import MailIcon from '@bitrix24/b24icons-vue/outline/MailIcon'
import ContactIcon from '@bitrix24/b24icons-vue/outline/ContactIcon'

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

const items: NavigationMenuItem[] = [
  {
    label: 'Home',
    icon: HomeIcon,
    active: true
  },
  {
    label: 'Inbox',
    icon: MailIcon
  },
  {
    label: 'Contacts',
    icon: ContactIcon
  }
]
</script>

<template>
  <B24DashboardGroup>
    <B24DashboardSidebar
      :mode="mode"
      :menu="{
        side: 'left',
        inset: true
      }"
      :b24ui="{ overlay: 'bg-(--ui-color-bg-content-primary) base-mode' }"
    >
      <template #header="{ collapsed }">
        <Logo v-if="!collapsed" class="h-5 w-auto text-(--b24ui-typography-label-color)" />
        <B24Icon v-else class="size-10 text-[#2fc6f6] mx-auto" />
      </template>

      <B24NavigationMenu
        :items="items"
        orientation="vertical"
      />
    </B24DashboardSidebar>

    <B24DashboardPanel>
      <template #header>
        <B24DashboardNavbar title="Dashboard" />
      </template>
    </B24DashboardPanel>
  </B24DashboardGroup>
</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 { NavigationMenuItem } from '@bitrix24/b24ui-nuxt'
import HomeIcon from '@bitrix24/b24icons-vue/outline/HomeIcon'
import MailIcon from '@bitrix24/b24icons-vue/outline/MailIcon'
import ContactIcon from '@bitrix24/b24icons-vue/outline/ContactIcon'

const items: NavigationMenuItem[] = [
  {
    label: 'Home',
    icon: HomeIcon,
    active: true
  },
  {
    label: 'Inbox',
    icon: MailIcon
  },
  {
    label: 'Contacts',
    icon: ContactIcon
  }
]
</script>

<template>
  <B24DashboardGroup>
    <B24DashboardSidebar
      open
      :toggle="{
        color: 'air-primary',
        class: 'rounded-full'
      }"
      :menu="{
        side: 'left',
        inset: true
      }"
      :b24ui="{ overlay: 'bg-(--ui-color-bg-content-primary) base-mode' }"
    >
      <template #header>
        <Logo class="h-5 w-auto text-(--b24ui-typography-label-color)" />
      </template>

      <B24NavigationMenu
        :items="items"
        orientation="vertical"
      />
    </B24DashboardSidebar>

    <B24DashboardPanel>
      <template #header>
        <B24DashboardNavbar title="Dashboard" />
      </template>
    </B24DashboardPanel>
  </B24DashboardGroup>
</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 { NavigationMenuItem } from '@bitrix24/b24ui-nuxt'
import HomeIcon from '@bitrix24/b24icons-vue/outline/HomeIcon'
import MailIcon from '@bitrix24/b24icons-vue/outline/MailIcon'
import ContactIcon from '@bitrix24/b24icons-vue/outline/ContactIcon'

const items: NavigationMenuItem[] = [
  {
    label: 'Home',
    icon: HomeIcon,
    active: true
  },
  {
    label: 'Inbox',
    icon: MailIcon
  },
  {
    label: 'Contacts',
    icon: ContactIcon
  }
]
</script>

<template>
  <B24DashboardGroup>
    <B24DashboardSidebar
      open
      toggle-side="right"
      :menu="{
        side: 'left',
        inset: true
      }"
      :b24ui="{ overlay: 'bg-(--ui-color-bg-content-primary) base-mode' }"
    >
      <template #header>
        <Logo class="h-5 w-auto text-(--b24ui-typography-label-color)" />
      </template>

      <B24NavigationMenu
        :items="items"
        orientation="vertical"
      />
    </B24DashboardSidebar>

    <B24DashboardPanel>
      <template #header>
        <B24DashboardNavbar title="Dashboard" />
      </template>
    </B24DashboardPanel>
  </B24DashboardGroup>
</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 { NavigationMenuItem } from '@bitrix24/b24ui-nuxt'
import B24Icon from '@bitrix24/b24icons-vue/main/B24Icon'
import HomeIcon from '@bitrix24/b24icons-vue/outline/HomeIcon'
import MailIcon from '@bitrix24/b24icons-vue/outline/MailIcon'
import ContactIcon from '@bitrix24/b24icons-vue/outline/ContactIcon'

const items: NavigationMenuItem[] = [
  {
    label: 'Home',
    icon: HomeIcon,
    active: true
  },
  {
    label: 'Inbox',
    icon: MailIcon
  },
  {
    label: 'Contacts',
    icon: ContactIcon
  }
]

const open = ref(true)

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

<template>
  <B24DashboardSidebar
    v-model:open="open"
    :menu="{
      side: 'left',
      inset: true
    }"
    :b24ui="{ overlay: 'bg-(--ui-color-bg-content-primary) base-mode' }"
  >
    <template #header="{ collapsed }">
      <Logo v-if="!collapsed" class="h-5 w-auto text-(--b24ui-typography-label-color)" />
      <B24Icon v-else class="size-10 text-[#2fc6f6] mx-auto" />
    </template>

    <B24NavigationMenu
      :items="items"
      orientation="vertical"
    />
  </B24DashboardSidebar>
</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 { NavigationMenuItem } from '@bitrix24/b24ui-nuxt'
import B24Icon from '@bitrix24/b24icons-vue/main/B24Icon'
import HomeIcon from '@bitrix24/b24icons-vue/outline/HomeIcon'
import MailIcon from '@bitrix24/b24icons-vue/outline/MailIcon'
import ContactIcon from '@bitrix24/b24icons-vue/outline/ContactIcon'

const items: NavigationMenuItem[] = [
  {
    label: 'Home',
    icon: HomeIcon,
    active: true
  },
  {
    label: 'Inbox',
    icon: MailIcon
  },
  {
    label: 'Contacts',
    icon: ContactIcon
  }
]

const collapsed = ref(false)

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

<template>
  <B24DashboardSidebar v-model:collapsed="collapsed" collapsible>
    <template #header>
      <Logo v-if="!collapsed" class="h-5 w-auto text-(--b24ui-typography-label-color)" />
      <B24Icon v-else class="size-10 text-[#2fc6f6] mx-auto" />
    </template>

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

API

Props

Prop Default Type
mode'slideover' T

The mode of the sidebar menu.

menu DashboardSidebarMenu<T>

The props for the sidebar menu component.

toggletrueboolean | Omit<ButtonProps, LinkPropsKeys>

Customize the toggle button to open the sidebar. { color: 'air-tertiary' }

toggleSide'left' "left" | "right"

The side to render the toggle button on.

autoClosetrueboolean

Automatically close when route changes.

iduseId() string

The id of the panel.

side'left' "left" | "right"

The side to render the panel on.

minSize200 number

The minimum size of the panel.

maxSize250 number

The maximum size of the panel.

defaultSize240 number

The default size of the panel.

resizablefalseboolean

Whether to allow the user to resize the panel.

collapsiblefalseboolean

Whether to allow the user to collapse the panel.

collapsedSize66 number

The size of the panel when collapsed.

openfalseboolean
collapsedfalseboolean
b24ui { root?: ClassNameValue; header?: ClassNameValue; body?: ClassNameValue; footer?: ClassNameValue; toggle?: ClassNameValue; handle?: ClassNameValue; content?: ClassNameValue; overlay?: ClassNameValue; }

Slots

Slot Type
header{ collapsed: boolean; collapse: (value: boolean) => void; }
default{ collapsed: boolean; collapse: (value: boolean) => void; }
footer{ collapsed: boolean; collapse: (value: boolean) => void; }
toggle{ open: boolean; toggle: () => void; b24ui: object; }
content{ close?: (() => void) | undefined; }
resize-handle{ onMouseDown: (e: MouseEvent) => void; onTouchStart: (e: TouchEvent) => void; onDoubleClick: (e: MouseEvent) => void; b24ui: object; }

Theme

app.config.ts
export default defineAppConfig({
  b24ui: {
    dashboardSidebar: {
      slots: {
        root: 'relative hidden lg:flex flex-col min-h-svh min-w-16 w-(--width) shrink-0',
        header: 'h-(--b24ui-header-height) shrink-0 flex items-center gap-1.5 px-4',
        body: 'flex flex-col gap-4 flex-1 overflow-y-auto py-2 scrollbar-thin scrollbar-transparent',
        footer: 'shrink-0 flex items-center gap-1.5 px-4 py-2',
        toggle: '',
        handle: '',
        content: 'lg:hidden',
        overlay: 'lg:hidden'
      },
      variants: {
        menu: {
          true: {
            header: 'sm:px-6',
            body: 'sm:px-6',
            footer: 'sm:px-6'
          }
        },
        side: {
          left: {
            root: 'border-e border-(--ui-color-divider-default)'
          },
          right: {
            root: ''
          }
        },
        toggleSide: {
          left: {
            toggle: ''
          },
          right: {
            toggle: 'ms-auto'
          }
        }
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'

export default defineConfig({
  plugins: [
    vue(),
    bitrix24UIPluginVite({
      b24ui: {
        dashboardSidebar: {
          slots: {
            root: 'relative hidden lg:flex flex-col min-h-svh min-w-16 w-(--width) shrink-0',
            header: 'h-(--b24ui-header-height) shrink-0 flex items-center gap-1.5 px-4',
            body: 'flex flex-col gap-4 flex-1 overflow-y-auto py-2 scrollbar-thin scrollbar-transparent',
            footer: 'shrink-0 flex items-center gap-1.5 px-4 py-2',
            toggle: '',
            handle: '',
            content: 'lg:hidden',
            overlay: 'lg:hidden'
          },
          variants: {
            menu: {
              true: {
                header: 'sm:px-6',
                body: 'sm:px-6',
                footer: 'sm:px-6'
              }
            },
            side: {
              left: {
                root: 'border-e border-(--ui-color-divider-default)'
              },
              right: {
                root: ''
              }
            },
            toggleSide: {
              left: {
                toggle: ''
              },
              right: {
                toggle: 'ms-auto'
              }
            }
          }
        }
      }
    })
  ]
})
Releases
Published under MIT License.

Copyright © 2024-present Bitrix24