WUI logo

Drawer

Allows user to open a modal with a special style.

version

4.1.2

install

yarn add @welcome-ui/drawer

usage

import { Drawer } from '@welcome-ui/drawer'

About #

Drawer based on Reakit's dialog with a really nice theme 💅

Usage #

The most basic drawer needs useDrawerState(), <Drawer.Trigger />, <Drawer.Backdrop /> and <Drawer />. Please note you have to wrap your <Drawer /> with a <Drawer.Backdrop />. If you don't want this <Drawer.Backdrop /> to be visible, please provide it a backdropVisible prop set to false. Backdrop allows us to have a smooth scroll across all browsers by wrapping the Drawer. This way, the Drawer can be absolutely positioned in the fixed Backdrop wrapper.

function DefaultDrawer() {
const drawer = useDrawerState()
return (
<>
<Drawer.Trigger as={Button} {...drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop {...drawer} backdropVisible={false}>
<Drawer aria-label="Default drawer" {...drawer}>
<Drawer.Close {...drawer} />
Praesent sit amet quam ac velit faucibus dapibus. Quisque sapien ligula, rutrum quis aliquam
nec, convallis sit amet erat. Mauris auctor blandit porta.
</Drawer>
</Drawer.Backdrop>
</>
)
}

Backdrop #

You have to wrap <Drawer /> with <Drawer.Backdrop />. It can be either visible or not, thanks to the backdropVisible prop (which is true by default). It corresponds to Reakit Dialog's Backdrop with custom styling.

function BackdropDrawer() {
const drawer = useDrawerState()
return (
<>
<Drawer.Trigger as={Button} {...drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop {...drawer}>
<Drawer aria-label="Backdrop drawer" {...drawer}>
<Drawer.Close {...drawer} />
Praesent sit amet quam ac velit faucibus dapibus. Quisque sapien ligula, rutrum quis aliquam
nec, convallis sit amet erat. Mauris auctor blandit porta.
</Drawer>
</Drawer.Backdrop>
</>
)
}

Layout #

We provide basic layout components for your drawer: <Drawer.Close />, <Drawer.Title />, <Drawer.Content /> and <Drawer.Footer />. They're all optionnal. If you're using <Drawer.Close /> along with <Drawer.Title />, please make sure to position <Drawer.Close /> first in your code, for styling purpose.

function ContentDrawer() {
const drawer = useDrawerState()
return (
<>
<Drawer.Trigger as={Button} {...drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop {...drawer}>
<Drawer aria-label="Layout drawer" {...drawer}>
<Drawer.Close {...drawer} />
<Drawer.Title>Hello</Drawer.Title>
<Drawer.Content>
Praesent sit amet quam ac velit faucibus dapibus. Quisque sapien ligula, rutrum quis
aliquam nec, convallis sit amet erat. Mauris auctor blandit porta.
</Drawer.Content>
<Drawer.Footer>
<Button onClick={drawer.hide}>Close Drawer</Button>
</Drawer.Footer>
</Drawer>
</Drawer.Backdrop>
</>
)
}

Placement #

By default the placement of the drawer will be on the right but you can set it to top, bottom, or left.

function PlacementDrawer() {
const drawer = useDrawerState()
const [placement, setPlacement] = React.useState('right')
return (
<>
<Box mb="xl">
<Field label="Placement" flexDirection="row">
<RadioGroup
value={placement}
onChange={e => setPlacement(e.target.value)}
options={[
{ value: 'top', label: 'Top' },
{ value: 'right', label: 'Right' },
{ value: 'bottom', label: 'Bottom' },
{ value: 'left', label: 'Left' },
]}
/>
</Field>
</Box>
<Drawer.Trigger as={Button} {...drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop {...drawer}>
<Drawer aria-label="Placement drawer" {...drawer} placement={placement}>
Praesent sit amet quam ac velit faucibus dapibus. Quisque sapien ligula, rutrum quis
aliquam nec, convallis sit amet erat. Mauris auctor blandit porta.
</Drawer>
</Drawer.Backdrop>
</>
)
}

Size #

By default the size of the drawer will be lg which is set in the theme. We provide 3 different sizes that will adapt according to the position of the Drawer. You can also set a custom size if needed.

function SizeDrawer() {
const drawer = useDrawerState()
const [size, setSize] = React.useState('lg')
const [placement, setPlacement] = React.useState('right')
return (
<>
<Box mb="xl">
<Field label="Size" flexDirection="row">
<RadioGroup
value={size}
onChange={e => setSize(e.target.value)}
options={[
{ value: 'sm', label: 'sm' },
{ value: 'md', label: 'md' },
{ value: 'lg', label: 'lg' },
{
value: '50%',
label: (
<>
50% <small>(width or height depending on the placement</small>
</>
),
},
]}
/>
</Field>
</Box>
<Box mb="xl">
<Field label="Placement" flexDirection="row">
<RadioGroup
value={placement}
onChange={e => setPlacement(e.target.value)}
options={[
{ value: 'top', label: 'Top' },
{ value: 'right', label: 'Right' },
{ value: 'bottom', label: 'Bottom' },
{ value: 'left', label: 'Left' },
]}
/>
</Field>
</Box>
<Drawer.Trigger as={Button} {...drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop {...drawer}>
<Drawer aria-label="Size drawer" {...drawer} size={size} placement={placement}>
Praesent sit amet quam ac velit faucibus dapibus. Quisque sapien ligula, rutrum quis
aliquam nec, convallis sit amet erat. Mauris auctor blandit porta.
</Drawer>
</Drawer.Backdrop>
</>
)
}

Styling #

All the elements can be styled as you see fit, by extending drawer's theme or directly with styled props.

function StylingDrawer() {
const drawer = useDrawerState()
return (
<>
<Drawer.Trigger as={Button} {...drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop {...drawer} backgroundColor="rgba(20, 0, 80, .5)">
<Drawer aria-label="Default drawer" {...drawer} backgroundColor="nude.200">
<Drawer.Close {...drawer} w={30} h={30} />
<Drawer.Title borderBottom="1px solid" borderBottomColor="dark.200">
Hello
</Drawer.Title>
<Drawer.Content backgroundColor="light.900">
Praesent sit amet quam ac velit faucibus dapibus. Quisque sapien ligula, rutrum quis
aliquam nec, convallis sit amet erat. Mauris auctor blandit porta.
</Drawer.Content>
<Drawer.Footer borderTop="1px solid" borderTopColor="dark.200">
<Stack direction="row">
<Button onClick={drawer.hide}>Save</Button>
<Button onClick={drawer.hide} variant="tertiary">
Close
</Button>
</Stack>
</Drawer.Footer>
</Drawer>
</Drawer.Backdrop>
</>
)
}

useDrawerState #

We use useDialogState from Reakit Dialog for the state of the drawer with the animated flag set to true by default.

Pass options to useDrawerState :

  • visible: e.g. const modal = useDrawerState({ visible: true })

And the hook returns (among other things):

  • visible : whether the drawer is currently visible
  • hide : a function to hide the drawer

Properties #

Drawer #
NameType(s)DefaultRequired
placement
"top"
"right"
"bottom"
"left"
right
size
string
lg
Drawer.Backdrop #
NameType(s)DefaultRequired
hideOnClickOutside
Boolean
true
backdropVisible
Boolean
true

Packages #

Dependencies #
Peer dependencies #

Previous

Toast

Next

Modal