Improve dropdown menus, animation

This commit is contained in:
Tom Moor
2017-09-09 16:55:02 -07:00
parent dcbad23cb1
commit c919e51ce6
6 changed files with 87 additions and 77 deletions

View File

@ -5,19 +5,7 @@ import { observer } from 'mobx-react';
import styled from 'styled-components'; import styled from 'styled-components';
import Flex from 'components/Flex'; import Flex from 'components/Flex';
import { color } from 'styles/constants'; import { color } from 'styles/constants';
import { fadeAndScaleIn } from 'styles/animations';
type MenuItemProps = {
onClick?: Function,
children?: React.Element<any>,
};
const DropdownMenuItem = ({ onClick, children }: MenuItemProps) => {
return (
<MenuItem onClick={onClick}>
{children}
</MenuItem>
);
};
type DropdownMenuProps = { type DropdownMenuProps = {
label: React.Element<any>, label: React.Element<any>,
@ -73,37 +61,18 @@ const MenuContainer = styled.div`
`; `;
const Menu = styled.div` const Menu = styled.div`
animation: ${fadeAndScaleIn} 250ms ease;
transform-origin: 75% 0;
position: absolute; position: absolute;
right: 0; right: 0;
z-index: 1000; z-index: 1000;
border: 1px solid #eee; border: ${color.slateLight};
background-color: #fff; background: ${color.white};
border-radius: 2px;
min-width: 160px; min-width: 160px;
overflow: hidden;
box-shadow: 0 0 0 1px rgba(0,0,0,.05), 0 4px 8px rgba(0,0,0,.08), 0 2px 4px rgba(0,0,0,.08);
`; `;
const MenuItem = styled.div` export default DropdownMenu;
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 };

View File

@ -0,0 +1,42 @@
// @flow
import React from 'react';
import styled from 'styled-components';
import { color } from 'styles/constants';
const DropdownMenuItem = ({
onClick,
children,
}: {
onClick?: Function,
children?: React.Element<any>,
}) => {
return (
<MenuItem onClick={onClick}>
{children}
</MenuItem>
);
};
const MenuItem = styled.div`
margin: 0;
padding: 5px 10px;
height: 32px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
font-size: 15px;
a {
text-decoration: none;
width: 100%;
}
&:hover {
color: ${color.white};
background: ${color.primary};
}
`;
export default DropdownMenuItem;

View File

@ -1,2 +1,3 @@
// @flow // @flow
export { DropdownMenu, DropdownMenuItem } from './DropdownMenu'; export { default as DropdownMenu } from './DropdownMenu';
export { default as DropdownMenuItem } from './DropdownMenuItem';

View File

@ -79,6 +79,16 @@ class Document extends BaseModel {
return !this.isEmpty && !this.isSaving; return !this.isEmpty && !this.isSaving;
} }
@computed get allowDelete(): boolean {
const collection = this.collection;
return (
collection &&
collection.type === 'atlas' &&
collection.documents &&
collection.documents.length > 1
);
}
/* Actions */ /* Actions */
@action star = async () => { @action star = async () => {
@ -182,6 +192,14 @@ class Document extends BaseModel {
return; return;
}; };
download() {
const a = window.document.createElement('a');
a.textContent = 'download';
a.download = `${this.title}.md`;
a.href = `data:text/markdown;charset=UTF-8,${encodeURIComponent(this.text)}`;
a.click();
}
updateData(data: Object = {}, dirty: boolean = false) { updateData(data: Object = {}, dirty: boolean = false) {
if (data.text) { if (data.text) {
const { title, emoji } = parseTitle(data.text); const { title, emoji } = parseTitle(data.text);

View File

@ -204,8 +204,7 @@ type Props = {
/> />
<Meta align="center" justify="flex-end" readOnly={!isEditing}> <Meta align="center" justify="flex-end" readOnly={!isEditing}>
<Flex align="center"> <Flex align="center">
{document && {!isNew &&
!isNew &&
!isEditing && !isEditing &&
<Collaborators document={document} />} <Collaborators document={document} />}
<HeaderAction> <HeaderAction>

View File

@ -1,6 +1,5 @@
// @flow // @flow
import React, { Component } from 'react'; import React, { Component } from 'react';
import invariant from 'invariant';
import get from 'lodash/get'; 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';
@ -21,7 +20,6 @@ type Props = {
}; };
onCreateChild = () => { onCreateChild = () => {
invariant(this.props.document, 'Document is not available');
this.props.history.push(`${this.props.document.url}/new`); this.props.history.push(`${this.props.document.url}/new`);
}; };
@ -41,41 +39,24 @@ type Props = {
}; };
onExport = () => { onExport = () => {
const doc = this.props.document; this.props.document.download();
if (doc) {
const a = document.createElement('a');
a.textContent = 'download';
a.download = `${doc.title}.md`;
a.href = `data:text/markdown;charset=UTF-8,${encodeURIComponent(doc.text)}`;
a.click();
}
}; };
render() { render() {
const document = get(this.props, 'document'); const collection = this.props.document.collection;
if (document) { const allowDelete = this.props.document.allowDelete;
const collection = document.collection;
const allowDelete =
collection &&
collection.type === 'atlas' &&
collection.documents &&
collection.documents.length > 1;
return ( return (
<DropdownMenu label={<Icon type="MoreHorizontal" />}> <DropdownMenu label={<Icon type="MoreHorizontal" />} top right>
{collection && {collection &&
<div> <DropdownMenuItem onClick={this.onCreateDocument}>
<DropdownMenuItem onClick={this.onCreateDocument}> New document
New document </DropdownMenuItem>}
</DropdownMenuItem> <DropdownMenuItem onClick={this.onExport}>Export</DropdownMenuItem>
</div>} {allowDelete &&
<DropdownMenuItem onClick={this.onExport}>Export</DropdownMenuItem> <DropdownMenuItem onClick={this.onDelete}>Delete</DropdownMenuItem>}
{allowDelete && </DropdownMenu>
<DropdownMenuItem onClick={this.onDelete}>Delete</DropdownMenuItem>} );
</DropdownMenu>
);
}
return null;
} }
} }