From a456c8a689afd64158fd25aace17d1fe56f30ac9 Mon Sep 17 00:00:00 2001 From: areski Date: Mon, 13 Mar 2023 13:51:04 +0100 Subject: [PATCH 01/91] feat(drawer): wip implementation --- src/docs/routes.tsx | 13 ++++++++ src/lib/components/Flowbite/FlowbiteTheme.ts | 9 ++++++ src/lib/components/index.ts | 1 + src/lib/theme/default.ts | 33 ++++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/src/docs/routes.tsx b/src/docs/routes.tsx index be0717715..3a65ca413 100644 --- a/src/docs/routes.tsx +++ b/src/docs/routes.tsx @@ -16,6 +16,7 @@ import { HiDeviceTablet, HiDuplicate, HiHome, + HiLogout, HiMinus, HiOutlineChevronDoubleRight, HiOutlineClock, @@ -35,6 +36,7 @@ import ButtonsPage from './pages/ButtonsPage'; import CardPage from './pages/CardPage'; import CarouselPage from './pages/CarouselPage'; import DashboardPage from './pages/DashboardPage'; +import DrawerPage from './pages/DrawerPage'; import DropdownPage from './pages/DropdownPage'; import FooterPage from './pages/FooterPage'; import FormsPage from './pages/FormsPage'; @@ -229,6 +231,17 @@ export const routes: RouteProps[] = [ images: { light: 'modal-light.svg', dark: 'modal-dark.svg' }, }, }, + { + title: 'Drawer', + icon: HiLogout, + href: '/drawer', + component: , + group: false, + card: { + className: 'w-36', + images: { light: 'drawer-light.svg', dark: 'drawer-dark.svg' }, + }, + }, { title: 'Navbars', icon: FiNavigation, diff --git a/src/lib/components/Flowbite/FlowbiteTheme.ts b/src/lib/components/Flowbite/FlowbiteTheme.ts index 42bb2aca6..f758093b2 100644 --- a/src/lib/components/Flowbite/FlowbiteTheme.ts +++ b/src/lib/components/Flowbite/FlowbiteTheme.ts @@ -9,6 +9,7 @@ import type { FlowbiteCardTheme } from '../Card'; import type { FlowbiteCarouselTheme } from '../Carousel'; import type { FlowbiteCheckboxTheme } from '../Checkbox'; import type { FlowbiteDarkThemeToggleTheme } from '../DarkThemeToggle'; +import type { FlowbiteDrawerTheme } from '../Drawer'; import type { FlowbiteDropdownTheme } from '../Dropdown'; import type { FlowbiteFileInputTheme } from '../FileInput'; import type { FlowbiteFooterTheme } from '../Footer'; @@ -50,6 +51,7 @@ export interface FlowbiteTheme { footer: FlowbiteFooterTheme; listGroup: FlowbiteListGroupTheme; modal: FlowbiteModalTheme; + drawer: FlowbiteDrawerTheme; navbar: FlowbiteNavbarTheme; rating: FlowbiteRatingTheme; pagination: FlowbitePaginationTheme; @@ -136,6 +138,13 @@ export interface FlowbitePositions { 'center-right': string; } +export interface FlowbitePlacements { + left: string; + right: string; + top: string; + bottom: string; +} + export interface FlowbiteSizes { xs: string; sm: string; diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index 3409b5103..7dfe0430f 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -8,6 +8,7 @@ export * from './Card'; export * from './Carousel'; export * from './Checkbox'; export * from './DarkThemeToggle/DarkThemeToggle'; +export * from './Drawer'; export * from './Dropdown'; export * from './FileInput'; export * from './Flowbite'; diff --git a/src/lib/theme/default.ts b/src/lib/theme/default.ts index 875971429..7e86b4e37 100644 --- a/src/lib/theme/default.ts +++ b/src/lib/theme/default.ts @@ -562,6 +562,39 @@ const theme: FlowbiteTheme = { popup: 'border-t', }, }, + drawer: { + root: { + // base: 'fixed top-0 right-0 left-0 z-50 h-modal overflow-y-auto overflow-x-hidden md:inset-0 md:h-full', + base: 'fixed top-0 left-0 z-40 h-screen p-0 overflow-y-auto bg-white w-80 dark:bg-gray-800 shadow', + show: { + on: 'overflow-x-hidden ', + off: '-translate-x-full overflow-x-hidden transition-transform', + }, + placements: { + left: 'items-center justify-start', + right: 'items-start justify-center', + top: 'items-start justify-start', + bottom: 'items-end justify-end', + }, + }, + content: { + // base: 'relative h-full w-full p-4 md:h-auto', + // inner: 'relative rounded-lg bg-white shadow dark:bg-gray-700', + base: 'relative', + inner: 'relative', + }, + body: { + base: 'px-5', + }, + header: { + base: 'flex items-start justify-between rounded-t p-5', + title: 'text-xl font-medium text-gray-600 dark:text-white', + close: { + base: 'ml-auto inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 dark:hover:bg-gray-600 dark:hover:text-white', + icon: 'h-5 w-5', + }, + }, + }, navbar: { root: { base: 'border-gray-200 bg-white px-2 py-2.5 dark:border-gray-700 dark:bg-gray-800 sm:px-4', From c6785be84b7f3968c59867393c46e6b62343d46b Mon Sep 17 00:00:00 2001 From: areski Date: Mon, 13 Mar 2023 13:53:38 +0100 Subject: [PATCH 02/91] feat(drawer): wip implementation --- src/docs/pages/DrawerPage.tsx | 186 +++++++++++++++++++ src/lib/components/Drawer/Drawer.spec.tsx | 165 ++++++++++++++++ src/lib/components/Drawer/Drawer.stories.tsx | 138 ++++++++++++++ src/lib/components/Drawer/Drawer.tsx | 130 +++++++++++++ src/lib/components/Drawer/DrawerBody.tsx | 23 +++ src/lib/components/Drawer/DrawerContext.tsx | 17 ++ src/lib/components/Drawer/DrawerHeader.tsx | 41 ++++ src/lib/components/Drawer/index.ts | 3 + 8 files changed, 703 insertions(+) create mode 100644 src/docs/pages/DrawerPage.tsx create mode 100644 src/lib/components/Drawer/Drawer.spec.tsx create mode 100644 src/lib/components/Drawer/Drawer.stories.tsx create mode 100644 src/lib/components/Drawer/Drawer.tsx create mode 100644 src/lib/components/Drawer/DrawerBody.tsx create mode 100644 src/lib/components/Drawer/DrawerContext.tsx create mode 100644 src/lib/components/Drawer/DrawerHeader.tsx create mode 100644 src/lib/components/Drawer/index.ts diff --git a/src/docs/pages/DrawerPage.tsx b/src/docs/pages/DrawerPage.tsx new file mode 100644 index 000000000..2f83d08a8 --- /dev/null +++ b/src/docs/pages/DrawerPage.tsx @@ -0,0 +1,186 @@ +import type { FC } from 'react'; +import { useState } from 'react'; +import { HiOutlineExclamationCircle } from 'react-icons/hi'; +import { Button, Drawer } from '../../lib'; +import { Checkbox } from '../../lib/components/Checkbox'; +import { Label } from '../../lib/components/Label'; +import { Select } from '../../lib/components/Select'; +import { TextInput } from '../../lib/components/TextInput'; +import type { CodeExample } from './DemoPage'; +import { DemoPage } from './DemoPage'; + +const DrawerPage: FC = () => { + const [openDrawer, setOpenDrawer] = useState(); + const [drawerPlacement, setDrawerPlacement] = useState('left'); + + const examples: CodeExample[] = [ + { + title: 'Default drawer', + code: ( + <> + + setOpenDrawer(undefined)}> + Terms of Service + +
+

+ With less than a month to go before the European Union enacts new consumer privacy laws for its + citizens, companies around the world are updating their terms of service agreements to comply. +

+

+ The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is + meant to ensure a common set of data rights in the European Union. It requires organizations to notify + users as soon as possible of high-risk data breaches that could personally affect them. +

+
+
+
+ + ), + }, + { + title: 'Dismissable drawer', + code: ( + <> + + setOpenDrawer(undefined)}> + Terms of Service + +
+

+ With less than a month to go before the European Union enacts new consumer privacy laws for its + citizens, companies around the world are updating their terms of service agreements to comply. +

+

+ The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is + meant to ensure a common set of data rights in the European Union. It requires organizations to notify + users as soon as possible of high-risk data breaches that could personally affect them. +

+
+
+
+ + ), + }, + { + title: 'Pop-up drawer', + code: ( + <> + + setOpenDrawer(undefined)}> + + +
+ +

+ Are you sure you want to delete this product? +

+
+ + +
+
+
+
+ + ), + }, + { + title: 'Form elements', + code: ( + <> + + setOpenDrawer(undefined)}> + + +
+

Sign in to our platform

+
+
+
+ +
+
+
+
+ +
+
+
+ + +
+ + Lost Password? + +
+
+ +
+
+ Not registered?  + + Create account + +
+
+
+
+ + ), + }, + { + title: 'Placement', + code: ( + <> +
+
+ +
+ +
+ setOpenDrawer(undefined)} + > + Small drawer + +
+

+ With less than a month to go before the European Union enacts new consumer privacy laws for its + citizens, companies around the world are updating their terms of service agreements to comply. +

+

+ The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is + meant to ensure a common set of data rights in the European Union. It requires organizations to notify + users as soon as possible of high-risk data breaches that could personally affect them. +

+
+
+
+ + ), + }, + ]; + + return ; +}; + +export default DrawerPage; diff --git a/src/lib/components/Drawer/Drawer.spec.tsx b/src/lib/components/Drawer/Drawer.spec.tsx new file mode 100644 index 000000000..f9b1cb4a5 --- /dev/null +++ b/src/lib/components/Drawer/Drawer.spec.tsx @@ -0,0 +1,165 @@ +import { render, screen, waitFor, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { useCallback, useState } from 'react'; +import { describe, expect, it } from 'vitest'; +import { Button } from '../Button'; +import { TextInput } from '../TextInput'; +import type { DrawerProps } from './Drawer'; +import { Drawer } from './Drawer'; + +describe('Components / Drawer', () => { + it('should automatically focus the `TextInput` inside the `Drawer` when its opened', async () => { + const root = document.createElement('div'); + const user = userEvent.setup(); + + render(); + + const openButton = screen.getByRole('button'); + + await user.click(openButton); + + const drawer = within(root).getByRole('dialog'); + const input = within(drawer).getByTestId('text-input'); + + waitFor(() => expect(input).toHaveFocus()); + }); + + it('should be removed from DOM and garbage collected', async () => { + const root = document.createElement('div'); + + const { unmount } = render(); + + unmount(); + + await waitFor(() => expect(root.childNodes.length).toBe(0)); + }); + + it('should be closed by clicking outside if the "dismissible" prop is passed.', async () => { + const root = document.createElement('div'); + const user = userEvent.setup(); + + render(); + + const openButton = screen.getByRole('button'); + + await user.click(openButton); + + const drawer = within(root).getByRole('dialog'); + + expect(drawer).toHaveAttribute('aria-hidden', 'false'); + + await user.click(drawer); + + expect(drawer).toHaveAttribute('aria-hidden', 'true'); + }); + + it('should be closed by Esc key press.', async () => { + const root = document.createElement('div'); + const user = userEvent.setup(); + + render(); + + const openButton = screen.getByRole('button'); + + await user.click(openButton); + + const drawer = within(root).getByRole('dialog'); + + expect(drawer).toHaveAttribute('aria-hidden', 'false'); + + await user.keyboard('[Escape]'); + + expect(drawer).toHaveAttribute('aria-hidden', 'true'); + }); + + describe('A11y', () => { + it('should have `role="dialog"`', async () => { + const user = userEvent.setup(); + const root = document.createElement('div'); + + render(); + + const openButton = screen.getByRole('button'); + + await user.click(openButton); + + const drawer = within(root).getByRole('dialog'); + + expect(drawer).toBeDefined(); + }); + }); + + describe('Keyboard interactions', () => { + it('should open `Drawer` when `Space` is pressed on its toggle button', async () => { + const root = document.createElement('div'); + const user = userEvent.setup(); + + render(); + + const openButton = screen.getByRole('button'); + + await user.click(openButton); + + const drawer = within(root).getByRole('dialog'); + + expect(root).toContainElement(drawer); + expect(drawer).toHaveAttribute('aria-hidden', 'false'); + }); + + it('should close `Drawer` when `Space` is pressed on any of its buttons', async () => { + const root = document.createElement('div'); + const user = userEvent.setup(); + + render(); + + const openButton = screen.getByRole('button'); + + await user.click(openButton); + + const drawer = within(root).getByRole('dialog'); + const closeButton = within(drawer).getAllByRole('button')[0]; + + expect(drawer).toHaveAttribute('aria-hidden', 'false'); + + await user.click(closeButton); + + expect(drawer).toHaveAttribute('aria-hidden', 'true'); + }); + }); +}); + +const TestDrawer = ({ root, dismissible = false }: Pick): JSX.Element => { + const [open, setOpen] = useState(false); + + const setInputRef = useCallback( + (input: HTMLInputElement) => { + if (open && input) { + input.focus(); + } + }, + [open], + ); + + return ( + <> + + setOpen(false)}> + Terms of Service + +
+

+ With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, + companies around the world are updating their terms of service agreements to comply. +

+

+ The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant + to ensure a common set of data rights in the European Union. It requires organizations to notify users as + soon as possible of high-risk data breaches that could personally affect them. +

+
+ +
+
+ + ); +}; diff --git a/src/lib/components/Drawer/Drawer.stories.tsx b/src/lib/components/Drawer/Drawer.stories.tsx new file mode 100644 index 000000000..c9768033a --- /dev/null +++ b/src/lib/components/Drawer/Drawer.stories.tsx @@ -0,0 +1,138 @@ +import { action } from '@storybook/addon-actions'; +import type { Meta, Story } from '@storybook/react/types-6-0'; +import { HiOutlineExclamationCircle } from 'react-icons/hi'; +import { Button } from '../Button'; +import { Checkbox } from '../Checkbox'; +import { Label } from '../Label'; +import { TextInput } from '../TextInput'; +import type { DrawerProps } from './Drawer'; +import { Drawer } from './Drawer'; + +export default { + title: 'Components/Drawer', + component: Drawer, + args: { + show: false, + }, +} as Meta; + +const Template: Story = ({ children, ...rest }): JSX.Element => { + return ( + <> + + + {children} + + + ); +}; + +export const Default = Template.bind({}); +Default.args = { + children: ( + <> + Info + +
+ With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, + companies around the world are updating their terms of service agreements to comply. +
+ +
+ + ), +}; + +export const PopUp = Template.bind({}); +PopUp.storyName = 'Pop-up drawer'; +PopUp.args = { + children: ( + +
+ +

+ Are you sure you want to delete this product? +

+
+ + +
+
+
+ ), +}; + +export const FormElements = Template.bind({}); +FormElements.storyName = 'Form elements'; +FormElements.args = { + children: ( + <> + + +
+

Sign in to our platform

+
+
+
+ +
+
+
+
+ +
+
+
+ + +
+ + Lost Password? + +
+
+ +
+
+ Not registered?  + + Create account + +
+
+
+ + ), +}; diff --git a/src/lib/components/Drawer/Drawer.tsx b/src/lib/components/Drawer/Drawer.tsx new file mode 100644 index 000000000..71ddae3ad --- /dev/null +++ b/src/lib/components/Drawer/Drawer.tsx @@ -0,0 +1,130 @@ +import classNames from 'classnames'; +import type { ComponentProps, FC, MouseEvent, PropsWithChildren } from 'react'; +import { useEffect, useRef } from 'react'; +import { createPortal } from 'react-dom'; +import type { DeepPartial } from '..'; +import { mergeDeep } from '../../helpers/mergeDeep'; +import windowExists from '../../helpers/window-exists'; +import { useKeyDown } from '../../hooks'; +import type { FlowbiteBoolean, FlowbitePlacements } from '../Flowbite/FlowbiteTheme'; +import { useTheme } from '../Flowbite/ThemeContext'; +import type { FlowbiteDrawerBodyTheme } from './DrawerBody'; +import { DrawerBody } from './DrawerBody'; +import { DrawerContext } from './DrawerContext'; +import type { FlowbiteDrawerHeaderTheme } from './DrawerHeader'; +import { DrawerHeader } from './DrawerHeader'; + +export interface FlowbiteDrawerTheme { + root: FlowbiteDrawerRootTheme; + content: FlowbiteDrawerContentTheme; + body: FlowbiteDrawerBodyTheme; + header: FlowbiteDrawerHeaderTheme; +} + +export interface FlowbiteDrawerRootTheme { + base: string; + show: FlowbiteBoolean; + placements: DrawerPlacements; +} + +export interface FlowbiteDrawerContentTheme { + base: string; + inner: string; +} + +export interface DrawerPlacements extends FlowbitePlacements { + [key: string]: string; +} + +export interface DrawerProps extends PropsWithChildren> { + onClose?: () => void; + placement?: keyof DrawerPlacements; + root?: HTMLElement; + show?: boolean; + dismissible?: boolean; + theme?: DeepPartial; +} + +const DrawerComponent: FC = ({ + children, + className, + dismissible = false, + onClose, + placement = 'left', + root, + show, + theme: customTheme = {}, + ...props +}) => { + const theme = mergeDeep(useTheme().theme.drawer, customTheme); + + // Declare a ref to store a reference to a div element. + const containerRef = useRef(null); + + // If the current value of the ref is falsy (e.g. null), set it to a new div + // element. + if (!containerRef.current) { + containerRef.current = document.createElement('div'); + } + + // If the current value of the ref is not already a child of the root element, + // append it or replace its parent. + if (containerRef.current.parentNode !== root && windowExists()) { + root = root || document.body; + root.appendChild(containerRef.current); + } + + useEffect(() => { + return () => { + const container = containerRef.current; + + // If a container exists on unmount, it is removed from the DOM and + // garbage collected. + if (container) { + container.parentNode?.removeChild(container); + containerRef.current = null; + } + }; + }, []); + + useKeyDown('Escape', () => { + if (dismissible && onClose) { + onClose(); + } + }); + + const handleOnClick = (e: MouseEvent) => { + if (dismissible && e.target === e.currentTarget && onClose) { + onClose(); + } + }; + + return createPortal( + +
+
+
{children}
+
+
+
, + containerRef.current, + ); +}; + +DrawerComponent.displayName = 'Drawer'; +DrawerHeader.displayName = 'Drawer.Header'; +DrawerBody.displayName = 'Drawer.Body'; + +export const Drawer = Object.assign(DrawerComponent, { Header: DrawerHeader, Body: DrawerBody }); diff --git a/src/lib/components/Drawer/DrawerBody.tsx b/src/lib/components/Drawer/DrawerBody.tsx new file mode 100644 index 000000000..ab2140523 --- /dev/null +++ b/src/lib/components/Drawer/DrawerBody.tsx @@ -0,0 +1,23 @@ +import classNames from 'classnames'; +import type { ComponentProps, FC, PropsWithChildren } from 'react'; +import type { DeepPartial } from '..'; +import { mergeDeep } from '../../helpers/mergeDeep'; +import { useTheme } from '../Flowbite/ThemeContext'; + +export interface FlowbiteDrawerBodyTheme { + base: string; +} + +export interface DrawerBodyProps extends PropsWithChildren> { + theme?: DeepPartial; +} + +export const DrawerBody: FC = ({ children, className, theme: customTheme = {}, ...props }) => { + const theme = mergeDeep(useTheme().theme.drawer.body, customTheme); + + return ( +
+ {children} +
+ ); +}; diff --git a/src/lib/components/Drawer/DrawerContext.tsx b/src/lib/components/Drawer/DrawerContext.tsx new file mode 100644 index 000000000..917e767a8 --- /dev/null +++ b/src/lib/components/Drawer/DrawerContext.tsx @@ -0,0 +1,17 @@ +import { createContext, useContext } from 'react'; + +type DrawerContext = { + onClose?: () => void; +}; + +export const DrawerContext = createContext(undefined); + +export function useDrawerContext(): DrawerContext { + const context = useContext(DrawerContext); + + if (!context) { + throw new Error('useDrawerContext should be used within the DrawerContext provider!'); + } + + return context; +} diff --git a/src/lib/components/Drawer/DrawerHeader.tsx b/src/lib/components/Drawer/DrawerHeader.tsx new file mode 100644 index 000000000..80701c0ba --- /dev/null +++ b/src/lib/components/Drawer/DrawerHeader.tsx @@ -0,0 +1,41 @@ +import classNames from 'classnames'; +import type { ComponentProps, ElementType, FC, PropsWithChildren } from 'react'; +import { HiOutlineX } from 'react-icons/hi'; +import type { DeepPartial } from '..'; +import { mergeDeep } from '../../helpers/mergeDeep'; +import { useTheme } from '../Flowbite/ThemeContext'; +import { useDrawerContext } from './DrawerContext'; + +export interface FlowbiteDrawerHeaderTheme { + base: string; + title: string; + close: { + base: string; + icon: string; + }; +} + +export interface DrawerHeaderProps extends PropsWithChildren> { + as?: ElementType; + theme?: DeepPartial; +} + +export const DrawerHeader: FC = ({ + as: Component = 'h3', + children, + className, + theme: customTheme = {}, + ...props +}) => { + const theme = mergeDeep(useTheme().theme.drawer.header, customTheme); + const { onClose } = useDrawerContext(); + + return ( +
+ {children} + +
+ ); +}; diff --git a/src/lib/components/Drawer/index.ts b/src/lib/components/Drawer/index.ts new file mode 100644 index 000000000..9765740b8 --- /dev/null +++ b/src/lib/components/Drawer/index.ts @@ -0,0 +1,3 @@ +export * from './Drawer'; +export type { DrawerBodyProps } from './DrawerBody'; +export type { DrawerHeaderProps } from './DrawerHeader'; From 9ca0601f0d8a387298f14906e4edaee09cc8f969 Mon Sep 17 00:00:00 2001 From: areski Date: Mon, 13 Mar 2023 16:19:14 +0100 Subject: [PATCH 03/91] feat(drawer): continue wip on placement --- src/docs/pages/DrawerPage.tsx | 82 +++++++++++++++----- src/lib/components/Drawer/Drawer.tsx | 8 +- src/lib/components/Flowbite/FlowbiteTheme.ts | 8 +- src/lib/theme/default.ts | 24 ++++-- 4 files changed, 86 insertions(+), 36 deletions(-) diff --git a/src/docs/pages/DrawerPage.tsx b/src/docs/pages/DrawerPage.tsx index 2f83d08a8..fff017859 100644 --- a/src/docs/pages/DrawerPage.tsx +++ b/src/docs/pages/DrawerPage.tsx @@ -38,23 +38,70 @@ const DrawerPage: FC = () => { ), }, + { + title: 'Drawer Navigation', + code: ( + <> + + setOpenDrawer(undefined)}> + Menu + + + + + + ), + }, { title: 'Dismissable drawer', code: ( <> - - setOpenDrawer(undefined)}> - Terms of Service + + setOpenDrawer(undefined)}> + Dismissable

