Move collaborators to top right (#201)

* Hopefully the last time we rejig this before launch

* Improved spacing

* Move to injectGlobal, alignment fixes
This commit is contained in:
Tom Moor 2017-09-03 17:26:57 -07:00 committed by GitHub
parent 7f88c56c2f
commit e34ffe0cf4
11 changed files with 99 additions and 68 deletions

View File

@ -8,7 +8,7 @@ type Props = {
const Container = styled.div`
width: 100%;
margin: 40px 20px;
margin: 60px 20px;
`;
const Content = styled.div`

View File

@ -0,0 +1,56 @@
// @flow
import React from 'react';
import moment from 'moment';
import styled from 'styled-components';
import { color } from 'styles/constants';
import Flex from 'components/Flex';
import Tooltip from 'components/Tooltip';
import Document from 'models/Document';
const Collaborators = function({ document }: { document: Document }) {
const {
createdAt,
updatedAt,
createdBy,
updatedBy,
collaborators,
} = document;
let tooltip;
if (createdAt === updatedAt) {
tooltip = `${createdBy.name} published ${moment(createdAt).fromNow()}`;
} else {
tooltip = `${updatedBy.name} modified ${moment(updatedAt).fromNow()}`;
}
return (
<Avatars>
<Tooltip tooltip={tooltip} placement="bottom">
{collaborators.map(user => (
<Avatar key={user.id} src={user.avatarUrl} />
))}
</Tooltip>
</Avatars>
);
};
const Avatars = styled(Flex)`
flex-direction: row-reverse;
margin-right: 10px;
height: 26px;
`;
const Avatar = styled.img`
width: 26px;
height: 26px;
flex-shrink: 0;
border-radius: 50%;
border: 2px solid ${color.white};
margin-right: -13px;
&:first-child {
margin-right: 0;
}
`;
export default Collaborators;

View File

@ -0,0 +1,3 @@
// @flow
import Collaborators from './Collaborators';
export default Collaborators;

View File

@ -5,7 +5,7 @@ import { Link } from 'react-router-dom';
import Document from 'models/Document';
import styled from 'styled-components';
import { color } from 'styles/constants';
import PublishingInfo from 'components/PublishingInfo';
import PublishingInfo from './components/PublishingInfo';
import StarIcon from 'components/Icon/StarIcon';
type Props = {

View File

@ -5,7 +5,6 @@ import styled from 'styled-components';
import { color } from 'styles/constants';
import Collection from 'models/Collection';
import Document from 'models/Document';
import type { User } from 'types';
import Flex from 'components/Flex';
const Container = styled(Flex)`
@ -13,24 +12,6 @@ const Container = styled(Flex)`
font-size: 13px;
`;
const Avatars = styled(Flex)`
flex-direction: row-reverse;
margin-right: 10px;
`;
const Avatar = styled.img`
width: 26px;
height: 26px;
flex-shrink: 0;
border-radius: 50%;
border: 2px solid ${color.white};
margin-right: -13px;
&:first-child {
margin-right: 0;
}
`;
const Modified = styled.span`
color: ${props => (props.highlight ? color.slateDark : color.slate)};
font-weight: ${props => (props.highlight ? '600' : '400')};
@ -38,14 +19,13 @@ const Modified = styled.span`
class PublishingInfo extends Component {
props: {
collaborators?: Array<User>,
collection?: Collection,
document: Document,
views?: number,
};
render() {
const { collaborators, collection, document } = this.props;
const { collection, document } = this.props;
const {
modifiedSinceViewed,
createdAt,
@ -56,12 +36,6 @@ class PublishingInfo extends Component {
return (
<Container align="center">
{collaborators &&
<Avatars>
{collaborators.map(user => (
<Avatar key={user.id} src={user.avatarUrl} title={user.name} />
))}
</Avatars>}
{createdAt === updatedAt
? <span>
{createdBy.name}

View File

@ -27,7 +27,6 @@ type Props = {
onImageUploadStop: Function,
emoji: string,
readOnly: boolean,
heading?: ?React.Element<*>,
};
type KeyData = {
@ -187,12 +186,7 @@ type KeyData = {
auto
>
<MaxWidth column auto>
<HeaderContainer
onClick={this.focusAtStart}
readOnly={this.props.readOnly}
>
{this.props.heading}
</HeaderContainer>
<Header onClick={this.focusAtStart} readOnly={this.props.readOnly} />
<Toolbar state={this.state.state} onChange={this.onChange} />
<Editor
ref={ref => (this.editor = ref)}
@ -224,11 +218,10 @@ const MaxWidth = styled(Flex)`
height: 100%;
`;
const HeaderContainer = styled(Flex).attrs({
align: 'flex-end',
})`
height: 100px;
const Header = styled(Flex)`
height: 60px;
flex-shrink: 0;
align-items: flex-end;
${({ readOnly }) => !readOnly && 'cursor: text;'}
`;

View File

@ -1,3 +0,0 @@
// @flow
import PublishingInfo from './PublishingInfo';
export default PublishingInfo;

View File

@ -0,0 +1,11 @@
// @flow
import { TooltipTrigger } from 'pui-react-tooltip';
import { injectGlobal } from 'styled-components';
injectGlobal([
`
.tooltip:hover .tooltip-container:not(.tooltip-container-hidden){visibility:visible;opacity:1}.tooltip-container{visibility:hidden;-webkit-transition:opacity ease-out 0.2s;transition:opacity ease-out 0.2s;z-index:10;position:absolute;bottom:100%;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);margin:0 0 8px 0;text-align:left}.tooltip-container.tooltip-container-visible{visibility:visible}.tooltip-container.tooltip-hoverable:after{content:"";position:absolute;width:calc(100% + 16px);height:calc(100% + 16px);top:50%;left:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%)}.tooltip-container .tooltip-content{white-space:nowrap;padding:4px 8px;font-size:12px;line-height:16px;font-weight:400;letter-spacing:0;text-transform:none;background-color:#243641;color:#fff;border-radius:2px;border:1px solid #243641;box-shadow:0px 2px 2px 0px rgba(36, 54, 65, .1),0px 0px 2px 0px rgba(36, 54, 65, .1)}.tooltip-container .tooltip-content:before{content:"";z-index:1;position:absolute;bottom:-4px;left:50%;-webkit-transform:translateX(-50%) rotateZ(45deg);transform:translateX(-50%) rotateZ(45deg);background-color:#243641;border-bottom:1px solid #243641;border-right:1px solid #243641;width:8px;height:8px}.tooltip-container .tooltip-content:after{content:"";box-sizing:content-box;z-index:-1;position:absolute;bottom:-4px;left:50%;-webkit-transform:translateX(-50%) rotateZ(45deg);transform:translateX(-50%) rotateZ(45deg);background-color:#243641;box-shadow:0px 2px 2px 0px rgba(36, 54, 65, .1),0px 0px 2px 0px rgba(36, 54, 65, .1);width:8px;height:8px}.tooltip{position:relative;display:inline-block}.tooltip.tooltip-light .tooltip-content{background-color:#fff;color:#243641;border:1px solid #DFE5E8}.tooltip.tooltip-light .tooltip-content:before{background-color:#fff;border-bottom:1px solid #DFE5E8;border-right:1px solid #DFE5E8}.tooltip.tooltip-light .tooltip-content:after{background-color:#fff}.tooltip.tooltip-bottom .tooltip-container{top:100%;bottom:auto;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);margin:8px 0 0 0}.tooltip.tooltip-bottom .tooltip-container .tooltip-content:before{bottom:auto;top:-4px;border-top:1px solid #243641;border-right:none;border-bottom:none;border-left:1px solid #243641}.tooltip.tooltip-bottom .tooltip-container .tooltip-content:after{bottom:auto;top:-4px}.tooltip.tooltip-bottom.tooltip-light .tooltip-content:before{border-top:1px solid #DFE5E8;border-left:1px solid #DFE5E8}.tooltip.tooltip-right .tooltip-container{top:50%;bottom:auto;left:100%;-webkit-transform:translatey(-50%);transform:translatey(-50%);margin:0 0 0 8px}.tooltip.tooltip-right .tooltip-container .tooltip-content:before{bottom:auto;left:-4px;top:50%;-webkit-transform:translatey(-50%) rotateZ(45deg);transform:translatey(-50%) rotateZ(45deg);border-top:none;border-right:none;border-bottom:1px solid #243641;border-left:1px solid #243641}.tooltip.tooltip-right .tooltip-container .tooltip-content:after{bottom:auto;left:-4px;top:50%;-webkit-transform:translatey(-50%) rotateZ(45deg);transform:translatey(-50%) rotateZ(45deg)}.tooltip.tooltip-right.tooltip-light .tooltip-content:before{border-bottom:1px solid #DFE5E8;border-left:1px solid #DFE5E8}.tooltip.tooltip-left .tooltip-container{top:50%;bottom:auto;right:100%;left:auto;-webkit-transform:translatey(-50%);transform:translatey(-50%);margin:0 8px 0 0}.tooltip.tooltip-left .tooltip-container .tooltip-content:before{bottom:auto;right:-4px;left:auto;top:50%;-webkit-transform:translatey(-50%) rotateZ(45deg);transform:translatey(-50%) rotateZ(45deg);border-top:1px solid #243641;border-right:1px solid #243641;border-bottom:none;border-left:none}.tooltip.tooltip-left .tooltip-container .tooltip-content:after{bottom:auto;right:-4px;left:auto;top:50%;-webkit-transform:translatey(-50%) rotateZ(45deg);transform:translatey(-50%) rotateZ(45deg)}.tooltip.tooltip-left.tooltip-light .tooltip-content:before{border-top:1px solid #DFE5E8;border-right:1px solid #DFE5E8}.tooltip-sm.tooltip-container{width:120px}.tooltip-sm.tooltip-container .tooltip-content{white-space:normal}.tooltip-md.tooltip-container{width:240px}.tooltip-md.tooltip-container .tooltip-content{white-space:normal}.tooltip-lg.tooltip-container{width:360px}.tooltip-lg.tooltip-container .tooltip-content{white-space:normal}.tether-element{z-index:99}.overlay-trigger{color:#1B78B3;-webkit-transition:all 300ms ease-out;transition:all 300ms ease-out;-webkit-transition-property:background-color, color, opacity;transition-property:background-color, color, opacity}.overlay-trigger:hover,.overlay-trigger:focus{color:#1f8ace;cursor:pointer;outline:none;text-decoration:none}.overlay-trigger:active,.overlay-trigger.active{color:#176698}
`,
]);
export default TooltipTrigger;

View File

@ -6,7 +6,6 @@ import { observer, inject } from 'mobx-react';
import { withRouter, Prompt } from 'react-router';
import Flex from 'components/Flex';
import { layout } from 'styles/constants';
import invariant from 'invariant';
import Document from 'models/Document';
import UiStore from 'stores/UiStore';
@ -18,7 +17,7 @@ import Editor from 'components/Editor';
import DropToImport from 'components/DropToImport';
import { HeaderAction } from 'components/Layout';
import LoadingIndicator from 'components/LoadingIndicator';
import PublishingInfo from 'components/PublishingInfo';
import Collaborators from 'components/Collaborators';
import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
@ -154,20 +153,6 @@ type Props = {
this.setState({ isDragging: false });
};
renderHeading(isEditing: boolean) {
invariant(this.document, 'document not available');
if (this.props.newDocument) return;
return (
<InfoWrapper visible={!isEditing}>
<PublishingInfo
collaborators={this.document.collaborators}
document={this.document}
/>
</InfoWrapper>
);
}
render() {
const isNew = this.props.newDocument;
const isEditing = !!this.props.match.params.edit || isNew;
@ -211,11 +196,14 @@ type Props = {
onChange={this.onChange}
onSave={this.onSave}
onCancel={this.onCancel}
heading={this.renderHeading(!!isEditing)}
readOnly={!isEditing}
/>
<Meta align="center" justify="flex-end" readOnly={!isEditing}>
<Flex align="center">
{document &&
!isNew &&
!isEditing &&
<Collaborators document={document} />}
<HeaderAction>
{isEditing
? <SaveAction
@ -263,11 +251,6 @@ const Meta = styled(Flex)`
padding: ${layout.padding};
`;
const InfoWrapper = styled(Flex)`
opacity: ${({ visible }) => (visible ? '1' : '0')};
transition: all 100ms ease-in-out;
`;
const Container = styled(Flex)`
position: relative;
width: 100%;

View File

@ -138,6 +138,7 @@
"pg": "^6.1.5",
"pg-hstore": "2.3.2",
"polished": "1.2.1",
"pui-react-tooltip": "^8.3.3",
"query-string": "^4.3.4",
"randomstring": "1.1.5",
"raw-loader": "^0.5.1",

View File

@ -946,7 +946,7 @@ babel-register@^6.26.0:
mkdirp "^0.5.1"
source-map-support "^0.4.15"
babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
babel-runtime@^6.1.18, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
dependencies:
@ -1506,7 +1506,7 @@ clap@^1.0.9:
dependencies:
chalk "^1.1.3"
classnames@2.2.3, classnames@^2.1.5:
classnames@2.2.3, classnames@^2.1.5, classnames@^2.2.0:
version "2.2.3"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.3.tgz#551b774b6762a0c0a997187f7ba4f1d603961ac5"
@ -7207,7 +7207,7 @@ promise@7.x, promise@^7.0.3, promise@^7.1.1:
dependencies:
asap "~2.0.3"
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8:
prop-types@>=15.5.6, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8:
version "15.5.10"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
dependencies:
@ -7242,6 +7242,19 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0"
randombytes "^2.0.1"
pui-css-tooltips@=8.3.3:
version "8.3.3"
resolved "https://registry.yarnpkg.com/pui-css-tooltips/-/pui-css-tooltips-8.3.3.tgz#3e4dd13e4883991dcdb27b065377b3e866edfd7e"
pui-react-tooltip@^8.3.3:
version "8.3.3"
resolved "https://registry.yarnpkg.com/pui-react-tooltip/-/pui-react-tooltip-8.3.3.tgz#bb7e67c38a06e88501f245e6c2891e6252a7f546"
dependencies:
babel-runtime "^6.1.18"
classnames "^2.2.0"
prop-types ">=15.5.6"
pui-css-tooltips "=8.3.3"
"pullstream@>= 0.4.1 < 1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/pullstream/-/pullstream-0.4.1.tgz#d6fb3bf5aed697e831150eb1002c25a3f8ae1314"