Skip to content

Sidebar ​

Вертикальная боковая панель навигации со сворачиваемыми подменю, поиском, перетаскиванием, изменением размера, группами, значками, свёрнутым режимом, мини-режимом и многим другим.

Для горизонтальной навигации см. Menu.

Basic ​

vue
<script setup>
import { ref } from 'vue'
import { VxSidebar } from 'veloxui'

const active = ref('inbox')

const items = [
  { key: 'inbox', label: 'Inbox', icon: 'mail' },
  { key: 'starred', label: 'Starred', icon: 'star' },
  { key: 'drafts', label: 'Drafts', icon: 'file' },
  { key: 'trash', label: 'Trash', icon: 'trash' },
]
</script>

<template>
  <VxSidebar v-model="active" :items="items" />
</template>

With Badges ​

vue
<VxSidebar v-model="active" :items="[
  { key: 'inbox', label: 'Inbox', icon: 'mail', badge: 12, badgeType: 'primary' },
  { key: 'starred', label: 'Starred', icon: 'star', badge: 'New', badgeType: 'success' },
  { key: 'alerts', label: 'Alerts', icon: 'heart', badge: 3, badgeType: 'danger' },
]" />

Nested Submenus ​

Щёлкните по родительскому элементу, чтобы развернуть/свернуть его дочерние элементы.

vue
<VxSidebar v-model="active" :items="[
  {
    key: 'projects',
    label: 'Projects',
    icon: 'folder',
    children: [
      { key: 'design', label: 'Design System' },
      { key: 'api', label: 'API Platform' },
    ],
  },
]" />

Grouped ​

Группируйте элементы под заголовками разделов с помощью свойства group.

vue
<VxSidebar v-model="active" :items="[
  { key: 'inbox', label: 'Inbox', icon: 'mail', group: 'Communication' },
  { key: 'chat', label: 'Chat', icon: 'heart', group: 'Communication' },
  { key: 'analytics', label: 'Analytics', icon: 'search', group: 'Workspace' },
]" />

Notification Dots ​

Маленькие цветные индикаторы на элементах. По умолчанию красные, настраиваются через dotColor.

vue
<VxSidebar v-model="active" :items="[
  { key: 'inbox', label: 'Inbox', icon: 'mail', dot: true },
  { key: 'chat', label: 'Chat', icon: 'heart', dot: true, dotColor: '#22c55e' },
]" />

Searchable ​

Включите searchable, чтобы добавить поле поиска, фильтрующее элементы по подписи.

vue
<VxSidebar v-model="active" :items="items" searchable />
<VxSidebar v-model="active" :items="items" searchable search-placeholder="Find..." />

Collapsed ​

Переключите collapsed, чтобы показать только иконки с подсказками. Подменю появляются в виде выпадающих окон.

vue
<script setup>
import { ref } from 'vue'

const active = ref('inbox')
const collapsed = ref(false)

const items = [
  { key: 'home', label: 'Home', icon: 'home' },
  { key: 'inbox', label: 'Inbox', icon: 'mail', badge: 5, badgeType: 'primary' },
  {
    key: 'projects',
    label: 'Projects',
    icon: 'folder',
    children: [
      { key: 'design', label: 'Design System' },
      { key: 'api', label: 'API Platform' },
      { key: 'mobile', label: 'Mobile App' },
    ],
  },
  {
    key: 'settings',
    label: 'Settings',
    icon: 'settings',
    children: [
      { key: 'profile', label: 'Profile', icon: 'user' },
      { key: 'security', label: 'Security', icon: 'link' },
      { key: 'billing', label: 'Billing' },
    ],
  },
  { key: 'logout', label: 'Log Out', icon: 'logout', divider: true },
]
</script>

<template>
  <VxButton @click="collapsed = !collapsed">
    {{ collapsed ? 'Expand' : 'Collapse' }}
  </VxButton>
  <VxSidebar v-model="active" :items="items" :collapsed="collapsed" />
</template>

Mini Mode ​

При свёрнутом режиме с mini вместо иконок отображается первая буква каждой подписи.

vue
<VxSidebar v-model="active" :items="items" collapsed mini />

Resizable ​

Включите resizable, чтобы разрешить изменение размера перетаскиванием края боковой панели. Потяните за правый край.

← drag the edge to resize
vue
<script setup>
import { ref } from 'vue'
import { VxSidebar } from 'veloxui'

const active = ref('inbox')
const collapsed = ref(false)

const items = [
  { key: 'inbox', label: 'Inbox', icon: 'mail' },
  { key: 'starred', label: 'Starred', icon: 'star' },
  { key: 'drafts', label: 'Drafts', icon: 'file' },
  { key: 'trash', label: 'Trash', icon: 'trash' },
]
</script>

<template>
  <VxSidebar
    v-model="active"
    v-model:collapsed="collapsed"
    :items="items"
    resizable
    :min-width="160"
    :max-width="360"
  />
</template>

Draggable ​

Включите draggable, чтобы разрешить переупорядочивание элементов верхнего уровня перетаскиванием.

vue
<script setup>
import { ref } from 'vue'
import { VxSidebar } from 'veloxui'

const active = ref('inbox')
const items = ref([
  { key: 'inbox', label: 'Inbox', icon: 'mail' },
  { key: 'starred', label: 'Starred', icon: 'star' },
  { key: 'drafts', label: 'Drafts', icon: 'file' },
  { key: 'trash', label: 'Trash', icon: 'trash' },
  { key: 'settings', label: 'Settings', icon: 'settings' },
])

function onReorder(newItems) {
  items.value = newItems
}
</script>