- With less than a month to go before the European Union enacts new consumer privacy laws for its - citizens, companies around the world are updating their terms of service agreements to comply. -

-

- The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is - meant to ensure a common set of data rights in the European Union. It requires organizations to notify - users as soon as possible of high-risk data breaches that could personally affect them. + Incididunt cupidatat ut minim ea deserunt aute aliqua et adipisicing minim id. Amet esse dolore ipsum nostrud irure nostrud ipsum. Velit irure anim occaecat duis deserunt do ut.

@@ -141,16 +188,11 @@ const DrawerPage: FC = () => { <>
- setDrawerPlacement(event.target.value)}> + + + +
diff --git a/src/lib/components/Drawer/Drawer.tsx b/src/lib/components/Drawer/Drawer.tsx index 71ddae3ad..0c3a96524 100644 --- a/src/lib/components/Drawer/Drawer.tsx +++ b/src/lib/components/Drawer/Drawer.tsx @@ -23,7 +23,6 @@ export interface FlowbiteDrawerTheme { export interface FlowbiteDrawerRootTheme { base: string; - show: FlowbiteBoolean; placements: DrawerPlacements; } @@ -33,7 +32,7 @@ export interface FlowbiteDrawerContentTheme { } export interface DrawerPlacements extends FlowbitePlacements { - [key: string]: string; + [key: string]: FlowbiteBoolean; } export interface DrawerProps extends PropsWithChildren> { @@ -94,6 +93,8 @@ const DrawerComponent: FC = ({ }); const handleOnClick = (e: MouseEvent) => { + console.log("...handleOnClick") + console.log("dismissible:", dismissible) if (dismissible && e.target === e.currentTarget && onClose) { onClose(); } @@ -108,8 +109,7 @@ const DrawerComponent: FC = ({ role="dialog" className={classNames( theme.root.base, - theme.root.placements[placement], - show ? theme.root.show.on : theme.root.show.off, + show ? theme.root.placements[placement].on : theme.root.placements[placement].off, className, )} {...props} diff --git a/src/lib/components/Flowbite/FlowbiteTheme.ts b/src/lib/components/Flowbite/FlowbiteTheme.ts index f758093b2..84ceacf0e 100644 --- a/src/lib/components/Flowbite/FlowbiteTheme.ts +++ b/src/lib/components/Flowbite/FlowbiteTheme.ts @@ -139,10 +139,10 @@ export interface FlowbitePositions { } export interface FlowbitePlacements { - left: string; - right: string; - top: string; - bottom: string; + left: {on: string, off: string}; + right: {on: string, off: string}; + top: {on: string, off: string}; + bottom: {on: string, off: string}; } export interface FlowbiteSizes { diff --git a/src/lib/theme/default.ts b/src/lib/theme/default.ts index 7e86b4e37..2faa6fd4e 100644 --- a/src/lib/theme/default.ts +++ b/src/lib/theme/default.ts @@ -566,15 +566,23 @@ const theme: FlowbiteTheme = { root: { // base: 'fixed top-0 right-0 left-0 z-50 h-modal overflow-y-auto overflow-x-hidden md:inset-0 md:h-full', base: 'fixed top-0 left-0 z-40 h-screen p-0 overflow-y-auto bg-white w-80 dark:bg-gray-800 shadow', - show: { - on: 'overflow-x-hidden ', - off: '-translate-x-full overflow-x-hidden transition-transform', - }, placements: { - left: 'items-center justify-start', - right: 'items-start justify-center', - top: 'items-start justify-start', - bottom: 'items-end justify-end', + left: { + on: 'overflow-x-hidden ', + off: '-translate-x-full overflow-x-hidden transition-transform', + }, + right: { + on: 'overflow-x-hidden ', + off: '-translate-x-full overflow-x-hidden transition-transform', + }, + top: { + on: 'overflow-x-hidden ', + off: '-translate-x-full overflow-x-hidden transition-transform', + }, + bottom: { + on: 'overflow-x-hidden ', + off: '-translate-x-full overflow-x-hidden transition-transform', + }, }, }, content: { From e10c7643e72cd4365ca9c602cb316434e32efdad Mon Sep 17 00:00:00 2001 From: areski Date: Mon, 13 Mar 2023 16:23:03 +0100 Subject: [PATCH 04/91] feat(drawer): wip implementation --- src/docs/pages/DrawerPage.tsx | 138 ++++++++++++++----- src/lib/components/Drawer/Drawer.tsx | 4 +- src/lib/components/Flowbite/FlowbiteTheme.ts | 8 +- 3 files changed, 113 insertions(+), 37 deletions(-) diff --git a/src/docs/pages/DrawerPage.tsx b/src/docs/pages/DrawerPage.tsx index fff017859..a64e26f10 100644 --- a/src/docs/pages/DrawerPage.tsx +++ b/src/docs/pages/DrawerPage.tsx @@ -48,42 +48,117 @@ const DrawerPage: FC = () => { @@ -101,7 +176,8 @@ const DrawerPage: FC = () => {

- Incididunt cupidatat ut minim ea deserunt aute aliqua et adipisicing minim id. Amet esse dolore ipsum nostrud irure nostrud ipsum. Velit irure anim occaecat duis deserunt do ut. + Incididunt cupidatat ut minim ea deserunt aute aliqua et adipisicing minim id. Amet esse dolore ipsum + nostrud irure nostrud ipsum. Velit irure anim occaecat duis deserunt do ut.

diff --git a/src/lib/components/Drawer/Drawer.tsx b/src/lib/components/Drawer/Drawer.tsx index 0c3a96524..97cf1bbd0 100644 --- a/src/lib/components/Drawer/Drawer.tsx +++ b/src/lib/components/Drawer/Drawer.tsx @@ -93,8 +93,8 @@ const DrawerComponent: FC = ({ }); const handleOnClick = (e: MouseEvent) => { - console.log("...handleOnClick") - console.log("dismissible:", dismissible) + console.log('...handleOnClick'); + console.log('dismissible:', dismissible); if (dismissible && e.target === e.currentTarget && onClose) { onClose(); } diff --git a/src/lib/components/Flowbite/FlowbiteTheme.ts b/src/lib/components/Flowbite/FlowbiteTheme.ts index 84ceacf0e..1d309eff0 100644 --- a/src/lib/components/Flowbite/FlowbiteTheme.ts +++ b/src/lib/components/Flowbite/FlowbiteTheme.ts @@ -139,10 +139,10 @@ export interface FlowbitePositions { } export interface FlowbitePlacements { - left: {on: string, off: string}; - right: {on: string, off: string}; - top: {on: string, off: string}; - bottom: {on: string, off: string}; + left: { on: string; off: string }; + right: { on: string; off: string }; + top: { on: string; off: string }; + bottom: { on: string; off: string }; } export interface FlowbiteSizes { From 16830039ca61de133b0827f9794aac03678bc9fd Mon Sep 17 00:00:00 2001 From: areski Date: Mon, 13 Mar 2023 18:22:23 +0100 Subject: [PATCH 05/91] feat(drawer): wip implementation --- src/docs/pages/DrawerPage.tsx | 69 ++++++++++++----------- src/lib/components/Drawer/Drawer.spec.tsx | 10 ++-- src/lib/components/Drawer/Drawer.tsx | 11 ++-- src/lib/theme/default.ts | 19 ++++--- 4 files changed, 56 insertions(+), 53 deletions(-) diff --git a/src/docs/pages/DrawerPage.tsx b/src/docs/pages/DrawerPage.tsx index a64e26f10..a220e5838 100644 --- a/src/docs/pages/DrawerPage.tsx +++ b/src/docs/pages/DrawerPage.tsx @@ -43,7 +43,7 @@ const DrawerPage: FC = () => { code: ( <> - setOpenDrawer(undefined)}> + setOpenDrawer(undefined)}> Menu