Merge pull request #121 from jorilallo/jori/refactor-dropdown
Refactored Dropdown components
This commit is contained in:
@ -1,66 +1,111 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { observable } from 'mobx';
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import Flex from 'components/Flex';
|
||||||
|
import { color } from 'styles/constants';
|
||||||
|
|
||||||
import styles from './DropdownMenu.scss';
|
type MenuItemProps = {
|
||||||
|
|
||||||
const MenuItem = ({
|
|
||||||
onClick,
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
onClick?: Function,
|
onClick?: Function,
|
||||||
children?: React.Element<any>,
|
children?: React.Element<any>,
|
||||||
}) => {
|
};
|
||||||
|
|
||||||
|
const DropdownMenuItem = ({ onClick, children }: MenuItemProps) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.menuItem} onClick={onClick}>
|
<MenuItem onClick={onClick}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
type DropdownMenuProps = {
|
||||||
|
label: React.Element<any>,
|
||||||
|
children?: React.Element<any>,
|
||||||
|
};
|
||||||
|
|
||||||
class DropdownMenu extends React.Component {
|
@observer class DropdownMenu extends React.Component {
|
||||||
static propTypes = {
|
props: DropdownMenuProps;
|
||||||
label: React.PropTypes.node.isRequired,
|
@observable menuOpen: boolean = false;
|
||||||
children: React.PropTypes.node.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
handleClick = () => {
|
||||||
menuVisible: false,
|
this.menuOpen = !this.menuOpen;
|
||||||
};
|
|
||||||
|
|
||||||
onMouseEnter = () => {
|
|
||||||
this.setState({ menuVisible: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
onMouseLeave = () => {
|
|
||||||
this.setState({ menuVisible: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
onClick = () => {
|
|
||||||
this.setState({ menuVisible: !this.state.menuVisible });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div
|
<MenuContainer onClick={this.handleClick}>
|
||||||
className={styles.menuContainer}
|
{this.menuOpen && <Backdrop />}
|
||||||
onMouseEnter={this.onMouseEnter}
|
|
||||||
onMouseLeave={this.onMouseLeave}
|
|
||||||
>
|
|
||||||
<div className={styles.label} onClick={this.onClick}>
|
|
||||||
{this.props.label}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{this.state.menuVisible
|
<Label>
|
||||||
? <div className={styles.menu}>
|
{this.props.label}
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
{this.menuOpen &&
|
||||||
|
<Menu>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</div>
|
</Menu>}
|
||||||
: null}
|
</MenuContainer>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DropdownMenu;
|
const Backdrop = styled.div`
|
||||||
export { MenuItem };
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Label = styled(Flex).attrs({
|
||||||
|
justify: 'center',
|
||||||
|
align: 'center',
|
||||||
|
})`
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1000;
|
||||||
|
|
||||||
|
min-height: 43px;
|
||||||
|
margin: 0 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const MenuContainer = styled.div`
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Menu = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
background-color: #fff;
|
||||||
|
min-width: 160px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const MenuItem = styled.div`
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border-left: 2px solid transparent;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-left: 2px solid ${color.primary};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export { DropdownMenu, DropdownMenuItem };
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
@import '~styles/constants.scss';
|
|
||||||
|
|
||||||
.label {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
min-height: 43px;
|
|
||||||
margin: 0 5px;
|
|
||||||
color: $actionColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuContainer {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.menu {
|
|
||||||
position: absolute;
|
|
||||||
top: $headerHeight;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
background-color: #fff;
|
|
||||||
min-width: 160px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuItem {
|
|
||||||
margin: 0;
|
|
||||||
padding: 5px 10px;
|
|
||||||
height: 32px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
border-left: 2px solid transparent;
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: $textColor;
|
|
||||||
text-decoration: none;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-left: 2px solid $actionColor;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import DropdownMenu, { MenuItem } from './DropdownMenu';
|
import { DropdownMenu, DropdownMenuItem } from './DropdownMenu';
|
||||||
import MoreIcon from './components/MoreIcon';
|
import MoreIcon from './components/MoreIcon';
|
||||||
export default DropdownMenu;
|
export { DropdownMenu, DropdownMenuItem, MoreIcon };
|
||||||
export { MenuItem, MoreIcon };
|
|
||||||
|
@ -9,7 +9,7 @@ import keydown from 'react-keydown';
|
|||||||
import Flex from 'components/Flex';
|
import Flex from 'components/Flex';
|
||||||
import { color, layout } from 'styles/constants';
|
import { color, layout } from 'styles/constants';
|
||||||
|
|
||||||
import DropdownMenu, { MenuItem } from 'components/DropdownMenu';
|
import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu';
|
||||||
import { LoadingIndicatorBar } from 'components/LoadingIndicator';
|
import { LoadingIndicatorBar } from 'components/LoadingIndicator';
|
||||||
import Scrollable from 'components/Scrollable';
|
import Scrollable from 'components/Scrollable';
|
||||||
import Avatar from 'components/Avatar';
|
import Avatar from 'components/Avatar';
|
||||||
@ -101,17 +101,19 @@ type Props = {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<DropdownMenu label={<Avatar src={user.user.avatarUrl} />}>
|
<DropdownMenu label={<Avatar src={user.user.avatarUrl} />}>
|
||||||
<MenuLink to="/settings">
|
<MenuLink to="/settings">
|
||||||
<MenuItem>Settings</MenuItem>
|
<DropdownMenuItem>Settings</DropdownMenuItem>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
<MenuLink to="/keyboard-shortcuts">
|
<MenuLink to="/keyboard-shortcuts">
|
||||||
<MenuItem>
|
<DropdownMenuItem>
|
||||||
Keyboard shortcuts
|
Keyboard shortcuts
|
||||||
</MenuItem>
|
</DropdownMenuItem>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
<MenuLink to="/developers">
|
<MenuLink to="/developers">
|
||||||
<MenuItem>API</MenuItem>
|
<DropdownMenuItem>API</DropdownMenuItem>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
<MenuItem onClick={this.handleLogout}>Logout</MenuItem>
|
<DropdownMenuItem onClick={this.handleLogout}>
|
||||||
|
Logout
|
||||||
|
</DropdownMenuItem>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
|
@ -5,7 +5,11 @@ import get from 'lodash/get';
|
|||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import Document from 'models/Document';
|
import Document from 'models/Document';
|
||||||
import DropdownMenu, { MenuItem, MoreIcon } from 'components/DropdownMenu';
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuItem,
|
||||||
|
MoreIcon,
|
||||||
|
} from 'components/DropdownMenu';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
history: Object,
|
history: Object,
|
||||||
@ -63,12 +67,13 @@ type Props = {
|
|||||||
<DropdownMenu label={<MoreIcon />}>
|
<DropdownMenu label={<MoreIcon />}>
|
||||||
{collection &&
|
{collection &&
|
||||||
<div>
|
<div>
|
||||||
<MenuItem onClick={this.onCreateDocument}>
|
<DropdownMenuItem onClick={this.onCreateDocument}>
|
||||||
New document
|
New document
|
||||||
</MenuItem>
|
</DropdownMenuItem>
|
||||||
</div>}
|
</div>}
|
||||||
<MenuItem onClick={this.onExport}>Export</MenuItem>
|
<DropdownMenuItem onClick={this.onExport}>Export</DropdownMenuItem>
|
||||||
{allowDelete && <MenuItem onClick={this.onDelete}>Delete</MenuItem>}
|
{allowDelete &&
|
||||||
|
<DropdownMenuItem onClick={this.onDelete}>Delete</DropdownMenuItem>}
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user