Feat: Drawer component
thmsmtylr opened this issue · 1 comments
thmsmtylr commented
I've created a Drawer
component based off of the Radix Dialog
component something I think the Radix library is missing. Do you have any interest in adding this component? Here's a rough sketch of how it would look:
drawer.tsx:
import { Transition } from "@headlessui/react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { Cross1Icon } from "@radix-ui/react-icons";
import { clsx } from "clsx";
import React, { Fragment } from "react";
import Button from "./shared/button";
type Position = "left" | "right";
export interface DrawerProps {
title?: string;
description?: string;
position?: Position;
isOpen: boolean;
onOpenChange: () => void;
}
const Drawer = (props: DrawerProps) => {
const {
title = "Drawer",
position = "right",
description,
isOpen,
onOpenChange,
} = props;
return (
<DialogPrimitive.Root open={isOpen} onOpenChange={onOpenChange}>
<DialogPrimitive.Portal forceMount>
<Transition.Root show={isOpen}>
<Transition.Child
as={Fragment}
enter="ease-in-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in-out duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<DialogPrimitive.Overlay className="fixed inset-0 bg-black/50" />
</Transition.Child>
<Transition.Child
as={Fragment}
enter="transform transition ease-in-out duration-300"
enterFrom="translate-x-full"
enterTo="translate-x-0"
leave="transform transition ease-in-out duration-300"
leaveFrom="translate-x-0"
leaveTo="translate-x-full"
>
<DialogPrimitive.Content
forceMount
className={clsx(
position === "right" ? "right-0" : "left-0",
"fixed top-0 flex h-full w-screen max-w-md flex-col overflow-y-scroll bg-gray-800 py-6 shadow-xl"
)}
>
<DialogPrimitive.Title className="mb-2 px-4 text-sm font-medium text-gray-900 dark:text-gray-100">
{title}
</DialogPrimitive.Title>
{description && (
<DialogPrimitive.Description className="px-4 text-sm font-normal text-gray-700 dark:text-gray-400">
{description}
</DialogPrimitive.Description>
)}
<div className="mt-[25px] flex justify-end px-4">
<DialogPrimitive.Close
className={clsx(
"inline-flex select-none justify-center rounded-md px-4 py-2 text-sm font-medium",
"bg-purple-600 text-white hover:bg-purple-700 dark:bg-purple-700 dark:text-gray-100 dark:hover:bg-purple-600",
"border border-transparent",
"focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75"
)}
>
Save changes
</DialogPrimitive.Close>
</div>
<DialogPrimitive.Close className="absolute top-6 right-3.5 inline-flex items-center justify-center rounded-full p-1 focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75">
<Cross1Icon className="h-4 w-4 text-gray-500 hover:text-gray-700 dark:text-gray-500 dark:hover:text-gray-400" />
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</Transition.Child>
</Transition.Root>
</DialogPrimitive.Portal>
</DialogPrimitive.Root>
);
};
export { Drawer };
index.tsx:
const DrawerWithState = () => {
const [drawerOpen, setDrawerOpen] = useState<boolean>(false);
const handleDrawerToggle = () => {
setDrawerOpen(!drawerOpen);
};
return (
<>
<Button onClick={handleDrawerToggle}>Click</Button>
<Drawer
isOpen={drawerOpen}
onOpenChange={handleDrawerToggle}
description="Navigation drawers provide access to destinations in your app. Side sheets are surfaces containing supplementary content that are anchored to the left or right edge of the screen."
/>
</>
);
};
{
label: "Drawer",
link: `${REPO_URL}/components/drawer.tsx`,
component: <DrawerWithState />,
},
I have the changes on a PR locally. I'd very much like to contribute to your library moving forward 👍 . Please let me know your thoughts and feedback? Thanks!
ecklf commented
Much appreciated, but I'll stick to the official Radix primitives for the demo. We have things like shadcn/ui
now, which is a fully built collection of components.