Skip to content

Commit

Permalink
feat: migrate Drawer component
Browse files Browse the repository at this point in the history
  • Loading branch information
theo-mesnil committed Jul 24, 2023
1 parent 8b65296 commit 3d64b9d
Show file tree
Hide file tree
Showing 11 changed files with 258 additions and 350 deletions.
24 changes: 14 additions & 10 deletions docs/components/Header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'
import { Box } from '@welcome-ui/box'
import { InformationIcon, MenuIcon } from '@welcome-ui/icons'
import NextLink from 'next/link'
import { Drawer, useDrawerState } from '@welcome-ui/drawer'
import { Drawer, useDrawer } from '@welcome-ui/drawer'
import { useModal } from '@welcome-ui/modal'
import { Button } from '@welcome-ui/button'
import { CrossIcon } from '@welcome-ui/icons'
Expand All @@ -19,7 +19,7 @@ import * as S from './styles'
import { NavBar } from './NavBar'

export const Header = () => {
const mobileMenuDrawerState = useDrawerState()
const mobileMenuDrawer = useDrawer()
const modal = useModal()
const { pathname } = useRouter()
const variants = {
Expand Down Expand Up @@ -63,20 +63,24 @@ export const Header = () => {
{hasBeenHydrated && (
<>
<Drawer.Trigger
flexShrink={0}
as={Button}
display={{ md: 'none' }}
shape="circle"
size="sm"
state={mobileMenuDrawerState}
store={mobileMenuDrawer}
>
{mobileMenuDrawerState.visible ? <CrossIcon /> : <MenuIcon />}
{mobileMenuDrawer.open ? <CrossIcon /> : <MenuIcon />}
</Drawer.Trigger>
<Drawer.Backdrop backdropVisible={false} state={mobileMenuDrawerState}>
<S.MenuMobileDrawer aria-label="Menu backdrop" state={mobileMenuDrawerState}>
<NavBar drawerState={mobileMenuDrawerState} isMobileMenu mb="lg" />
<ComponentsList onClick={() => mobileMenuDrawerState.hide()} />
</S.MenuMobileDrawer>
</Drawer.Backdrop>
<S.MenuMobileDrawer
withBackdrop={false}
store={mobileMenuDrawer}
aria-label="Menu backdrop"
withCloseButton={false}
>
<NavBar drawerState={mobileMenuDrawer} isMobileMenu mb="lg" />
<ComponentsList onClick={() => mobileMenuDrawer.hide()} />
</S.MenuMobileDrawer>
</>
)}
<ThemeHelper modalStore={modal} />
Expand Down
161 changes: 74 additions & 87 deletions docs/pages/components/drawer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,80 +21,71 @@ Drawer based on [Reakit's dialog](https://reakit.io/docs/dialog/) with a really

## 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.
The most basic drawer needs `useDrawer()`, `<Drawer.Trigger />` and `<Drawer />`. If you don't want a backdrop to be visible, please provide it a `withBackdrop` 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.

```jsx
function DefaultDrawer() {
const drawerState = useDrawerState()
const drawer = useDrawer()

return (
<>
<Drawer.Trigger as={Button} state={drawerState}>
<Drawer.Trigger as={Button} store={drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop state={drawerState} backdropVisible={false}>
<Drawer aria-label="Default drawer" state={drawerState}>
<Drawer.Close state={drawerState} />
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>
<Drawer aria-label="Default drawer" store={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>
</>
)
}
```

## 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](https://reakit.io/docs/dialog/#backdrop) with custom styling.
You have to add on `<Drawer />` a prop `withBackdrop`. This add our backdrop `<Drawer.Backdrop />` on the drawer. You can add custom wrapper with the property `backdrop`.

```jsx
function BackdropDrawer() {
const drawerState = useDrawerState()
const drawer = useDrawer()

return (
<>
<Drawer.Trigger as={Button} state={drawerState}>
Open Drawer
<Drawer.Trigger as={Button} store={drawer}>
Open Drawer with backdrop
</Drawer.Trigger>
<Drawer.Backdrop state={drawerState}>
<Drawer aria-label="Backdrop drawer" state={drawerState}>
<Drawer.Close state={drawerState} />
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>
<Drawer withBackdrop hideOnInteractOutside aria-label="Backdrop drawer" store={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>
</>
)
}
```

## 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.
We provide basic layout components for your drawer: `<Drawer.Title />`, `<Drawer.Content />` and `<Drawer.Footer />`. They're all optionnal. By default you have a close button `<Drawer.Close />`, you can remove it with set `false` on `withCloseButton` property. If you're using `<Drawer.Close />` along with `<Drawer.Title />`, please make sure to position `<Drawer.Close />` first in your code, for styling purpose.

```jsx
function ContentDrawer() {
const drawerState = useDrawerState()
const drawer = useDrawer()

return (
<>
<Drawer.Trigger as={Button} state={drawerState}>
<Drawer.Trigger as={Button} store={drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop state={drawerState}>
<Drawer aria-label="Layout drawer" state={drawerState}>
<Drawer.Close state={drawerState} />
<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={drawerState.hide}>Close Drawer</Button>
</Drawer.Footer>
</Drawer>
</Drawer.Backdrop>
<Drawer aria-label="Layout drawer" store={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>
</>
)
}
Expand All @@ -106,7 +97,7 @@ By default the `placement` of the drawer will be on the `right` but you can set

```jsx
function PlacementDrawer() {
const drawerState = useDrawerState()
const drawer = useDrawer()
const [placement, setPlacement] = React.useState('right')

return (
Expand All @@ -125,15 +116,13 @@ function PlacementDrawer() {
/>
</Field>
</Box>
<Drawer.Trigger as={Button} state={drawerState}>
<Drawer.Trigger as={Button} store={drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop state={drawerState}>
<Drawer aria-label="Placement drawer" state={drawerState} 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>
<Drawer aria-label="Placement drawer" store={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>
</>
)
}
Expand All @@ -145,7 +134,7 @@ By default the `size` of the drawer will be `lg` which is set in the theme. We p

```jsx
function SizeDrawer() {
const drawerState = useDrawerState()
const drawer = useDrawer()
const [size, setSize] = React.useState('lg')
const [placement, setPlacement] = React.useState('right')

Expand Down Expand Up @@ -186,15 +175,19 @@ function SizeDrawer() {
/>
</Field>
</Box>
<Drawer.Trigger as={Button} state={drawerState}>
<Drawer.Trigger as={Button} store={drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop state={drawerState}>
<Drawer aria-label="Size drawer" state={drawerState} 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>
<Drawer
aria-label="Size drawer"
store={drawer}
size={size}
placement={placement}
hideOnInteractOutside={false}
>
Praesent sit amet quam ac velit faucibus dapibus. Quisque sapien ligula, rutrum quis aliquam
nec, convallis sit amet erat. Mauris auctor blandit porta.
</Drawer>
</>
)
}
Expand All @@ -206,61 +199,55 @@ All the elements can be styled as you see fit, by extending drawer's theme or di
```jsx
function StylingDrawer() {
const drawerState = useDrawerState()
const drawer = useDrawer()

return (
<>
<Drawer.Trigger as={Button} state={drawerState}>
<Drawer.Trigger as={Button} store={drawer}>
Open Drawer
</Drawer.Trigger>
<Drawer.Backdrop state={drawerState}>
<Drawer aria-label="Default drawer" state={drawerState} backgroundColor="nude-200">
<Drawer.Close state={drawerState} 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={drawerState.hide}>Save</Button>
<Button onClick={drawerState.hide} variant="tertiary">
Close
</Button>
</Stack>
</Drawer.Footer>
</Drawer>
</Drawer.Backdrop>
<Drawer
aria-label="Default drawer"
store={drawer}
backgroundColor="nude-200"
withCloseButton={false}
>
<Drawer.Close store={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>
</>
)
}
```
## useDrawerState
We use `useDialogState` from [Reakit Dialog](https://reakit.io/docs/dialog/#usedialogstate) for the state of the drawer with the `animated` flag set to `true` by default.
Pass options to `useDrawerState` :
We use `useDialogStore` from [Ariakit Dialog](https://ariakit.org/reference/use-dialog-store) for the state of the drawer with the `animated` flag set to `true` by default.
- `visible`: e.g. `const modal = useDrawerState({ visible: true })`
Pass options to `useDrawer` :
And the hook returns (among other things):
- `visible` : whether the drawer is currently visible
- `hide` : a function to hide the drawer
- `defaultOpen`: e.g. `const drawer = useDrawer({ defaultOpen: true })`
## Properties
### Drawer
<props propTypes={props.propTypes.Drawer} />
### Drawer.Backdrop
<props propTypes={props.propTypes['Drawer.Backdrop']} />
## Packages
### Dependencies
Expand Down
5 changes: 1 addition & 4 deletions packages/Core/src/theme/drawers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ export const getDrawers = (theme: WuiTheme): ThemeDrawers => {
default: {
zIndex: 999,
},
closeButton: {
marginRight: `${space.xl}`,
marginTop: `${space.xl}`,
},
closeButton: {},
title: {
margin: 0,
backgroundColor: colors['light-900'],
Expand Down
4 changes: 2 additions & 2 deletions packages/Drawer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@
"url": "https://github.com/WTTJ/welcome-ui/issues"
},
"dependencies": {
"@ariakit/react": "^0.2.12",
"@welcome-ui/box": "^5.0.0-alpha.40",
"@welcome-ui/close-button": "^5.0.0-alpha.40",
"@welcome-ui/system": "^5.0.0-alpha.40",
"@welcome-ui/text": "^5.0.0-alpha.40",
"@welcome-ui/utils": "^5.0.0-alpha.37",
"reakit": "^1.3.11"
"@welcome-ui/utils": "^5.0.0-alpha.37"
},
"peerDependencies": {
"@xstyled/styled-components": "^3.7.3",
Expand Down
30 changes: 30 additions & 0 deletions packages/Drawer/src/Close.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'
import * as Ariakit from '@ariakit/react'
import { CloseButtonProps } from '@welcome-ui/close-button'
import { useTheme } from '@xstyled/styled-components'
import { Box } from '@welcome-ui/box'

import * as S from './styles'

export type CloseProps = Ariakit.DialogDismissProps & CloseButtonProps

export const Close: React.FC<CloseProps> = ({ zIndex = '2', ...props }) => {
const theme = useTheme()

return (
<Box h="0">
<Ariakit.DialogDismiss
render={
<S.CloseButton
left={`calc(100% - ${theme.space.lg} - ${theme.buttons.sizes.sm.height})`}
mt="lg"
position="sticky"
top="0"
zIndex={zIndex}
{...props}
/>
}
/>
</Box>
)
}
8 changes: 8 additions & 0 deletions packages/Drawer/src/Content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react'
import { BoxProps } from '@welcome-ui/box'

import * as S from './styles'

export const Content: React.FC<BoxProps> = props => {
return <S.Content flex="1" overflowY={{ md: 'auto' }} {...props} />
}
15 changes: 15 additions & 0 deletions packages/Drawer/src/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import { BoxProps } from '@welcome-ui/box'

import * as S from './styles'

export const Footer: React.FC<BoxProps> = props => {
return (
<S.Footer
bottom={{ xs: 0, md: 'auto' }}
position={{ xs: 'sticky', md: 'static' }}
w="100%"
{...props}
/>
)
}
Loading

0 comments on commit 3d64b9d

Please sign in to comment.