Skip to content
On this page

Drawer

A floating panel that slides out of the edge of the screen.

Basic usage

Control drawer display and hidden state through v-model two-way binding. Set the direction property to control the drawer expansion direction. Default slots inside components accept user-defined content.

<>
<template>
    <div>
        <kl-button @click="rtl = true">right to left</kl-button>
        <kl-button @click="ltr = true">left to right</kl-button>
        <kl-button @click="ttb = true">top to bottom</kl-button>
        <kl-button @click="btt = true">bottom to top</kl-button>

        <kl-drawer v-model="rtl" direction="rtl">
            <div class="header">
                <button @click="rtl = false"><KlOtherError /></button>
                <h3>Basic Drawer</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="ltr" direction="ltr">
            <div class="header">
                <button @click="ltr = false"><KlOtherError /></button>
                <h3>Basic Drawer</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="ttb" direction="ttb">
            <div class="header">
                <button @click="ttb = false"><KlOtherError /></button>
                <h3>Basic Drawer</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="btt" direction="btt">
            <div class="header">
                <button @click="btt = false"><KlOtherError /></button>
                <h3>Basic Drawer</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
    </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
const rtl = ref(false)
const ltr = ref(false)
const ttb = ref(false)
const btt = ref(false)
</script>

<style lang="scss" scoped>
.header {
    display: flex;
    padding: 16px 24px;
    border-bottom: 1px solid #ddd;

    h3 {
        white-space: nowrap;
        margin: 0 0 0 10px;
        padding: 0;
    }
}

.content {
    padding: 16px 24px;

    p {
        white-space: nowrap;
    }
}
</style>

Drawer size

Set the size property to customize the drawer size. If size is passed as a numeric type, the unit is px, and a percentage string is supported. The default is 30%.

<>
<template>
    <div>
        <kl-button @click="pt20 = true">20%</kl-button>
        <kl-button @click="pt30 = true">30%</kl-button>
        <kl-button @click="px200 = true">200px</kl-button>
        <kl-button @click="px300 = true">300px</kl-button>

        <kl-drawer v-model="pt20" size="20%">
            <div class="header">
                <button @click="pt20 = false"><KlOtherError /></button>
                <h3>Drawer Size</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="pt30" size="30%">
            <div class="header">
                <button @click="pt30 = false"><KlOtherError /></button>
                <h3>Drawer Size</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="px200" :size="200">
            <div class="header">
                <button @click="px200 = false"><KlOtherError /></button>
                <h3>Drawer Size</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="px300" :size="300">
            <div class="header">
                <button @click="px300 = false"><KlOtherError /></button>
                <h3>Drawer Size</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
    </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
const pt20 = ref(false)
const pt30 = ref(false)
const px200 = ref(false)
const px300 = ref(false)
</script>

<style lang="scss" scoped>
.header {
    display: flex;
    padding: 16px 24px;
    border-bottom: 1px solid #ddd;

    h3 {
        white-space: nowrap;
        margin: 0 0 0 10px;
        padding: 0;
    }
}

.content {
    padding: 16px 24px;

    p {
        white-space: nowrap;
    }
}
</style>

Set mask layer z-index

With the z-index property, you can change the level of the mask layer. Note: Drawer level = Mask level + 1. For example: If z-index = 299, then mask level = 299, drawer level = 300. The default value is 1000.

z-index: 300
<>
<template>
    <div>
        <div class="box">z-index: 300</div>
        <kl-button @click="drawer299 = true">z-index: 299</kl-button>
        <kl-button @click="drawer301 = true">z-index: 301</kl-button>

        <kl-drawer v-model="drawer299" :z-index="299">
            <div class="header">
                <button @click="drawer299 = false"><KlOtherError /></button>
                <h3>Drawer Tier</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="drawer301" :z-index="301">
            <div class="header">
                <button @click="drawer301 = false"><KlOtherError /></button>
                <h3>Drawer Tier</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
    </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