<template>
  <VxSidebar v-model="active" :items="items" draggable @reorder="onReorder" />
</template>

Router Integration ​

Используйте свойство to на элементах для SPA-навигации.

vue
<VxSidebar v-model="active" :items="[
  { key: 'home', label: 'Home', icon: 'home', to: '/' },
  { key: 'about', label: 'About', icon: 'user', to: '/about' },
]" />

Context Menu ​

Щёлкните правой кнопкой мыши по «Inbox» или «Starred», чтобы увидеть контекстное меню.

vue
<script setup>
import { ref } from 'vue'
import { VxSidebar } from 'veloxui'

const active = ref('inbox')

const items = [
  {
    key: 'inbox',
    label: 'Inbox',
    icon: 'mail',
    badge: 5,
    badgeType: 'primary',
    contextMenu: [
      { label: 'Mark all read', icon: 'check', action: (item) => {} },
      { label: 'Settings', icon: 'settings', action: (item) => {} },
      { label: 'Delete all', icon: 'trash', destructive: true, action: (item) => {} },
    ],
  },
  {
    key: 'starred',
    label: 'Starred',
    icon: 'star',
    contextMenu: [
      { label: 'Clear starred', icon: 'x', action: (item) => {} },
    ],
  },
  { key: 'drafts', label: 'Drafts', icon: 'file' },
  { key: 'settings', label: 'Settings', icon: 'settings' },
]
</script>

<template>
  <VxSidebar v-model="active" :items="items" />
</template>

Loading ​

Показывайте скелетные плейсхолдеры, пока загружаются данные.

vue
<VxSidebar loading :loading-count="6" />

Dark Theme ​

vue
<VxSidebar v-model="active" :items="items" theme="dark" />

Accordion ​

Установите accordion, чтобы одновременно могло быть открыто только одно подменю. Щёлкните «Projects», затем «Settings» — открытым останется только одно.

vue
<script setup>
import { ref } from 'vue'
import { VxSidebar } from 'veloxui'

const active = ref('home')

const items = [
  { key: 'home', label: 'Home', icon: 'home' },
  {
    key: 'projects',
    label: 'Projects',
    icon: 'folder',
    children: [
      { key: 'design', label: 'Design System' },
      { key: 'api', label: 'API Platform' },
    ],
  },
  {
    key: 'settings',
    label: 'Settings',
    icon: 'settings',
    children: [
      { key: 'profile', label: 'Profile', icon: 'user' },
      { key: 'security', label: 'Security', icon: 'link' },
    ],
  },
  { key: 'logout', label: 'Log Out', icon: 'logout' },
]
</script>

<template>
  <VxSidebar v-model="active" :items="items" accordion />
</template>

API ​

VxSidebar Props ​

PropTypeDefaultDescription
itemsMenuItem[][]Элементы боковой панели
v-modelstring''Ключ активного элемента
collapsedbooleanfalseСвернуть до одних иконок
theme'light' | 'dark''light'Цветовая тема
accordionbooleanfalseОдновременно открыто только одно подменю
indentnumber24Отступ дочерних элементов в px
collapsed-widthnumber48Ширина в свёрнутом режиме
widthnumber | string240Ширина боковой панели
roundedbooleantrueСкруглённые углы элементов
searchablebooleanfalseПоказывать поле поиска
search-placeholderstring'Search...'Плейсхолдер поля поиска
draggablebooleanfalseВключить переупорядочивание перетаскиванием
minibooleanfalseПоказывать первую букву в свёрнутом режиме
resizablebooleanfalseВключить маркер изменения размера
min-widthnumber160Минимальная ширина при изменении размера
max-widthnumber400Максимальная ширина при изменении размера
scroll-shadowbooleantrueПоказывать тени прокрутки
loadingbooleanfalseПоказывать скелетные плейсхолдеры
loading-countnumber6Количество скелетных элементов
root-classstring | string[] | object—Класс на корневом элементе
PropertyTypeRequiredDescription
keystringДаУникальный идентификатор
labelstringДаОтображаемый текст
iconstring | ComponentНетИмя встроенной иконки или Vue-компонент
disabledbooleanНетОтключить этот элемент
badgestring | numberНетСодержимое значка
badgeType'default' | 'primary' | 'success' | 'warning' | 'danger'НетЦвет значка
groupstringНетПодпись заголовка группы
dividerbooleanНетПоказать разделитель сверху
action(item) => voidНетОбработчик клика
childrenMenuItem[]НетВложенные элементы подменю
tostring | objectНетЦель навигации Vue Router
dotbooleanНетПоказать точку-уведомление
dotColorstringНетЦвет точки (по умолчанию красный)
pinnedbooleanНетЗакрепить элемент наверху
contextMenuContextMenuItem[]НетЭлементы контекстного меню

Slots ​

SlotPropsDescription
header—Содержимое над навигацией
footer—Содержимое под навигацией
item{ item, active }Пользовательский рендеринг элемента

Events ​

EventPayloadDescription
update:modelValue(key: string)Активный элемент изменён
update:collapsed(collapsed: boolean)Автосворачивание при размере меньше min-width
select(key, item)Элемент выбран
open-change(openKeys: string[])Подменю открыто/закрыто
search(query: string)Содержимое поиска изменилось
reorder(items: MenuItem[])Элементы переупорядочены перетаскиванием
resize(width: number)Размер боковой панели изменён
context-menu(item, event)Правый клик по элементу
pin(item)Элемент закреплён/откреплён

Exposed ​

NameTypeDescription
openKeys()() => string[]Получить ключи открытых подменю
toggleOpen(key)(key: string) => voidПереключить подменю