Skip to content

Commit

Permalink
feat: added drawer component (#20)
Browse files Browse the repository at this point in the history
* feat: added drawer component

* chore: review updates

* chore: minor updates

* chore: remove unused import
  • Loading branch information
anuraghazra authored Sep 8, 2020
1 parent 92329b2 commit f25f99c
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/drawer/Drawer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { createHook, createComponent } from "reakit-system";
import { useDialog, DialogOptions, DialogHTMLProps } from "reakit";
import { DRAWER_KEYS } from "./__keys";

const PLACEMENTS = {
left: {
left: 0,
top: 0,
bottom: 0,
height: "100vh",
},
right: {
right: 0,
top: 0,
bottom: 0,
height: "100vh",
},
top: {
right: 0,
left: 0,
top: 0,
width: "100vw",
},
bottom: {
right: 0,
left: 0,
bottom: 0,
width: "100vw",
},
};

export type TPlacement = keyof typeof PLACEMENTS;

const useDrawer = createHook<
DialogOptions & { placement?: TPlacement },
DialogHTMLProps
>({
name: "Drawer",
compose: [useDialog],
keys: [...DRAWER_KEYS, "placement"],
useProps({ placement = "left" }, { style: htmlStyles, ...htmlProps }) {
return {
style: {
...PLACEMENTS[placement],
position: "fixed",
htmlStyles,
},
...htmlProps,
};
},
});

export const Drawer = createComponent({
as: "div",
useHook: useDrawer,
});
25 changes: 25 additions & 0 deletions src/drawer/DrawerCloseButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createHook, createComponent } from "reakit-system";
import { useButton, DialogStateReturn, ButtonProps } from "reakit";
import { callAllHandlers } from "@chakra-ui/utils";
import { DRAWER_KEYS } from "./__keys";

export const useDrawerCloseButton = createHook<
Pick<DialogStateReturn, "hide">,
ButtonProps
>({
name: "DrawerCloseButton",
compose: useButton,
keys: [...DRAWER_KEYS, "hide"],

useProps({ hide }, { onClick: htmlOnClick, ...htmlProps }) {
return {
onClick: callAllHandlers(hide, htmlOnClick),
...htmlProps,
};
},
});

export const DrawerCloseButton = createComponent({
as: "button",
useHook: useDrawerCloseButton,
});
30 changes: 30 additions & 0 deletions src/drawer/__keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const DRAWER_STATE_KEYS = [
"baseId",
"unstable_idCountRef",
"visible",
"animated",
"animating",
"setBaseId",
"show",
"hide",
"toggle",
"setVisible",
"setAnimated",
"stopAnimation",
"modal",
"unstable_disclosureRef",
"setModal",
] as const;
export const DRAWER_KEYS = [
...DRAWER_STATE_KEYS,
"hideOnEsc",
"hideOnClickOutside",
"preventBodyScroll",
"unstable_initialFocusRef",
"unstable_finalFocusRef",
"unstable_orphan",
"unstable_autoFocusOnShow",
"unstable_autoFocusOnHide",
] as const;
export const DRAWER_BACKDROP_KEYS = DRAWER_STATE_KEYS;
export const DRAWER_DISCLOSURE_KEYS = DRAWER_BACKDROP_KEYS;
9 changes: 9 additions & 0 deletions src/drawer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export * from "./Drawer";
export * from "./DrawerCloseButton";
export {
useDialogState as useDrawerState,
DialogBackdrop as DrawerBackdrop,
useDialogBackdrop as useDrawerBackdrop,
DialogDisclosure as DrawerDisclosure,
useDialogDisclosure as useDrawerDisclosure,
} from "reakit/Dialog";
79 changes: 79 additions & 0 deletions src/drawer/stories/Drawer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from "react";
import { css } from "emotion";
import { Meta } from "@storybook/react";
import {
Drawer,
TPlacement,
useDrawerState,
DrawerBackdrop,
DrawerCloseButton,
DrawerDisclosure,
} from "../";

export default {
title: "Component/Drawer",
} as Meta;

const backdropStyles = css`
opacity: 0;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
transition: opacity 250ms ease-in-out;
background-color: rgba(0, 0, 0, 0.2);
&[data-enter] {
opacity: 1;
}
`;

const cssTransforms = {
top: "translate(0, -200px)",
bottom: "translate(0, 200px)",
left: "translate(-200px, 0)",
right: "translate(200px, 0)",
};

export const Default = () => {
const dialog = useDrawerState({ animated: true });
const inputRef = React.useRef<HTMLInputElement | null>(null);
const [placement, setPlacement] = React.useState<TPlacement>("left");

return (
<div>
<DrawerDisclosure {...dialog}>Open Drawer</DrawerDisclosure>
<select onBlur={e => setPlacement(e.target.value as TPlacement)}>
<option value="top">Top</option>
<option value="bottom">Bottom</option>
<option value="right">Right</option>
<option selected value="left">
Left
</option>
</select>
<DrawerBackdrop className={backdropStyles} {...dialog}>
<Drawer
{...dialog}
placement={placement}
aria-label="Hello world"
className={css`
opacity: 0;
padding: 10px;
background-color: white;
transition: 250ms ease-in-out;
transform: ${cssTransforms[placement]};
&[data-enter] {
opacity: 1;
transform: translate(0, 0);
}
`}
unstable_initialFocusRef={inputRef}
>
<DrawerCloseButton {...dialog}>X</DrawerCloseButton>
<p>Welcome to Reakit!</p>
<input ref={inputRef} />
</Drawer>
</DrawerBackdrop>
</div>
);
};

0 comments on commit f25f99c

Please sign in to comment.