const drawer299 = ref(false)
const drawer301 = ref(false)
</script>

<style lang="scss" scoped>
.box {
    position: relative;
    box-sizing: border-box;
    width: 120px;
    height: 120px;
    margin: 10px;
    padding: 10px;
    background-color: #67c23a;
    color: #fff;
    z-index: 300;
}
.header {
    display: flex;
    padding: 16px 24px;
    border-bottom: 1px solid #ddd;

    h3 {
        white-space: nowrap;
        margin: 0 0 0 10px;
        padding: 0;
    }
}

.content {
    padding: 16px 24px;

    p {
        white-space: nowrap;
    }
}
</style>

Whether to lock the scroll bar

By setting the lock-scroll property, you can decide whether to lock the scroll bar according to your own requirements. If you lock the scroll bar, you need to handle the page jitter problem caused by the scroll bar switching between display and hide. The default is true.

<>
<template>
    <div>
        <kl-button @click="lock = true">锁定滚动条</kl-button>
        <kl-button @click="unlock = true">不锁定滚动条</kl-button>

        <kl-drawer v-model="lock" :lock-scroll="true">
            <div class="header">
                <button @click="lock = false"><KlOtherError /></button>
                <h3>Lock Scroll</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
        <kl-drawer v-model="unlock" :lock-scroll="false">
            <div class="header">
                <button @click="unlock = false"><KlOtherError /></button>
                <h3>Unlock Scroll</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
    </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
const lock = ref(false)
const unlock = ref(false)
</script>

<style lang="scss" scoped>
.header {
    display: flex;
    padding: 16px 24px;
    border-bottom: 1px solid #ddd;

    h3 {
        white-space: nowrap;
        margin: 0 0 0 10px;
        padding: 0;
    }
}

.content {
    padding: 16px 24px;

    p {
        white-space: nowrap;
    }
}
</style>

Custom mask layer with drawer styles

By setting the modal-class and drawer-class properties, you can customize the styles of masks and drawers.

Note: To make a custom class name work, you need to use the :deep depth selector

<>
<template>
    <div>
        <kl-button @click="drawer = true">自定义样式</kl-button>

        <kl-drawer v-model="drawer" modal-class="modalClass" drawer-class="drawerClass">
            <div class="header">
                <button @click="drawer = false"><KlOtherError /></button>
                <h3>Custom Class</h3>
            </div>
            <div class="content">
                <p>Some contents...</p>
                <p>Some contents...</p>
                <p>Some contents...</p>
            </div>
        </kl-drawer>
    </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
const drawer = ref(false)
</script>

<style lang="scss" scoped>
:deep(.modalClass) {
    background-color: rgba(255, 0, 0, 0.4);
}

:deep(.drawerClass) {
    background-color: #000;
    color: #fff;
}

.header {
    display: flex;
    padding: 16px 24px;
    border-bottom: 1px solid #ddd;

    h3 {
        white-space: nowrap;
        margin: 0 0 0 10px;
        padding: 0;
    }
}

.content {
    padding: 16px 24px;

    p {
        white-space: nowrap;
    }
}
</style>

API

Attribute

namedescriptiontypedefault valuerequired
model-value / v-modelShow drawer or notbooleanyes
sizeThe size of the drawer form, in pixels when using type number and x% when using type stringnumber/string'30%'no
directionThe direction the drawer opensrtl / ltr / ttb / bttrtlno
modalWhether a mask is requiredbooleantrueno
lock-scrollWhether to scroll lock the body when the drawer appearsbooleantrueno
modal-classThe custom class name of the mask layerstringno
drawer-classThe custom class name of the drawerstringno
close-escCan you close the drawer by pressing ESCbooleantrueno
z-indexSet the z-index of the mask layer, z-index of the drawer = z-index of the mask layer + 1number1000no

Slot

namedescription
defaultContents of drawer

Released under the MIT License.