Выдвижная панель
Боковая сдвижная панель, выезжающая от края экрана; подходит для временных действий, располагающихся ближе к краю, чем Dialog (подробности, фильтры, шаги мастера). Как и Dialog, использует role="dialog" + aria-modal="true"; фокус удерживается внутри панели, закрытие возможно по Esc и нажатием на маску.
Базовое использование
<template>
<LhButton @click="basic = true">Открыть панель</LhButton>
<LhDrawer v-model="basic" title="Детали заказа">
<p>Здесь размещается основное содержимое панели.</p>
</LhDrawer>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const basic = ref(false)
</script><script>
export default {
data() {
return { basic: false }
},
}
</script>
<template>
<LhButton @click="basic = true">Открыть панель</LhButton>
<LhDrawer v-model="basic" title="Детали заказа">
<p>Здесь размещается основное содержимое панели.</p>
</LhDrawer>
</template>Четыре направления
<script setup lang="ts">
import { ref } from 'vue'
const dirVisible = ref(false)
const direction = ref<'right' | 'left' | 'top' | 'bottom'>('right')
const size = ref('40%')
function openDir(d: 'right' | 'left' | 'top' | 'bottom') {
direction.value = d
dirVisible.value = true
}
</script>
<template>
<!-- Открыть правую панель -->
<LhButton @click="openDir('right')">right</LhButton>
<!-- Открыть левую панель -->
<LhButton @click="openDir('left')">left</LhButton>
<!-- Открыть верхнюю панель -->
<LhButton @click="openDir('top')">top</LhButton>
<!-- Открыть нижнюю панель -->
<LhButton @click="openDir('bottom')">bottom</LhButton>
<!-- Выезд в указанном направлении -->
<LhDrawer v-model="dirVisible" :title="`Панель: ${direction}`" :direction="direction" :size="size">
<p>Текущее направление: {{ direction }}</p>
</LhDrawer>
</template><script>
export default {
data() {
return { dirVisible: false, direction: 'right', size: '40%' }
},
methods: {
openDir(d) {
this.direction = d
this.dirVisible = true
},
},
}
</script>
<template>
<!-- Открыть правую панель -->
<LhButton @click="openDir('right')">right</LhButton>
<!-- Открыть левую панель -->
<LhButton @click="openDir('left')">left</LhButton>
<!-- Открыть верхнюю панель -->
<LhButton @click="openDir('top')">top</LhButton>
<!-- Открыть нижнюю панель -->
<LhButton @click="openDir('bottom')">bottom</LhButton>
<!-- Выезд в указанном направлении -->
<LhDrawer v-model="dirVisible" :title="`Панель: ${direction}`" :direction="direction" :size="size">
<p>Текущее направление: {{ direction }}</p>
</LhDrawer>
</template>Пользовательский размер и нижняя область
<script setup lang="ts">
import { ref } from 'vue'
const sized = ref(false)
</script>
<template>
<!-- Открыть панель шириной 480px -->
<LhButton @click="sized = true">Панель шириной 480px</LhButton>
<!-- Панель фиксированного размера, внизу — область действий -->
<LhDrawer v-model="sized" title="Условия фильтрации" :size="480">
<LhInput placeholder="Фильтр по названию" />
<LhInput placeholder="Фильтр по тегам" />
<template #footer>
<LhButton @click="sized = false">Отмена</LhButton>
<LhButton type="primary" @click="sized = false">Применить фильтр</LhButton>
</template>
</LhDrawer>
</template><script>
export default {
data() {
return { sized: false }
},
}
</script>
<template>
<!-- Открыть панель шириной 480px -->
<LhButton @click="sized = true">Панель шириной 480px</LhButton>
<!-- Панель фиксированного размера, внизу — область действий -->
<LhDrawer v-model="sized" title="Условия фильтрации" :size="480">
<LhInput placeholder="Фильтр по названию" />
<LhInput placeholder="Фильтр по тегам" />
<template #footer>
<LhButton @click="sized = false">Отмена</LhButton>
<LhButton type="primary" @click="sized = false">Применить фильтр</LhButton>
</template>
</LhDrawer>
</template>Если в
sizeпередать число, это пиксели; строка поддерживает проценты (например'40%'). Для направления влево/вправо параметр задаёт ширину, для вверх/вниз — высоту.
Поведенческие переключатели
mask-closable запрещает закрытие по нажатию на маску, show-close скрывает кнопку закрытия в правом верхнем углу, close-on-esc отключает закрытие по Esc, lock-scroll отключает блокировку прокрутки страницы при открытии, teleport-target задаёт контейнер монтирования.
<script setup lang="ts">
import { ref } from 'vue'
const adv1 = ref(false)
const adv2 = ref(false)
const adv3 = ref(false)
</script>
<template>
<!-- Открыть панель «Только кнопка закрытия» -->
<LhButton @click="adv1 = true">Только кнопка закрытия</LhButton>
<!-- Открыть панель «Без блокировки прокрутки» -->
<LhButton @click="adv2 = true">Без блокировки прокрутки</LhButton>
<!-- Нажатие на маску и Esc не закрывают -->
<LhDrawer
v-model="adv1"
title="Только кнопка закрытия"
:mask-closable="false"
:show-close="false"
:close-on-esc="false"
>
<p>Нажатие на маску и Esc не закрывают панель — только кнопка.</p>
<template #footer>
<LhButton type="primary" @click="adv1 = false">Закрыть</LhButton>
</template>
</LhDrawer>
<!-- При открытии страницу по-прежнему можно прокручивать -->
<LhDrawer v-model="adv2" title="Без блокировки прокрутки" :lock-scroll="false">
<p>При открытой панели страницу по-прежнему можно прокручивать.</p>
</LhDrawer>
<!-- Монтирование в заданный контейнер -->
<LhDrawer v-model="adv3" title="Заданный контейнер монтирования" teleport-target="#drawer-host">
<p>Панель перенесена в контейнер с id drawer-host.</p>
</LhDrawer>
</template><script>
export default {
data() {
return { adv1: false, adv2: false, adv3: false }
},
}
</script>
<template>
<!-- Открыть панель «Только кнопка закрытия» -->
<LhButton @click="adv1 = true">Только кнопка закрытия</LhButton>
<!-- Открыть панель «Без блокировки прокрутки» -->
<LhButton @click="adv2 = true">Без блокировки прокрутки</LhButton>
<!-- Нажатие на маску и Esc не закрывают -->
<LhDrawer
v-model="adv1"
title="Только кнопка закрытия"
:mask-closable="false"
:show-close="false"
:close-on-esc="false"
>
<p>Нажатие на маску и Esc не закрывают панель — только кнопка.</p>
<template #footer>
<LhButton type="primary" @click="adv1 = false">Закрыть</LhButton>
</template>
</LhDrawer>
<!-- При открытии страницу по-прежнему можно прокручивать -->
<LhDrawer v-model="adv2" title="Без блокировки прокрутки" :lock-scroll="false">
<p>При открытой панели страницу по-прежнему можно прокручивать.</p>
</LhDrawer>
<!-- Монтирование в заданный контейнер -->
<LhDrawer v-model="adv3" title="Заданный контейнер монтирования" teleport-target="#drawer-host">
<p>Панель перенесена в контейнер с id drawer-host.</p>
</LhDrawer>
</template>Drawer API
Props
| Свойство | Описание | Тип | По умолчанию |
|---|---|---|---|
| modelValue | Показывать ли (v-model) | boolean | — |
| title | Заголовок (можно также использовать слот header) | string | — |
| direction | Направление | "right" | "left" | "top" | "bottom" | 'right' |
| size | Размер: число — px, строка поддерживает проценты | string | number | '30%' |
| maskClosable | Закрывать ли при нажатии на маску | boolean | true |
| showClose | Показывать ли кнопку закрытия | boolean | true |
| teleportTarget | Цель Teleport (селектор или элемент, по умолчанию body) | string | HTMLElement | 'body' |
| lockScroll | Блокировать ли прокрутку страницы | boolean | true |
| closeOnEsc | Закрывать ли по Esc | boolean | true |
| themeVars | Тематические переменные уровня компонента, переопределяют конфигурацию ConfigProvider | { [x: string]: string; } | — |
| bgPattern | Фоновый узор уровня компонента, переопределяет конфигурацию ConfigProvider | string | — |
| sx | Свойство быстрой компоновки sx (применяется к панели) | LhSxProps | — |
Events
| Событие | Описание | Параметр |
|---|---|---|
| update:model-value | Изменение видимости | (value: boolean) |
| open | Срабатывает после открытия | — |
| close | Срабатывает после закрытия | — |
Slots
| Слот | Описание |
|---|---|
| default | Основное содержимое |
| header | Пользовательский заголовок (включая область заголовка) |
| footer | Пользовательская нижняя область действий |
Methods
| Метод | Описание |
|---|---|
| open | Программное открытие |
| close | Программное закрытие |
Доступность
role="dialog"+aria-modal="true"; при наличии заголовка он связывается черезaria-labelledby, без заголовка используетсяdrawer.titleиз языкового пакета в качестве aria-label- При открытии фокус переносится на первый доступный для фокуса элемент панели, Tab циклически перемещается внутри панели, после закрытия фокус возвращается на триггер
- Закрытие по Esc (можно отключить через
close-on-esc); маска декоративная (aria-hidden) - Кнопка закрытия — настоящий
<button>, aria-label берётся из языкового пакетаdrawer.close - Анимация выезда/заезда при
prefers-reduced-motionупрощается до чистого плавного появления/исчезновения
Типы
Структура открытых TypeScript-типов этого компонента (автоматически извлечено из packages/components/drawer/src/types.ts и исходников @lh-ui/share/core/*; раскройте каждый пункт, чтобы увидеть полное определение; описания свойств — в таблице Props выше):
LhDrawerProps
/**
* Props компонента Drawer
*/
export interface LhDrawerProps {
/** Показывать ли (v-model) */
modelValue?: boolean
/** Заголовок */
title?: string
/** Направление */
direction?: LhDrawerDirection
/** Размер: число — px, строка поддерживает проценты */
size?: string | number
/** Закрывать ли при нажатии на маску */
maskClosable?: boolean
/** Показывать ли кнопку закрытия */
showClose?: boolean
/** Цель Teleport (селектор или элемент, по умолчанию body) */
teleportTarget?: string | HTMLElement
/** Блокировать ли прокрутку страницы */
lockScroll?: boolean
/** Закрывать ли по Esc */
closeOnEsc?: boolean
/** Тематические переменные уровня компонента, переопределяют конфигурацию ConfigProvider */
themeVars?: Record<string, string>
/** Фоновый узор уровня компонента, переопределяет конфигурацию ConfigProvider */
bgPattern?: string
/** Свойство быстрой компоновки sx (применяется к панели) */
sx?: LhSxProps
}LhDrawerDirection (из @lh-ui/share/core/drawer (logic.ts))
/**
* Чистая логика Drawer (без зависимостей от фреймворка)
*/
/** Направление панели */
export type LhDrawerDirection = 'right' | 'left' | 'top' | 'bottom'