Skip to content

Commit 33823b6

Browse files
committed
Fix dialog and tooltip design
1 parent 064a942 commit 33823b6

File tree

5 files changed

+99
-107
lines changed

5 files changed

+99
-107
lines changed

resources/scripts/components/elements/dialog/Dialog.tsx

Lines changed: 63 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,25 @@
1-
import React, { Fragment } from 'react';
2-
import { Dialog as HeadlessDialog, Transition } from '@headlessui/react';
1+
import React from 'react';
2+
import { Dialog as HDialog } from '@headlessui/react';
33
import { Button } from '@/components/elements/button/index';
4-
import styles from './style.module.css';
54
import { XIcon } from '@heroicons/react/solid';
6-
import { CheckIcon, ExclamationIcon, InformationCircleIcon, ShieldExclamationIcon } from '@heroicons/react/outline';
5+
import DialogIcon from '@/components/elements/dialog/DialogIcon';
6+
import { AnimatePresence, motion } from 'framer-motion';
77
import classNames from 'classnames';
88

99
interface Props {
10-
visible: boolean;
11-
onDismissed: () => void;
10+
open: boolean;
11+
onClose: () => void;
12+
hideCloseIcon?: boolean;
1213
title?: string;
14+
description?: string;
1315
children?: React.ReactNode;
1416
}
1517

16-
interface DialogIconProps {
17-
type: 'danger' | 'info' | 'success' | 'warning';
18-
className?: string;
19-
}
20-
21-
const DialogIcon = ({ type, className }: DialogIconProps) => {
22-
const [ Component, styles ] = (function (): [(props: React.ComponentProps<'svg'>) => JSX.Element, string] {
23-
switch (type) {
24-
case 'danger':
25-
return [ ShieldExclamationIcon, 'bg-red-500 text-red-50' ];
26-
case 'warning':
27-
return [ ExclamationIcon, 'bg-yellow-600 text-yellow-50' ];
28-
case 'success':
29-
return [ CheckIcon, 'bg-green-600 text-green-50' ];
30-
case 'info':
31-
return [ InformationCircleIcon, 'bg-primary-500 text-primary-50' ];
32-
}
33-
})();
34-
35-
return (
36-
<div className={classNames('flex items-center justify-center w-10 h-10 rounded-full', styles, className)}>
37-
<Component className={'w-6 h-6'} />
38-
</div>
39-
);
40-
};
41-
4218
const DialogButtons = ({ children }: { children: React.ReactNode }) => (
4319
<>{children}</>
4420
);
4521

