From 33823b65ded587039361bc6c474959fc8848e507 Mon Sep 17 00:00:00 2001 From: DaneEveritt Date: Sun, 12 Jun 2022 15:07:52 -0400 Subject: [PATCH] Fix dialog and tooltip design --- .../components/elements/dialog/Dialog.tsx | 142 ++++++++---------- .../components/elements/dialog/DialogIcon.tsx | 29 ++++ .../components/elements/dialog/index.ts | 1 - .../elements/dialog/style.module.css | 20 --- .../components/elements/tooltip/Tooltip.tsx | 14 +- 5 files changed, 99 insertions(+), 107 deletions(-) create mode 100644 resources/scripts/components/elements/dialog/DialogIcon.tsx delete mode 100644 resources/scripts/components/elements/dialog/style.module.css diff --git a/resources/scripts/components/elements/dialog/Dialog.tsx b/resources/scripts/components/elements/dialog/Dialog.tsx index 891806306..83551142f 100644 --- a/resources/scripts/components/elements/dialog/Dialog.tsx +++ b/resources/scripts/components/elements/dialog/Dialog.tsx @@ -1,49 +1,25 @@ -import React, { Fragment } from 'react'; -import { Dialog as HeadlessDialog, Transition } from '@headlessui/react'; +import React from 'react'; +import { Dialog as HDialog } from '@headlessui/react'; import { Button } from '@/components/elements/button/index'; -import styles from './style.module.css'; import { XIcon } from '@heroicons/react/solid'; -import { CheckIcon, ExclamationIcon, InformationCircleIcon, ShieldExclamationIcon } from '@heroicons/react/outline'; +import DialogIcon from '@/components/elements/dialog/DialogIcon'; +import { AnimatePresence, motion } from 'framer-motion'; import classNames from 'classnames'; interface Props { - visible: boolean; - onDismissed: () => void; + open: boolean; + onClose: () => void; + hideCloseIcon?: boolean; title?: string; + description?: string; children?: React.ReactNode; } -interface DialogIconProps { - type: 'danger' | 'info' | 'success' | 'warning'; - className?: string; -} - -const DialogIcon = ({ type, className }: DialogIconProps) => { - const [ Component, styles ] = (function (): [(props: React.ComponentProps<'svg'>) => JSX.Element, string] { - switch (type) { - case 'danger': - return [ ShieldExclamationIcon, 'bg-red-500 text-red-50' ]; - case 'warning': - return [ ExclamationIcon, 'bg-yellow-600 text-yellow-50' ]; - case 'success': - return [ CheckIcon, 'bg-green-600 text-green-50' ]; - case 'info': - return [ InformationCircleIcon, 'bg-primary-500 text-primary-50' ]; - } - })(); - - return ( -
- -
- ); -}; - const DialogButtons = ({ children }: { children: React.ReactNode }) => ( <>{children} ); -const Dialog = ({ visible, title, onDismissed, children }: Props) => { +const Dialog = ({ open, title, description, onClose, hideCloseIcon, children }: Props) => { const items = React.Children.toArray(children || []); const [ buttons, icon, content ] = [ // @ts-expect-error @@ -55,55 +31,63 @@ const Dialog = ({ visible, title, onDismissed, children }: Props) => { ]; return ( - - onDismissed()} className={styles.wrapper}> -
- - - - -
-
- {icon &&
{icon}
} -
- {title && - - {title} - - } - + + {open && ( + +
+
+
+ +
+ {icon &&
{icon}
} +
+ {title && + + {title} + + } + {description && {description}} {content} - +
-
- {buttons &&
{buttons}
} - {/* Keep this below the other buttons so that it isn't the default focus if they're present. */} -
- onDismissed()} className={'hover:rotate-90'}> - - -
+ {buttons && +
+ {buttons} +
+ } + {/* Keep this below the other buttons so that it isn't the default focus if they're present. */} + {!hideCloseIcon && +
+ + + +
+ } +
- -
- - +
+ + )} + ); }; diff --git a/resources/scripts/components/elements/dialog/DialogIcon.tsx b/resources/scripts/components/elements/dialog/DialogIcon.tsx new file mode 100644 index 000000000..bd7f19a01 --- /dev/null +++ b/resources/scripts/components/elements/dialog/DialogIcon.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { CheckIcon, ExclamationIcon, InformationCircleIcon, ShieldExclamationIcon } from '@heroicons/react/outline'; +import classNames from 'classnames'; + +interface Props { + type: 'danger' | 'info' | 'success' | 'warning'; + className?: string; +} + +export default ({ type, className }: Props) => { + const [ Component, styles ] = (function (): [ (props: React.ComponentProps<'svg'>) => JSX.Element, string ] { + switch (type) { + case 'danger': + return [ ShieldExclamationIcon, 'bg-red-500 text-red-50' ]; + case 'warning': + return [ ExclamationIcon, 'bg-yellow-600 text-yellow-50' ]; + case 'success': + return [ CheckIcon, 'bg-green-600 text-green-50' ]; + case 'info': + return [ InformationCircleIcon, 'bg-primary-500 text-primary-50' ]; + } + })(); + + return ( +
+ +
+ ); +}; diff --git a/resources/scripts/components/elements/dialog/index.ts b/resources/scripts/components/elements/dialog/index.ts index 96085ec9a..d186b2504 100644 --- a/resources/scripts/components/elements/dialog/index.ts +++ b/resources/scripts/components/elements/dialog/index.ts @@ -1,2 +1 @@ export { default as Dialog } from './Dialog'; -export { default as styles } from './style.module.css'; diff --git a/resources/scripts/components/elements/dialog/style.module.css b/resources/scripts/components/elements/dialog/style.module.css deleted file mode 100644 index 94959ee77..000000000 --- a/resources/scripts/components/elements/dialog/style.module.css +++ /dev/null @@ -1,20 +0,0 @@ -.wrapper { - @apply fixed z-10 inset-0 overflow-y-auto; -} - -.overlay { - @apply fixed inset-0 bg-gray-900 opacity-50; -} - -.container { - @apply relative bg-gray-600 rounded max-w-xl w-full mx-auto shadow-lg; - @apply ring-4 ring-gray-800 ring-opacity-80; - - & .title { - @apply font-header text-xl font-medium mb-2 text-white pr-4; - } - - & > .button_bar { - @apply px-6 py-3 bg-gray-700 flex items-center justify-end space-x-3 rounded-b; - } -} diff --git a/resources/scripts/components/elements/tooltip/Tooltip.tsx b/resources/scripts/components/elements/tooltip/Tooltip.tsx index d731e6180..476c7db49 100644 --- a/resources/scripts/components/elements/tooltip/Tooltip.tsx +++ b/resources/scripts/components/elements/tooltip/Tooltip.tsx @@ -16,6 +16,7 @@ import { useRole, } from '@floating-ui/react-dom-interactions'; import { AnimatePresence, motion } from 'framer-motion'; +import classNames from 'classnames'; interface Props { rest?: number; @@ -30,11 +31,11 @@ interface Props { children: React.ReactElement; } -const arrowSides: Record = { - top: 'bottom', - bottom: 'top', - left: 'right', - right: 'left', +const arrowSides: Record = { + top: 'bottom-[-6px] left-0', + bottom: 'top-[-6px] left-0', + right: 'top-0 left-[-6px]', + left: 'top-0 right-[-6px]', }; export default ({ @@ -103,9 +104,8 @@ export default ({ ref={arrowEl} style={{ transform: `translate(${Math.round(ax || 0)}px, ${Math.round(ay || 0)}px) rotate(45deg)`, - [side]: '-6px', }} - className={'absolute top-0 left-0 bg-gray-900 w-3 h-3'} + className={classNames('absolute bg-gray-900 w-3 h-3', side)} /> }