More styles and components
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import Link from 'react-router/lib/Link';
|
||||
|
||||
import DocumentPreview from 'components/DocumentPreview';
|
||||
import DocumentLink from './components/DocumentLink';
|
||||
|
||||
import styles from './AtlasPreview.scss';
|
||||
import classNames from 'classnames/bind';
|
||||
@@ -21,7 +21,7 @@ class AtlasPreview extends React.Component {
|
||||
{ data.recentDocuments.length > 0 ?
|
||||
data.recentDocuments.map(document => {
|
||||
return (
|
||||
<DocumentPreview document={ document } />)
|
||||
<DocumentLink document={ document } key={ document.id } />)
|
||||
})
|
||||
: (
|
||||
<div className={ styles.description }>No documents. Why not <Link to={ `/atlas/${data.id}/new` }>create one</Link>?</div>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
import moment from 'moment';
|
||||
import Link from 'react-router/lib/Link';
|
||||
|
||||
import styles from './DocumentLink.scss';
|
||||
|
||||
const DocumentLink = (props) => {
|
||||
return (
|
||||
<Link to={ `/documents/${props.document.id}` } className={ styles.link }>
|
||||
<h3 className={ styles.title }>{ props.document.title }</h3>
|
||||
<span className={ styles.timestamp }>{ moment(props.document.updatedAt).fromNow() }</span>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default DocumentLink;
|
||||
@@ -0,0 +1,23 @@
|
||||
@import '../../../../utils/constants.scss';
|
||||
|
||||
.link {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: space-between;
|
||||
|
||||
margin-bottom: 20px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
color: $textColor;
|
||||
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
font-size: 13px;
|
||||
color: #ccc;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import DocumentLink from './DocumentLink';
|
||||
export default DocumentLink;
|
||||
@@ -1,5 +1,4 @@
|
||||
.content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
margin: 40px 20px;
|
||||
}
|
||||
11
src/components/Divider/Divider.js
Normal file
11
src/components/Divider/Divider.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
import styles from './Divider.scss';
|
||||
|
||||
const Divider = (props) => {
|
||||
return(
|
||||
<div className={ styles.divider }><span></span></div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Divider;
|
||||
13
src/components/Divider/Divider.scss
Normal file
13
src/components/Divider/Divider.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
.divider {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
width: 50%;
|
||||
margin: 20px 0;
|
||||
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
2
src/components/Divider/index.js
Normal file
2
src/components/Divider/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import Divider from './Divider';
|
||||
export default Divider;
|
||||
@@ -1,24 +1,29 @@
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import marked from 'marked';
|
||||
|
||||
import { Avatar } from 'rebass';
|
||||
import Flex from 'components/Flex';
|
||||
import { Link } from 'react-router';
|
||||
import PublishingInfo from 'components/PublishingInfo';
|
||||
|
||||
import styles from './Document.scss';
|
||||
|
||||
const Document = (props) => {
|
||||
return (
|
||||
<div className={ styles.container }>
|
||||
<Flex align="center" className={ styles.user }>
|
||||
<Avatar src={ props.document.user.avatarUrl } size={ 24 } />
|
||||
<span className={ styles.userName }>
|
||||
{ props.document.user.name } published { moment(document.createdAt).fromNow() }
|
||||
</span>
|
||||
</Flex>
|
||||
class Document extends React.Component {
|
||||
static propTypes = {
|
||||
document: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
<div dangerouslySetInnerHTML={{ __html: props.document.html }} />
|
||||
</div>
|
||||
);
|
||||
render() {
|
||||
return (
|
||||
<div className={ styles.container }>
|
||||
<PublishingInfo
|
||||
avatarUrl={ this.props.document.user.avatarUrl }
|
||||
name={ this.props.document.user.name }
|
||||
timestamp={ this.props.document.createdAt }
|
||||
/>
|
||||
<div dangerouslySetInnerHTML={{ __html: this.props.document.html }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Document;
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
.container {
|
||||
padding: 20px 0;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.user {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.userName {
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
29
src/components/DocumentList/DocumentList.js
Normal file
29
src/components/DocumentList/DocumentList.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
|
||||
import DocumentPreview from 'components/DocumentPreview';
|
||||
import Divider from 'components/Divider';
|
||||
|
||||
import styles from './DocumentList.scss';
|
||||
|
||||
class DocumentList extends React.Component {
|
||||
static propTypes = {
|
||||
documents: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{ this.props.documents.map((document) => {
|
||||
return (
|
||||
<div>
|
||||
<DocumentPreview document={ document } />
|
||||
<Divider />
|
||||
</div>
|
||||
);
|
||||
}) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default DocumentList;
|
||||
0
src/components/DocumentList/DocumentList.scss
Normal file
0
src/components/DocumentList/DocumentList.scss
Normal file
2
src/components/DocumentList/index.js
Normal file
2
src/components/DocumentList/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import DocumentList from './DocumentList';
|
||||
export default DocumentList;
|
||||
@@ -1,26 +1,46 @@
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import Link from 'react-router/lib/Link';
|
||||
import marked from 'marked';
|
||||
|
||||
import styles from './documentPreview.scss';
|
||||
import classNames from 'classnames/bind';
|
||||
const cx = classNames.bind(styles);
|
||||
import { Link } from 'react-router';
|
||||
|
||||
class documentPreview extends React.Component {
|
||||
import PublishingInfo from 'components/PublishingInfo';
|
||||
|
||||
import styles from './DocumentPreview.scss';
|
||||
|
||||
class Document extends React.Component {
|
||||
static propTypes = {
|
||||
document: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const document = this.props.document;
|
||||
|
||||
return (
|
||||
<Link to={ `/documents/${document.id}` } className={ styles.documentPreview }>
|
||||
<h3>{ document.title }</h3>
|
||||
<span>{ moment(document.updatedAt).fromNow() }</span>
|
||||
</Link>
|
||||
<div className={ styles.container }>
|
||||
<PublishingInfo
|
||||
avatarUrl={ this.props.document.user.avatarUrl }
|
||||
name={ this.props.document.user.name }
|
||||
timestamp={ document.createdAt }
|
||||
/>
|
||||
|
||||
<Link
|
||||
to={ `/documents/${this.props.document.id}` }
|
||||
className={ styles.title }
|
||||
>
|
||||
<h2>{ this.props.document.title }</h2>
|
||||
</Link>
|
||||
|
||||
<div dangerouslySetInnerHTML={{ __html: this.props.document.preview }} />
|
||||
|
||||
<div>
|
||||
<Link
|
||||
to={ `/documents/${this.props.document.id}` }
|
||||
className={ styles.continueLink }
|
||||
>
|
||||
Continue reading...
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default documentPreview;
|
||||
export default Document;
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
@import '../../utils/constants.scss';
|
||||
|
||||
.documentPreview {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: space-between;
|
||||
|
||||
margin-bottom: 20px;
|
||||
text-decoration: none;
|
||||
.container {
|
||||
width: 100%;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
.title {
|
||||
color: $textColor;
|
||||
text-decoration: none;
|
||||
|
||||
margin: 0;
|
||||
h2 {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 13px;
|
||||
color: #ccc;
|
||||
.continueLink {
|
||||
text-decoration: none;
|
||||
}
|
||||
26
src/components/PublishingInfo/PublishingInfo.js
Normal file
26
src/components/PublishingInfo/PublishingInfo.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
|
||||
import { Avatar } from 'rebass';
|
||||
import Flex from 'components/Flex';
|
||||
|
||||
import styles from './PublishingInfo.scss';
|
||||
|
||||
const PublishingInfo = (props) => {
|
||||
return (
|
||||
<Flex align="center" className={ styles.user }>
|
||||
<Avatar src={ props.avatarUrl } size={ 24 } />
|
||||
<span className={ styles.userName }>
|
||||
{ props.name } published { moment(props.timestamp).fromNow() }
|
||||
</span>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
PublishingInfo.propTypes = {
|
||||
avatarUrl: React.PropTypes.string.isRequired,
|
||||
name: React.PropTypes.string.isRequired,
|
||||
timestamp: React.PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default PublishingInfo;
|
||||
9
src/components/PublishingInfo/PublishingInfo.scss
Normal file
9
src/components/PublishingInfo/PublishingInfo.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
.user {
|
||||
margin-bottom: 30px;
|
||||
color: #ccc;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.userName {
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
2
src/components/PublishingInfo/index.js
Normal file
2
src/components/PublishingInfo/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import PublishingInfo from './PublishingInfo';
|
||||
export default PublishingInfo;
|
||||
@@ -11,6 +11,8 @@ import { client } from 'utils/ApiClient';
|
||||
import Layout, { Title } from 'components/Layout';
|
||||
import AtlasPreviewLoading from 'components/AtlasPreviewLoading';
|
||||
import CenteredContent from 'components/CenteredContent';
|
||||
import DocumentList from 'components/DocumentList';
|
||||
import Divider from 'components/Divider';
|
||||
|
||||
import styles from './Atlas.scss';
|
||||
|
||||
@@ -54,7 +56,9 @@ class Atlas extends React.Component {
|
||||
</blockquote>
|
||||
</div>
|
||||
|
||||
<div className={ styles.divider }><span></span></div>
|
||||
<Divider />
|
||||
|
||||
<DocumentList documents={ atlas.recentDocuments } preview={ true } />
|
||||
</div>
|
||||
) }
|
||||
</CenteredContent>
|
||||
|
||||
@@ -15,17 +15,3 @@
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
width: 50%;
|
||||
margin: 20px 0;
|
||||
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,84 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--line-height-1: 1;
|
||||
--line-height-2: 1.125;
|
||||
--line-height-3: 1.25;
|
||||
--line-height-4: 1.5;
|
||||
--letter-spacing: 1;
|
||||
--caps-letter-spacing: .2em;
|
||||
--bold-font-weight: bold;
|
||||
}
|
||||
|
||||
html, body, .viewport {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-family: 'Atlas Grotesk', 'Helvetica Neue', sans-serif;
|
||||
body {
|
||||
font-family: 'Atlas Grotesk', -apple-system, 'Helvetica Neue', Helvetica, sans-serif;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
color: $textColor;
|
||||
background-color: #fff;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
svg {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0C77F8;
|
||||
}
|
||||
h1, h2, h3,
|
||||
h4, h5, h6 {
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
margin-top: 1em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
h1 { font-size: 2rem }
|
||||
h2 { font-size: 1.5rem }
|
||||
h3 { font-size: 1.25rem }
|
||||
h4 { font-size: 1rem }
|
||||
h5 { font-size: .875rem }
|
||||
h6 { font-size: .75rem }
|
||||
p, dl, ol, ul, pre, blockquote {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
code,
|
||||
pre,
|
||||
samp {
|
||||
font-family:
|
||||
'Atlas Typewriter',
|
||||
'Source Code Pro',
|
||||
Menlo,
|
||||
Consolas,
|
||||
'Liberation Mono',
|
||||
monospace;
|
||||
}
|
||||
code, samp {
|
||||
font-size: 87.5%;
|
||||
padding: .125em;
|
||||
}
|
||||
pre {
|
||||
font-size: 87.5%;
|
||||
overflow: scroll;
|
||||
}
|
||||
blockquote {
|
||||
font-size: 1.25rem;
|
||||
font-style: italic;
|
||||
margin-left: 0;
|
||||
}
|
||||
hr {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
border: 0;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #ccc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user