46-
const Dialog = ({ visible, title, onDismissed, children }: Props) => {
22+
const Dialog = ({ open, title, description, onClose, hideCloseIcon, children }: Props) => {
4723
const items = React.Children.toArray(children || []);
4824
const [ buttons, icon, content ] = [
4925
// @ts-expect-error
@@ -55,55 +31,63 @@ const Dialog = ({ visible, title, onDismissed, children }: Props) => {
5531
];
5632

5733
return (
58-
<Transition show={visible} as={Fragment}>
59-
<HeadlessDialog onClose={() => onDismissed()} className={styles.wrapper}>
60-
<div className={'flex items-center justify-center min-h-screen'}>
61-
<Transition.Child
62-
as={Fragment}
63-
enter={'ease-out duration-200'}
64-
enterFrom={'opacity-0'}
65-
enterTo={'opacity-100'}
66-
leave={'ease-in duration-100'}
67-
leaveFrom={'opacity-100'}
68-
leaveTo={'opacity-0'}
69-
>
70-
<HeadlessDialog.Overlay className={styles.overlay}/>
71-
</Transition.Child>
72-
<Transition.Child
73-
as={Fragment}
74-
enter={'ease-out duration-200'}
75-
enterFrom={'opacity-0 scale-95'}
76-
enterTo={'opacity-100 scale-100'}
77-
leave={'ease-in duration-100'}
78-
leaveFrom={'opacity-100 scale-100'}
79-
leaveTo={'opacity-0 scale-95'}
80-
>
81-
<div className={styles.container}>
82-
<div className={'flex p-6'}>
83-
{icon && <div className={'mr-4'}>{icon}</div>}
84-
<div className={'flex-1'}>
85-
{title &&
86-
<HeadlessDialog.Title className={styles.title}>
87-
{title}
88-
</HeadlessDialog.Title>
89-
}
90-
<HeadlessDialog.Description className={'pr-4'}>
34+
<AnimatePresence>
35+
{open && (
36+
<HDialog
37+
static
38+
as={motion.div}
39+
initial={{ opacity: 0 }}
40+
animate={{ opacity: 1 }}
41+
exit={{ opacity: 0 }}
42+
transition={{ duration: 0.15 }}
43+
open={open}
44+
onClose={onClose}
45+
>
46+
<div className={'fixed inset-0 bg-gray-900/50'}/>
47+
<div className={'fixed inset-0 overflow-y-auto'}>
48+
<div className={'flex min-h-full items-center justify-center p-4 text-center'}>
49+
<HDialog.Panel
50+
as={motion.div}
51+
initial={{ opacity: 0, scale: 0.85 }}
52+
animate={{ opacity: 1, scale: 1 }}
53+
exit={{ opacity: 0 }}
54+
transition={{ type: 'spring', damping: 15, stiffness: 300, duration: 0.15 }}
55+
className={classNames([
56+
'relative bg-gray-600 rounded max-w-xl w-full mx-auto shadow-lg text-left',
57+
'ring-4 ring-gray-800 ring-opacity-80',
58+
])}
59+
>
60+
<div className={'flex p-6'}>
61+
{icon && <div className={'mr-4'}>{icon}</div>}
62+
<div className={'flex-1 max-h-[70vh] overflow-y-scroll overflow-x-hidden'}>
63+
{title &&
64+
<HDialog.Title className={'font-header text-xl font-medium mb-2 text-white pr-4'}>
65+
{title}
66+
</HDialog.Title>
67+
}
68+
{description && <HDialog.Description>{description}</HDialog.Description>}
9169
{content}
92-
</HeadlessDialog.Description>
70+
</div>
9371
</div>
94-
</div>
95-
{buttons && <div className={styles.button_bar}>{buttons}</div>}
96-
{/* Keep this below the other buttons so that it isn't the default focus if they're present. */}
97-
<div className={'absolute right-0 top-0 m-4'}>
98-
<Button.Text square small onClick={() => onDismissed()} className={'hover:rotate-90'}>
99-
<XIcon className={'w-5 h-5'}/>
100-
</Button.Text>
101-
</div>
72+
{buttons &&
73+
<div className={'px-6 py-3 bg-gray-700 flex items-center justify-end space-x-3 rounded-b'}>
74+
{buttons}
75+
</div>
76+
}
77+
{/* Keep this below the other buttons so that it isn't the default focus if they're present. */}
78+
{!hideCloseIcon &&
79+
<div className={'absolute right-0 top-0 m-4'}>
80+
<Button.Text square small onClick={onClose} className={'hover:rotate-90'}>
81+
<XIcon className={'w-5 h-5'}/>
82+
</Button.Text>
83+
</div>
84+
}
85+
</HDialog.Panel>
10286
</div>
103-
</Transition.Child>
104-
</div>
105-
</HeadlessDialog>
106-
</Transition>
87+
</div>
88+
</HDialog>
89+
)}
90+
</AnimatePresence>
10791
);
10892
};
10993

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
import { CheckIcon, ExclamationIcon, InformationCircleIcon, ShieldExclamationIcon } from '@heroicons/react/outline';
3+
import classNames from 'classnames';
4+
5+
interface Props {
6+
type: 'danger' | 'info' | 'success' | 'warning';
7+
className?: string;
8+
}
9+
10+
export default ({ type, className }: Props) => {
11+
const [ Component, styles ] = (function (): [ (props: React.ComponentProps<'svg'>) => JSX.Element, string ] {
12+
switch (type) {
13+
case 'danger':
14+
return [ ShieldExclamationIcon, 'bg-red-500 text-red-50' ];
15+
case 'warning':
16+
return [ ExclamationIcon, 'bg-yellow-600 text-yellow-50' ];
17+
case 'success':
18+
return [ CheckIcon, 'bg-green-600 text-green-50' ];
19+
case 'info':
20+
return [ InformationCircleIcon, 'bg-primary-500 text-primary-50' ];
21+
}
22+
})();
23+
24+
return (
25+
<div className={classNames('flex items-center justify-center w-10 h-10 rounded-full', styles, className)}>
26+
<Component className={'w-6 h-6'}/>
27+
</div>
28+
);
29+
};
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
export { default as Dialog } from './Dialog';
2-
export { default as styles } from './style.module.css';

resources/scripts/components/elements/dialog/style.module.css

Lines changed: 0 additions & 20 deletions
This file was deleted.

resources/scripts/components/elements/tooltip/Tooltip.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
useRole,
1717
} from '@floating-ui/react-dom-interactions';
1818
import { AnimatePresence, motion } from 'framer-motion';
19+
import classNames from 'classnames';
1920

2021
interface Props {
2122
rest?: number;
@@ -30,11 +31,11 @@ interface Props {
3031
children: React.ReactElement;
3132
}
3233

33-
const arrowSides: Record<Side, Side> = {
34-
top: 'bottom',
35-
bottom: 'top',
36-
left: 'right',
37-
right: 'left',
34+
const arrowSides: Record<Side, string> = {
35+
top: 'bottom-[-6px] left-0',
36+
bottom: 'top-[-6px] left-0',
37+
right: 'top-0 left-[-6px]',
38+
left: 'top-0 right-[-6px]',
3839
};
3940

4041
export default ({
@@ -103,9 +104,8 @@ export default ({
103104
ref={arrowEl}
104105
style={{
105106
transform: `translate(${Math.round(ax || 0)}px, ${Math.round(ay || 0)}px) rotate(45deg)`,
106-
[side]: '-6px',
107107
}}
108-
className={'absolute top-0 left-0 bg-gray-900 w-3 h-3'}
108+
className={classNames('absolute bg-gray-900 w-3 h-3', side)}
109109
/>
110110
}
111111
</motion.div>

0 commit comments

Comments
 (0)