feat: Dropdown component
This commit is contained in:
parent
92a2071a04
commit
487bcf043b
@ -31,6 +31,7 @@ export {
|
|||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
DateRange,
|
DateRange,
|
||||||
Dialog,
|
Dialog,
|
||||||
|
Dropdown,
|
||||||
EmptyStudies,
|
EmptyStudies,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
|||||||
107
platform/ui/src/components/Dropdown/Dropdown.jsx
Normal file
107
platform/ui/src/components/Dropdown/Dropdown.jsx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
import { Icon, Typography } from '@ohif/ui';
|
||||||
|
|
||||||
|
const Dropdown = ({ titleElement, title, list }) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const element = useRef(null);
|
||||||
|
|
||||||
|
const renderTitleElement = () => {
|
||||||
|
if (titleElement) {
|
||||||
|
return titleElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex">
|
||||||
|
<Typography>{title}</Typography>
|
||||||
|
<Icon name="chevron-down" className="text-white ml-1" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleList = () => {
|
||||||
|
setOpen(s => !s);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClick = e => {
|
||||||
|
if (element.current && !element.current.contains(e.target)) {
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderList = () => {
|
||||||
|
const itemsAmount = list.length;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
'absolute origin-top-right transition duration-300 transform top-100 right-0 mt-2 z-10 bg-primary-dark border border-secondary-main rounded shadow',
|
||||||
|
{
|
||||||
|
'scale-0': !open,
|
||||||
|
'scale-100': open,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{list.map((item, idx) => (
|
||||||
|
<div
|
||||||
|
key={item.title}
|
||||||
|
className={classnames(
|
||||||
|
'flex px-4 py-2 cursor-pointer items-center transition duration-300 hover:bg-secondary-main',
|
||||||
|
{
|
||||||
|
'border-b border-secondary-main': itemsAmount !== idx + 1,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(false);
|
||||||
|
|
||||||
|
if (item.onClick) {
|
||||||
|
item.onClick();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!!item.icon && (
|
||||||
|
<Icon name={item.icon} className="text-white w-4 mr-2" />
|
||||||
|
)}
|
||||||
|
<Typography>{item.title}</Typography>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.addEventListener('click', handleClick);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('click', handleClick);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div data-cy="dropdown" ref={element} className="relative">
|
||||||
|
<div className="cursor-pointer flex items-center" onClick={toggleList}>
|
||||||
|
{renderTitleElement()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{renderList()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Dropdown.propTypes = {
|
||||||
|
titleElement: PropTypes.node,
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
/** Items to render in the select's drop down */
|
||||||
|
list: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape({
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
icon: PropTypes.object,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
link: PropTypes.string,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Dropdown;
|
||||||
22
platform/ui/src/components/Dropdown/Dropdown.mdx
Normal file
22
platform/ui/src/components/Dropdown/Dropdown.mdx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: Dropdown
|
||||||
|
menu: General
|
||||||
|
route: components/dropdown
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Playground, Props } from 'docz';
|
||||||
|
import { Dropdown } from '@ohif/ui';
|
||||||
|
|
||||||
|
# Dropdown
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { Dropdown } from '@ohif/ui';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<Props of={Button} />
|
||||||
1
platform/ui/src/components/Dropdown/index.js
Normal file
1
platform/ui/src/components/Dropdown/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './Dropdown';
|
||||||
@ -2,6 +2,7 @@ import Button from './Button';
|
|||||||
import ButtonGroup from './ButtonGroup';
|
import ButtonGroup from './ButtonGroup';
|
||||||
import DateRange from './DateRange';
|
import DateRange from './DateRange';
|
||||||
import Dialog from './Dialog';
|
import Dialog from './Dialog';
|
||||||
|
import Dropdown from './Dropdown';
|
||||||
import EmptyStudies from './EmptyStudies';
|
import EmptyStudies from './EmptyStudies';
|
||||||
import Icon from './Icon';
|
import Icon from './Icon';
|
||||||
import IconButton from './IconButton';
|
import IconButton from './IconButton';
|
||||||
@ -53,6 +54,7 @@ export {
|
|||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
DateRange,
|
DateRange,
|
||||||
Dialog,
|
Dialog,
|
||||||
|
Dropdown,
|
||||||
EmptyStudies,
|
EmptyStudies,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user