Drawer
The TkDrawer
is a container component displayed as an overlay. It supports various features such as different header and footer types, multiple variants, and flexible positioning, making it suitable for a wide range of use cases.
- React
- Vue
- Angular
import { TkDrawer } from '@takeoff-ui/react'
import { TkDrawer } from '@takeoff-ui/vue'
import { TkDrawer } from '@takeoff-ui/angular'
Basic​
Demonstrates how to open and close the dialog with simple content.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!
- React
- Vue
- Angular
<TkButton label="Open Drawer" onTkClick={handleClick} />
<TkDrawer
header="Header Text"
open={showDrawer}
onTkDrawerClose={() => setShowDrawer(false)}
>
<div slot="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
quas!
</p>
</div>
</TkDrawer>
<script setup>
import { TkDrawer, TkButton } from '@takeoff-ui/vue';
import { ref } from 'vue';
const showDrawer = ref(false);
</script>
<template>
<div>
<TkButton label="Open Drawer" @tkClick="showDrawer = true" />
<TkDrawer
header="Header Text"
:open="showDrawer"
@tkDrawerClose="() => (showDrawer = false)"
>
<div slot="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore
sed consequuntur error repudiandae numquam deserunt quisquam repellat
libero asperiores earum nam nobis, culpa ratione quam perferendis
esse, cupiditate neque quas!
</p>
</div>
</TkDrawer>
</div>
</template>
Position​
Illustrates how to position the TkDialog
component on different sides of the screen. Easily set the dialog to appear from the left
, right
, top
, or bottom
, allowing for versatile UI layouts.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!
- React
- Vue
- Angular
<TkButton icon="keyboard_arrow_down" onTkClick={() => handleClick("top")} />
<TkButton icon="keyboard_arrow_left" onTkClick={() => handleClick("right")} />
<TkButton icon="keyboard_arrow_up" onTkClick={() => handleClick("bottom")} />
<TkButton icon="keyboard_arrow_right" onTkClick={() => handleClick("left")} />
<TkDrawer
header="Header Text"
open={showDrawer}
position={position}
onTkDrawerClose={() => setShowDrawer(false)}
>
<div slot="content">
<span>Content Slot</span>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
quas!
</p>
</div>
</TkDrawer>
<script setup>
import { TkDrawer, TkButton } from '@takeoff-ui/vue';
import { ref } from 'vue';
const showDrawer = ref(false);
const position = ref('');
const handleClick = (positionValue) => {
position.value = positionValue;
showDrawer.value = true;
};
</script>
<template>
<div>
<TkButton icon="keyboard_arrow_down" @tkClick="handleClick('top')" />
<TkButton icon="keyboard_arrow_left" @tkClick="handleClick('right')" />
<TkButton icon="keyboard_arrow_up" @tkClick="handleClick('bottom')" />
<TkButton icon="keyboard_arrow_right" @tkClick="handleClick('left')" />
<TkDrawer
header="Header Text"
:open="showDrawer"
:position="position"
@tkDrawerClose="() => (showDrawer = false)"
>
<div slot="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore
sed consequuntur error repudiandae numquam deserunt quisquam repellat
libero asperiores earum nam nobis, culpa ratione quam perferendis
esse, cupiditate neque quas!
</p>
</div>
</TkDrawer>
</div>
</template>
Drawer with Footer​
Demonstrates the flexibility of the TkDrawer
component's footer section. You can choose between having no footer or a footer with action buttons with footer
slot.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!
- React
- Vue
- Angular
<TkButton label="Open Drawer" onTkClick={() => setShowDrawer(true)} />
<TkDrawer
header="Drawer with Footer"
open={showDrawer}
onTkDrawerClose={() => setShowDrawer(false)}
>
<div slot="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
quas!
</p>
</div>
<div slot="footer">
<TkButton label="Cancel" variant="neutral" onTkClick={() => setShowDrawer(false)} type="text" />
<TkButton label="Confirm" variant="primary" />
</div>
</TkDrawer>
<TkButton label="Open Drawer" @tkClick="showDrawer = true" />
<TkDrawer
header="Drawer with Footer"
:open="showDrawer"
@tkDrawerClose="()=> showDrawer = false"
>
<div slot="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
quas!
</p>
</div>
<div slot="footer">
<TkButton label="Cancel" variant="neutral" @tkClick="showDrawer = false" type="text" />
<TkButton label="Confirm" variant="primary" />
</div>
</TkDrawer>
Templating​
Demonstrates how to create a fully custom TkDrawer
using container
slot. This allows for more complex drawer content tailored to specific application needs.
- React
- Vue
- Angular
<TkButton label="Open Custom Drawer" onTkClick={() => setShowDrawer(true)} />
<TkDrawer
open={showDrawer}
header="Settings"
onTkDrawerClose={() => setShowDrawer(false)}
>
<div slot="container">
<div className="notification-panel-header">
<span className="header-title">Notification</span>
<div className="header-actions">
<TkButton variant="neutral" icon="more_vert" size="small" type="text"></TkButton>
<TkButton variant="neutral" icon="close" size="small" type="text" onTkClick={() => setShowDrawer(false)}></TkButton>
</div>
</div>
<TkTabs
orientation="horizontal"
size="base"
tab-style="basic"
variant="primary"
is-closable="false"
default-active-index="0"
is-extendable="false"
>
<TkTabsItem slot="tab-content-0" label="All" badgeLabel="01" badged>
<div className="notification-container">
<div className="notification-content">
<div className="message-container">
<div className="message-header">
<div className="message-header-start">
<div className="message-date">14 april 2024</div>
<div className="message-title">Header Text</div>
</div>
<div className="message-header-end">
<TkBadge label="New" variant="info" type="filledlight"></TkBadge>
</div>
</div>
<p className="message-text">
Lorem Ipsum dolor sit amet consiquences.
</p>
</div>
<div className="message-action">
<TkButton variant="info" label="Action" type="text"></TkButton>
</div>
</div>
<div className="notification-end">
<TkButton variant="neutral" size="small" icon="more_vert" type="text"></TkButton>
</div>
</div>
</TkTabsItem>
<TkTabsItem label="New" badgeLabel="03" badged></TkTabsItem>
<TkTabsItem label="Unreaded" badgeLabel="03" badged></TkTabsItem>
</TkTabs>
</div>
</TkDrawer>
<script setup>
import {
TkDrawer,
TkButton,
TkTabs,
TkTabsItem,
TkBadge,
} from '@takeoff-ui/vue';
import { ref } from 'vue';
const showDrawer = ref(false);
</script>
<template>
<TkButton label="Open Custom Drawer" @tkClick="showDrawer = true" />
<TkDrawer
header="Settings"
:open="showDrawer"
@tkDrawerClose="() => (showDrawer = false)"
>
<div slot="container">
<div className="notification-panel-header">
<span className="header-title">Notification</span>
<div className="header-actions">
<TkButton
variant="neutral"
icon="more_vert"
size="small"
type="text"
></TkButton>
<TkButton
variant="neutral"
icon="close"
size="small"
type="text"
@tkClick="showDrawer = false"
></TkButton>
</div>
</div>
<TkTabs
orientation="horizontal"
size="base"
tab-style="basic"
variant="primary"
is-closable="false"
default-active-index="0"
:is-extendable="false"
>
<TkTabsItem label="All">
<div className="notification-container">
<div className="notification-content">
<div className="message-container">
<div className="message-header">
<div className="message-header-start">
<div className="message-date">14 april 2024</div>
<div className="message-title">Header Text</div>
</div>
<div className="message-header-end">
<TkBadge
label="New"
variant="info"
type="filledlight"
></TkBadge>
</div>
</div>
<p className="message-text">
Lorem Ipsum dolor sit amet consiquences.
</p>
</div>
<div className="message-action">
<TkButton variant="info" label="Action" type="text"></TkButton>
</div>
</div>
<div className="notification-end">
<TkButton
variant="neutral"
size="small"
icon="more_vert"
type="text"
></TkButton>
</div>
</div>
</TkTabsItem>
<TkTabsItem label="New"></TkTabsItem>
<TkTabsItem label="Unreaded"></TkTabsItem>
</TkTabs>
</div>
</TkDrawer>
</template>
<style>
.notification-panel-header {
display: flex;
padding: 16px;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.notification-panel-header .header-title {
color: var(--text-darkest, #222530);
/* Body/Base-16 */
font-family: var(--body-m-base-font, Geologica);
font-size: var(--body-m-base-size, 16px);
font-style: normal;
font-weight: 400;
line-height: var(--body-m-base-line-height, 24px);
/* 150% */
}
.notification-panel-header .header-actions {
display: flex;
align-items: center;
gap: 4px;
}
.notification-container {
display: flex;
padding: var(--notification-body-v-padding, 12px) var(--notification-body-h-padding, 16px);
align-items: flex-start;
gap: var(--notification-body-gap, 8px);
align-self: stretch;
border-bottom: var(--spacing-px, 1px) solid var(--border-light, #E1E4EA);
}
.notification-container .notification-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: var(--toast-base-content-gap, 8px);
flex: 1 0 0;
align-self: stretch;
}
.notification-container .notification-content .message-container {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 4px;
align-self: stretch;
}
.notification-container .notification-content .message-container .message-header {
display: flex;
align-items: flex-start;
gap: 8px;
align-self: stretch;
}
.notification-container .notification-content .message-container .message-header .message-header-start {
display: flex;
flex-direction: column;
align-items: flex-start;
flex: 1 0 0;
}
.notification-container .notification-content .message-container .message-header .message-header-start .message-date {
color: var(--text-sub-base, #99A0AE);
/* Subheading/2x-Small-10 */
font-family: var(--subheading-2xs-font, Geologica);
font-size: var(--subheading-2xs-size, 11px);
font-style: normal;
font-weight: 300;
line-height: var(--subheading-2xs-line-height, 16px);
/* 145.455% */
text-transform: uppercase;
}
.notification-container .notification-content .message-container .message-header .message-header-start .message-title {
color: var(--text-darkest, #222530);
/* Body/Small-14 */
font-family: var(--body-s-font, Geologica);
font-size: var(--body-s-size, 14px);
font-style: normal;
font-weight: 400;
line-height: var(--body-s-line-height, 20px);
/* 142.857% */
}
.notification-container .notification-content .message-container .message-text {
color: var(--text-dark, #525866);
/* Body/X-Small-12 */
font-family: var(--body-xs-font, Geologica);
font-size: var(--body-xs-size, 12px);
font-style: normal;
font-weight: 300;
line-height: var(--body-xs-line-height, 18px);
/* 150% */
text-align: left;
}
.notification-container .notification-content .message-container .message-action {
display: flex;
align-items: flex-start;
gap: 12px;
}
.notification-container .notification-end {
display: flex;
align-items: flex-start;
gap: 10px;
align-self: stretch;
}
</style>
Customize Container Styling​
Demonstrates how to customize the container of the TkDrawer
component using containerStyle
prop.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!
- React
- Vue
- Angular
const [width, setWidth] = useState("400px");
<TkButton label="Open Drawer" onTkClick={() => setShowDrawer(true)} />
<TkDrawer
header="Custom Width Drawer"
open={showDrawer}
onTkDrawerClose={() => setShowDrawer(false)}
containerStyle={{ width }}
>
<div slot="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore
sed consequuntur error repudiandae numquam deserunt quisquam repellat
libero asperiores earum nam nobis, culpa ratione quam perferendis
esse, cupiditate neque quas!
</p>
</div>
</TkDrawer>
<script setup>
import { ref } from 'vue';
const showDrawer = ref(false);
const width = ref('400px');
</script>
<template>
<TkDrawer
header="Custom Width Drawer"
:open="showDrawer"
@tkDrawerClose="showDrawer = false"
:containerStyle="{ width }"
>
<div slot="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore
sed consequuntur error repudiandae numquam deserunt quisquam repellat
libero asperiores earum nam nobis, culpa ratione quam perferendis
esse, cupiditate neque quas!
</p>
</div>
</TkDrawer>
</template>
Prevent Dismiss​
Illustrates how to prevent the TkDrawer
from being dismissed by clicking outside of it. This ensures that users must interact with the drawer's controls to close it.
Clicking outside the drawer will close it.
- React
- Vue
- Angular
const [showDrawer, setShowDrawer] = useState(false);
const [preventDismiss, setPreventDismiss] = useState(false);
return (
<>
<div className="mb-4">
<TkCheckbox
label="Prevent Dismiss by Clicking Outside"
value={preventDismiss}
onTkChange={(e) => setPreventDismiss(e.detail)}
/>
</div>
<TkButton label="Open Drawer" onTkClick={() => setShowDrawer(true)} />
<TkDrawer
header="Prevent Dismiss Drawer"
open={showDrawer}
preventDismiss={preventDismiss}
onTkDrawerClose={() => setShowDrawer(false)}
>
<div slot="content">
<p>
{preventDismiss
? "Clicking outside the drawer will not close it. Please use the close button."
: "Clicking outside the drawer will close it."}
</p>
</div>
</TkDrawer>
</>
);
<script setup>
import { TkDrawer, TkButton, TkCheckbox } from '@takeoff-ui/vue';
import { ref } from 'vue';
const preventDismiss = ref(false);
const showDrawer = ref(false);
</script>
<template>
<div>
<div>
<TkCheckbox
label="Prevent Dismiss by Clicking Outside"
v-model="preventDismiss"
/>
</div>
<TkButton label="Open Drawer" @tkClick="() => (showDrawer = true)" />
<TkDrawer
header="Prevent Dismiss Drawer"
:open="showDrawer"
:preventDismiss="preventDismiss"
@tkDrawerClose="showDrawer = false"
>
<div slot="content">
<p v-if="preventDismiss">
Clicking outside the drawer will not close it. Please use the close
button.
</p>
<p v-else>Clicking outside the drawer will close it.</p>
</div>
</TkDrawer>
</div>
</template>
API​
Props​
Name | Type | Default | Description |
---|---|---|---|
any | null | The style attribute of container element | |
"basic", "divided", "light" | 'basic' | The mode of the footer | |
string | null | Text to display in the drawer header | |
"basic", "dark", "divided", "light", "primary" | 'basic' | The type of the header | |
boolean | false | Controls whether the backdrop is shown | |
boolean | false | Controls whether to hide the close icon | |
"base", "dark", "darkest", "light", "lightest" | 'base' | Appearance of the mask | |
boolean | false | Controls whether the drawer is open or closed | |
"bottom", "full-screen", "left", "right", "top" | 'right' | Determines the position of the drawer | |
boolean | false | Prevents the drawer from being dismissed by clicking outside | |
boolean | false | Controls whether to unblock scrolling when the drawer is open |
Events​
Name | Description |
---|---|
tk-drawer-change | Emitted when the drawer's open state changes |
tk-drawer-close | Emitted when the drawer is closed |
tk-drawer-enter | Emitted when the drawer starts to enter |
tk-drawer-leave | Emitted when the drawer starts to leave |
tk-drawer-open | Emitted when the drawer is opened |
Methods​
Name | Description |
---|---|
close | Closes the drawer by emitting a tk-drawer-close event Parent components should listen for this event and update the open prop |
show | Opens the drawer by emitting a tk-drawer-open event Parent components should listen for this event and update the open prop |
Slots​
Name | Description |
---|---|
container | Custom container template. |
content | Custom inner body template. |
footer | Custom footer template. |
header | Custom header template. |
header-action | Custom actions template of header. |