@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
571 lines (521 loc) • 17.9 kB
Markdown
---
title: 'Drawer'
description: 'The Drawer component is a Modal variation that appears as a side panel at any chosen side of the page.'
version: 10.104.0
generatedAt: 2026-04-17T18:46:09.755Z
checksum: 8953eeeb2cb867c589fb63b790f1712d76c5101e998194e31f21f9ce479c2da0
---
# Drawer
## Import
```tsx
import { Drawer } from '@dnb/eufemia'
```
## Description
The Drawer component is a [Modal](/uilib/components/modal) variation that appears as a side panel at any chosen side of the page: top, bottom, left, or right (default `right`). A Drawer is typically used to show additional information. It can also be used for easy/quick tasks while staying in context.
## Relevant links
- [Figma](https://www.figma.com/design/cdtwQD8IJ7pTeE45U148r1/%F0%9F%92%BB-Eufemia---Web?node-id=12331-4011)
- [Source code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-eufemia/src/components/drawer)
- [Docs code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-design-system-portal/src/docs/uilib/components/drawer)
### Parts in Drawer
To provide custom content to parts of the Drawer, a set of component parts are provided:
- `<Drawer.Navigation>`: The navigation field at the top of the component, default with a close button (Equal to the property `navContent`).
- `<Drawer.Header>`: The header field of the component, where the `title` will appear (Equal to the property `headerContent`).
- `<Drawer.Body>`: The body of the Drawer, provided with a section background color, default `black-3` (Equal to the property `modalContent`).
### More detailed information
For more details regarding the component functionality, check out the [Modal documentation](/uilib/components/modal).
### Root Element (React Portal)
The Drawer component uses [PortalRoot](/uilib/components/portal-root) internally to render its content. See the [PortalRoot documentation](/uilib/components/portal-root) for information on how to control where the portal content appears in the DOM.
## Demos
### Basic Drawer
```tsx
render(
<Drawer
title="Drawer title"
triggerAttributes={{
text: 'Open drawer',
}}
>
<P top>Some informational content</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius pellentesque
nunc egestas risus amet mus aptent luctus imperdiet netus natoque
cubilia mattis nostra proin ornare scelerisque sodales faucibus
placerat sem bibendum pretium rutrum vitae sociis ligula inceptos
morbi quam mi sed pharetra fermentum tortor ullamcorper ipsum tellus
eros euismod volutpat nisl dui lectus fames suscipit phasellus
praesent justo mollis montes velit taciti gravida
</P>
</Drawer>
)
```
### Basic Drawer left placement
```tsx
render(
<Drawer title="Drawer title" containerPlacement="left">
<P top>Some informational content</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius pellentesque
nunc egestas risus amet
</P>
</Drawer>
)
```
### Basic Drawer in fullscreen
```tsx
render(
<Drawer
fullscreen
title="Drawer title"
triggerAttributes={{
text: 'Open drawer',
}}
>
<P top>Some informational content</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius pellentesque
nunc egestas risus amet
</P>
</Drawer>
)
```
### Drawer with custom content
```tsx
render(
<Drawer title="Custom title">
<Drawer.Navigation>
<Breadcrumb onClick={handleBack} />
</Drawer.Navigation>
<Drawer.Header>
<P bottom>This is a lorem ipsum dolor</P>
<Button bottom size="large">
Lorem ipsum
</Button>
<Button bottom size="large" variant="secondary">
Dolor sit
</Button>
<FormStatus state="info">This is a lorem ipsum dolor</FormStatus>
<Tabs
id="unique-linked-id"
data={[
{
title: 'One',
key: 'one',
},
{
title: 'Two',
key: 'two',
},
]}
/>
</Drawer.Header>
<Drawer.Body>
<Tabs.Content id="unique-linked-id" key="contentKey">
{({ title }) => {
return (
<>
<H2>{title}</H2>
<P top>This is a left aligned Drawer content.</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna
laoreet ad ultrices tempus urna curae parturient conubia
quisque viverra eget vestibulum neque pulvinar semper
vulputate id dis varius pellentesque nunc egestas risus
amet mus aptent luctus imperdiet netus natoque cubilia
mattis nostra proin ornare scelerisque sodales faucibus
placerat sem bibendum pretium rutrum vitae sociis ligula
inceptos morbi quam mi sed pharetra fermentum tortor
ullamcorper ipsum tellus eros euismod volutpat nisl dui
lectus fames suscipit phasellus praesent justo mollis
montes velit taciti gravida lacus commodo senectus feugiat
lorem etiam consequat penatibus cum hendrerit accumsan orci
potenti purus nulla
</P>
</>
)
}}
</Tabs.Content>
</Drawer.Body>
</Drawer>
)
```
### Customize trigger button
```tsx
render(
<Drawer
title="Drawer with custom trigger"
triggerAttributes={{
text: 'Custom trigger',
variant: 'primary',
size: 'large',
icon: 'loupe',
icon_position: 'left',
}}
>
<Drawer.Body spacing>
<P>Opened a Drawer with a custom trigger button!</P>
</Drawer.Body>
</Drawer>
)
```
### Close Drawer by callback method
```tsx
render(
<Drawer
title="Drawer title"
triggerAttributes={{
text: 'Open drawer',
}}
hideCloseButton
>
{({ close }) => (
<>
<Button text="Close by callback" on_click={close} />
</>
)}
</Drawer>
)
```
### Remove animation and spacing
```tsx
render(
<Drawer
title="No spacing or animation"
noAnimation
spacing={false}
hideCloseButton
>
<Drawer.Body>
<P top bottom>
This is a lorem ipsum dolor
</P>
<Button bottom size="large">
Lorem ipsum
</Button>
<Button bottom size="large" variant="secondary">
Dolor sit
</Button>
<FormStatus state="info">This is a lorem ipsum dolor</FormStatus>
</Drawer.Body>
</Drawer>
)
```
```tsx
const DrawerMock = () => {
const scrollRef = React.useRef(null)
const innerRef = React.useRef(null)
const [errorMessage, setErrorMessage] = React.useState(null)
const message = errorMessage
? errorMessage
: 'Yes, the "dnb-scroll-view" is used!'
return (
<Drawer
contentRef={innerRef}
scrollRef={scrollRef}
onOpen={() => {
const innerOverflowY = window.getComputedStyle(
innerRef.current
).overflowY
const contentElem = scrollRef.current.querySelector(
'.dnb-drawer__content'
)
const contentOverflowY =
window.getComputedStyle(contentElem)?.overflowY
const scrollOverflowY = window.getComputedStyle(
scrollRef.current
).overflowY
if (contentOverflowY !== 'visible') {
setErrorMessage(
`.dnb-drawer__content was "${contentOverflowY}" and not "visible"`
)
} else if (innerOverflowY !== 'visible') {
setErrorMessage(
`.dnb-drawer__inner was "${innerOverflowY}" and not "visible"`
)
} else if (scrollOverflowY !== 'auto') {
setErrorMessage('.dnb-scroll-view was not "auto"')
}
}}
>
<Drawer.Body>
<div
style={{
height: '100rem',
}}
>
<div className="drawer-scroll-view">
<P size="x-large">{message}</P>
</div>
</div>
</Drawer.Body>
</Drawer>
)
}
render(<DrawerMock />)
```
```tsx
render(
<Drawer title="Drawer title" containerPlacement="top">
<P top>Some informational content</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius pellentesque
nunc egestas risus amet
</P>
</Drawer>
)
```
```tsx
render(
<Drawer title="Drawer title" containerPlacement="bottom">
<P top>Some informational content</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius pellentesque
nunc egestas risus amet
</P>
</Drawer>
)
```
```tsx
const MockComponent = () => {
const scrollRef = React.useRef(null)
return (
<Drawer
title="Drawer title"
scrollRef={scrollRef}
onOpen={() => {
scrollRef.current.scrollTop = 50
}}
>
<P top>Some informational content</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius
pellentesque nunc egestas risus amet mus aptent luctus imperdiet
netus natoque cubilia mattis nostra proin ornare scelerisque
sodales faucibus placerat sem bibendum pretium rutrum vitae sociis
ligula inceptos morbi quam mi sed pharetra fermentum tortor
ullamcorper ipsum tellus eros euismod volutpat nisl dui lectus
fames suscipit phasellus praesent justo mollis montes velit taciti
gravida
</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius
pellentesque nunc egestas risus amet mus aptent luctus imperdiet
netus natoque cubilia mattis nostra proin ornare scelerisque
sodales faucibus placerat sem bibendum pretium rutrum vitae sociis
ligula inceptos morbi quam mi sed pharetra fermentum tortor
ullamcorper ipsum tellus eros euismod volutpat nisl dui lectus
fames suscipit phasellus praesent justo mollis montes velit taciti
gravida
</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna laoreet ad
ultrices tempus urna curae parturient conubia quisque viverra eget
vestibulum neque pulvinar semper vulputate id dis varius
pellentesque nunc egestas risus amet mus aptent luctus imperdiet
netus natoque cubilia mattis nostra proin ornare scelerisque
sodales faucibus placerat sem bibendum pretium rutrum vitae sociis
ligula inceptos morbi quam mi sed pharetra fermentum tortor
ullamcorper ipsum tellus eros euismod volutpat nisl dui lectus
fames suscipit phasellus praesent justo mollis montes velit taciti
gravida
</P>
</Drawer>
)
}
render(<MockComponent />)
```
```tsx
const MockComponent = () => {
const [showMe, setShowMe] = React.useState(false)
const scrollRef = React.useRef(null)
return (
<Drawer
title="Drawer title"
scrollRef={scrollRef}
onOpen={() => {
setShowMe(!showMe)
scrollRef.current.scrollTop = 50
}}
>
<Drawer.Navigation>
{showMe ? (
<>
<P bottom>This is a lorem ipsum dolor</P>
<P bottom>This is a lorem ipsum dolor</P>
<P bottom>This is a lorem ipsum dolor</P>
<P bottom>This is a lorem ipsum dolor</P>
</>
) : null}
</Drawer.Navigation>
<Drawer.Header>
<P bottom>This is a lorem ipsum dolor</P>
<Button bottom size="large">
Lorem ipsum
</Button>
<Button bottom size="large" variant="secondary">
Dolor sit
</Button>
<FormStatus state="info">This is a lorem ipsum dolor</FormStatus>
<Tabs
id="unique-linked-id-x"
data={[
{
title: 'One',
key: 'one',
},
{
title: 'Two',
key: 'two',
},
]}
/>
</Drawer.Header>
<Drawer.Body>
<Tabs.Content id="unique-linked-id-x" key="contentKey0">
{({ title }) => {
return (
<>
<H2>{title}</H2>
<P top>This is a left aligned Drawer content.</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna
laoreet ad ultrices tempus urna curae parturient conubia
quisque viverra eget vestibulum neque pulvinar semper
vulputate id dis
</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna
laoreet ad ultrices tempus urna curae parturient conubia
quisque viverra eget vestibulum neque pulvinar semper
vulputate id dis
</P>
<P top>
Elementum eu suspendisse sit platea elit porttitor magna
laoreet ad ultrices tempus urna curae parturient conubia
quisque viverra eget vestibulum neque pulvinar semper
vulputate id dis
</P>
</>
)
}}
</Tabs.Content>
</Drawer.Body>
</Drawer>
)
}
render(<MockComponent />)
```
## Properties
```json
{
"props": {
"containerPlacement": {
"doc": "Defines on what side the Drawer should be opened. Can be set to `left`, `right`, `top` and `bottom`. Defaults to `right`.",
"type": ["left", "right", "top", "bottom"],
"status": "optional"
},
"title": {
"doc": "The drawer title. Displays on the very top of the content.",
"type": "React.ReactNode",
"status": "optional"
},
"minWidth": {
"doc": "The minimum Drawer content width, defined by a CSS width value like `50vw` (50% of the viewport). Be careful on using fixed `minWidth` so you don't break responsiveness. Defaults to `30rem` (average width is set to `60vw`).",
"type": ["string", "number"],
"status": "optional"
},
"maxWidth": {
"doc": "The maximum Drawer content width, defined by a CSS width value like `20rem`. Defaults to `60rem` (average width is set to `60vw`).",
"type": ["string", "number"],
"status": "optional"
},
"className": {
"doc": "Give the Drawer content a class name (maps to `dnb-drawer`).",
"type": "string",
"status": "optional"
},
"spacing": {
"doc": "If set to `false` then the drawer content will be shown without any spacing. Defaults to `true`.",
"type": "boolean",
"status": "optional"
},
"preventCoreStyle": {
"doc": "By default the drawer content gets added the core style class `dnb-core-style`. Use `false` to disable this behavior.",
"type": "boolean",
"status": "optional"
},
"navContent": {
"doc": "The content which will appear in the navigation, above the header, and side-by-side the close button.",
"type": "React.ReactNode",
"status": "optional"
},
"headerContent": {
"doc": "The content which will appear in the header of the drawer.",
"type": "React.ReactNode",
"status": "optional"
},
"modalContent": {
"doc": "The content which will appear when triggering the drawer.",
"type": "React.ReactNode",
"status": "optional"
},
"alignContent": {
"doc": "Define the inner horizontal alignment of the content. Can be set to `left`, `center`, `right` and `centered`. If `centered`, then the content will also be centered vertically. Defaults to `left`.",
"type": ["left", "right", "centered", "center"],
"status": "optional"
},
"fullscreen": {
"doc": "If set to `true` then the drawer content will be shown as fullscreen, without showing the original content behind. Can be set to `false` to omit the auto fullscreen. Defaults to `auto`.",
"type": ["boolean", "string"],
"status": "optional"
}
}
}
```
### More properties
The properties of [Modal](/uilib/components/modal) formatted as camel case are also provided.
See the table below:
<PropertiesTable props={ModalProperties} />
## Translations
```json
{
"locales": ["da-DK", "en-GB", "nb-NO", "sv-SE"],
"entries": {
"Modal.close_title": {
"nb-NO": "Lukk",
"en-GB": "Close",
"sv-SE": "Stäng",
"da-DK": "Luk"
},
"Modal.dialog_title": {
"nb-NO": "Separat Vindu",
"en-GB": "Dialog Window",
"sv-SE": "Separat fönster",
"da-DK": "Separat vindue"
}
}
}
```
### Drawer sizes
The Drawer is responsive with the following properties:
```css
--drawer-width: 40vw;
--drawer-min-width: 384px;
--drawer-max-width: 40rem;
```
## Events
Drawer includes the same events as [Modal](/uilib/components/modal), only formatted as camel case.
<PropertiesTable props={ModalEvents} />