working on design & CSS

This commit is contained in:
Sacha Greif 2016-03-25 10:45:28 +09:00
parent 50a1a4f1d7
commit acc2c39253
22 changed files with 257 additions and 156 deletions

View file

@ -1,15 +1,23 @@
import Router from "../../router.js"
import { DropdownButton, MenuItem } from 'react-bootstrap';
const CategoriesList = (props) => {
const CategoriesList = ({categories}) => {
return (
<div className="categories">
<h4>Categories</h4>
<ul>
{props.results.map(category =>
<li key={category._id} className="post-category"><a href={Router.extendPathWithQueryParams("posts.list", {}, {cat: category.slug})}>{category.name}</a></li>
<DropdownButton bsStyle="default" className="btn-secondary" title="Categories" id="categories-dropdown">
<MenuItem href={Router.path("posts.list")} eventKey={0} className="dropdown-item post-category">All</MenuItem>
{categories.map((category, index) =>
<MenuItem
href={Router.extendPathWithQueryParams("posts.list", {}, {cat: category.slug})}
eventKey={index+1}
key={category._id}
className="dropdown-item post-category"
>
{category.name}
</MenuItem>
)}
</ul>
</DropdownButton>
</div>
)

View file

@ -1,4 +1,5 @@
import React, { PropTypes, Component } from 'react';
import { Alert } from 'react-bootstrap';
import Core from "meteor/nova:core";
const Messages = Core.Messages;
@ -10,10 +11,14 @@ class Flash extends Component{
}
render() {
let type = this.props.message.type;
type = type === "error" ? "danger" : type; // if type is "error", use "danger" instead
return (
<div className={`flash-message page-message page-message--${this.props.message.type}`}>
<div className="page-message__text">{this.props.message.content}</div>
</div>
<Alert className="flash-message" bsStyle={type}>
{this.props.message.content}
</Alert>
)
}
}

View file

@ -1,52 +1,33 @@
import NoSSR from 'react-no-ssr';
import Router from '../router.js'
import Core from "meteor/nova:core";
import { Button } from 'react-bootstrap';
const Messages = Core.Messages;
const Header = ({currentUser}) => {
({Logo, ListContainer, CategoriesList, FlashContainer, FlashMessages, ModalTrigger, NewDocContainer, CanCreatePost, CurrentUserContainer, NewsletterForm, SearchForm} = Telescope.components);
({Logo, ListContainer, CategoriesList, NewPostButton} = Telescope.components);
const logoUrl = Telescope.settings.get("logoUrl");
const siteTitle = Telescope.settings.get("title", "Telescope");
const tagline = Telescope.settings.get("tagline");
return (
<header className="header">
<div className="logo">
<Logo logoUrl={logoUrl} siteTitle={siteTitle} />
{tagline ? <h2 className="tagline">{tagline}</h2> : "" }
</div>
<div className="header-wrapper">
<header className="header">
<div className="logo">
<Logo logoUrl={logoUrl} siteTitle={siteTitle} />
{tagline ? <h2 className="tagline">{tagline}</h2> : "" }
</div>
<LogInButtons />
<LogInButtons />
{currentUser ? <p><a href={Router.path("account")}>My Account</a></p> : ""}
{currentUser ? <p><a href={Router.path("account")}>My Account</a></p> : ""}
<CanCreatePost user={currentUser}>
<ModalTrigger component={<Button bsStyle="primary">New Post</Button>}>
<NewDocContainer
collection={Posts}
label="New Post"
methodName="posts.new"
successCallback={(post)=>{
Messages.flash("Post created.", "success");
Router.go('posts.single', post);
}}
/>
</ModalTrigger>
</CanCreatePost>
<NewPostButton/>
<CurrentUserContainer component={NewsletterForm} />
<FlashContainer component={FlashMessages}/>
<div className="nav">
<ListContainer collection={Categories} limit={0}><CategoriesList/></ListContainer>
</div>
</header>
</header>
</div>
)
}

View file

@ -1,14 +1,24 @@
const Layout = props => {
({Header, Footer} = Telescope.components);
({Header, Footer, FlashContainer, FlashMessages, NewsletterForm} = Telescope.components);
return (
<div className="wrapper" id="wrapper">
<Header {...props}/>
<FlashContainer component={FlashMessages}/>
<div className="main">
<NewsletterForm />
{props.children}
</div>
<Footer {...props}/>
</div>
)
}

View file

@ -0,0 +1,30 @@
import React, { PropTypes, Component } from 'react';
import { Button } from 'react-bootstrap';
const NewPostButton = (props, context) => {
({ModalTrigger, NewDocContainer, CanCreatePost} = Telescope.components);
return (
<ModalTrigger component={<Button bsStyle="primary">New Post</Button>}>
<CanCreatePost user={context.currentUser}>
<NewDocContainer
collection={Posts}
label="New Post"
methodName="posts.new"
successCallback={(post)=>{
Messages.flash("Post created.", "success");
Router.go('posts.single', post);
}}
/>
</CanCreatePost>
</ModalTrigger>
)
}
NewPostButton.contextTypes = {
currentUser: React.PropTypes.object
};
module.exports = NewPostButton;
export default NewPostButton;

View file

@ -42,12 +42,13 @@ class NewsletterForm extends Component {
renderForm() {
return (
<Formsy.Form onSubmit={this.subscribeEmail}>
<Formsy.Form className="newsletter-form" onSubmit={this.subscribeEmail}>
<Input
name="email"
value=""
label={this.props.labelText}
placeholder={this.props.labelText}
type="text"
layout="elementOnly"
/>
<Button bsStyle="primary">{this.props.buttonText}</Button>
</Formsy.Form>
@ -56,7 +57,7 @@ class NewsletterForm extends Component {
renderButton() {
return (
<Button onClick={this.subscribeUser} bsStyle="primary">{this.props.buttonText}</Button>
<Button className="newsletter-button" onClick={this.subscribeUser} bsStyle="primary">{this.props.buttonText}</Button>
)
}
@ -64,8 +65,8 @@ class NewsletterForm extends Component {
if (Telescope.settings.get("showBanner", true)) {
return (
<div className="newsletter">
<h3>{this.props.headerText}</h3>
{this.props.currentUser ? this.renderButton() : this.renderForm()}
<h4 className="newsletter-tagline">{this.props.headerText}</h4>
{this.context.currentUser ? this.renderButton() : this.renderForm()}
</div>
)
} else {
@ -75,7 +76,6 @@ class NewsletterForm extends Component {
}
NewsletterForm.propTypes = {
currentUser: React.PropTypes.object,
headerText: React.PropTypes.string,
labelText: React.PropTypes.string,
buttonText: React.PropTypes.string,
@ -89,5 +89,9 @@ NewsletterForm.defaultProps = {
successMessage: "Thanks for subscribing!"
};
NewsletterForm.contextTypes = {
currentUser: React.PropTypes.object
};
module.exports = NewsletterForm;
export default NewsletterForm;

View file

@ -9,6 +9,7 @@ Telescope.registerComponent("FlashMessages", require('./common/FlashMessages.jsx
Telescope.registerComponent("NewsletterForm", require('./common/NewsletterForm.jsx'));
Telescope.registerComponent("Icon", require('./common/Icon.jsx'));
Telescope.registerComponent("SearchForm", require('./common/SearchForm.jsx'));
Telescope.registerComponent("NewPostButton", require('./common/NewPostButton.jsx'));
// posts

View file

@ -4,10 +4,10 @@ const PostStats = ({post}) => {
return (
<div className="post-stats">
{post.score ? <span title="Score"><Icon name="score"/> {Math.floor(post.score*10000)/10000} <span className="sr-only">Score</span></span> : ""}
<span title="Upvotes"><Icon name="upvote"/> {post.upvotes} <span className="sr-only">Upvotes</span></span>
<span title="Clicks"><Icon name="clicks"/> {post.clickCount} <span className="sr-only">Clicks</span></span>
<span title="Views"><Icon name="views"/> {post.viewCount} <span className="sr-only">Views</span></span>
{post.score ? <span className="post-stat" title="Score"><Icon name="score"/> {Math.floor(post.score*10000)/10000} <span className="sr-only">Score</span></span> : ""}
<span className="post-stat" title="Upvotes"><Icon name="upvote"/> {post.upvotes} <span className="sr-only">Upvotes</span></span>
<span className="post-stat" title="Clicks"><Icon name="clicks"/> {post.clickCount} <span className="sr-only">Clicks</span></span>
<span className="post-stat" title="Views"><Icon name="views"/> {post.viewCount} <span className="sr-only">Views</span></span>
</div>
)
}

View file

@ -47,7 +47,7 @@ class Vote extends Component {
<a href="#" className="upvote-button" onClick={this.upvote}>
<Icon name="upvote" />
<div className="sr-only">Upvote</div>
<div className="vote-count">{post.baseScore}</div>
<div className="vote-count">{post.baseScore || 0}</div>
</a>
</div>
)

View file

@ -69,6 +69,7 @@ class PostItem extends Component {
<UserAvatar user={post.user} size="small"/>
<UserName user={post.user}/>
<div className="post-date">{moment(post.postedAt).fromNow()}</div>
<div className="post-comments"><a href={Posts.getLink(post)}>{post.commentCount}&nbsp;comments</a></div>
<PostStats post={post} />
{this.renderActions()}

View file

@ -1,8 +1,16 @@
const PostListHeader = () => {
({PostViews, SearchForm} = Telescope.components)
({PostViews, SearchForm, ListContainer, CategoriesList} = Telescope.components)
return <div className="post-list-header"><PostViews /><SearchForm/></div>
return (
<div className="post-list-header">
<div className="post-list-categories">
<ListContainer collection={Categories} limit={0} resultsPropName="categories" component={CategoriesList}/>
</div>
<PostViews />
<SearchForm/>
</div>
)
}
module.exports = PostListHeader;

View file

@ -12,17 +12,26 @@ const PostViews = (props, context) => {
}
const currentRoute = context.currentRoute;
const currentView = currentRoute.queryParams.view || props.defaultView;
// console.log(currentRoute);
return (
<div className="post-views">
<ButtonGroup>
{views.map(view => <Button className={currentRoute.queryParams.view === view ? "post-view-active" : ""} bsStyle="default" key={view} href={Router.extendPathWithQueryParams("posts.list", {}, {view: view})}>{view}</Button>)}
{views.map(view => <Button className={currentView === view ? "post-view-active" : ""} bsStyle="default" key={view} href={Router.extendPathWithQueryParams("posts.list", {}, {view: view})}>{view}</Button>)}
</ButtonGroup>
</div>
)
}
PostViews.propTypes = {
defaultView: React.PropTypes.string
}
PostViews.defaultProps = {
defaultView: "top"
}
PostViews.contextTypes = {
currentRoute: React.PropTypes.object
};

View file

@ -0,0 +1,35 @@
.cheatsheet h1{
margin-bottom: 20px;
}
.cheatsheet-wrapper{
display: flex;
}
.cheatsheet-block{
flex: 1;
margin-right: 20px;
}
.cheatsheet-block:last-of-type{
margin-right: 0;
}
.cheatsheet ul{
list-style-type: none;
margin-bottom: 20px;
padding-left: 0px;
}
.cheatsheet ul li{
margin-bottom: 10px;
}
.cheatsheet h2{
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #ddd;
}
.cheatsheet h3{
margin-bottom: 10px;
font-weight: bold;
}
.cheatsheet code{
font-size: 13px;
}

View file

@ -1,3 +0,0 @@
.footer{
text-align: center;
}

View file

@ -1,3 +1,13 @@
body{
font-family: "Source Sans Pro", "Helvetica Neue", "Helvetica", sans-serif;
}
.main, .footer, .header{
margin-left: auto;
margin-right: auto;
max-width: 1200px;
}
.main{
margin-bottom: $vmargin;
}

View file

@ -0,0 +1,4 @@
.header-wrapper{
background: $light-grey;
margin-bottom: $vmargin;
}

View file

@ -2,4 +2,21 @@
background: $white;
border: 1px solid $light-border;
border-radius: 3px;
@include flex-center;
justify-content: center;
padding: $vmargin $hmargin;
margin-bottom: $vmargin;
.newsletter-tagline{
margin: 0 $hmargin 0 0;
font-size: 1.35rem;
}
.newsletter-button{
}
.newsletter-form{
@include flex-center;
.form-control{
margin: 0 5px 0 0;
}
}
}

View file

@ -0,0 +1,10 @@
.footer{
text-align: center;
margin-bottom: $vmargin;
}
.search-form{
.form-group{
margin-bottom: 0;
}
}

View file

@ -1,15 +1,15 @@
.post-list-header{
display: flex;
align-items: center;
@include flex-center;
justify-content: space-between;
margin-bottom: $vmargin;
}
.post-views{
a{
border: 1px solid $light-border;
@include border;
@include blueHover;
// border-radius: 3px;
// @include border-radius;
// padding: 3px 5px;
// margin-right: 5px;
&.post-view-active{
@ -18,16 +18,15 @@
}
}
.post-list-content{
border-top: 1px solid $light-border;
border-top: $border;
// padding-top: 15px;
// margin-top: 15px;
margin-bottom: $vmargin;
}
.post-item{
display: flex;
align-items: center;
border-bottom: 1px solid $light-border;
@include flex-center;
border-bottom: $border;
padding: $vmargin 5px;
// margin-bottom: 15px;
&.post-sticky{
@ -41,11 +40,10 @@
}
.upvote-button{
border: 1px solid $light-border;
border-radius: 3px;
display: flex;
@include border;
@include border-radius;
@include flex-center;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 3px 5px;
.icon{
@ -72,8 +70,7 @@
.post-title{
font-size: 1.35rem;
margin-bottom: 5px;
display: flex;
align-items: center;
@include flex-center;
.post-title-link{
color: $black;
&, &:active, &:hover{
@ -83,14 +80,13 @@
}
.post-categories{
display: flex;
align-items: center;
@include flex-center;
margin-left: 5px;
a{
display: block;
font-size: 0.8rem;
border: 1px solid $light-grey;
border-radius: 3px;
@include border;
@include border-radius;
margin-right: 5px;
padding: 2px 6px;
@include blueHover;
@ -99,23 +95,25 @@
.post-meta{
font-size: 0.9rem;
display: flex;
align-items: center;
.user-avatar, .user-name, .post-date, .post-stats, .post-actions{
@include flex-center;
.user-avatar{
margin-right: 5px;
}
.user-name, .post-date, .post-comments, .post-stats, .post-actions{
margin-right: $hmargin;
}
}
.post-date{
.post-date, .post-comments{
color: $medium-text;
}
.post-stats{
border: 1px solid $light-border;
border-radius: 3px;
@include border;
@include border-radius;
font-size: 0.8rem;
>span{
border-right: 1px solid $light-border;
.post-stat{
border-right: $border;
padding: 2px 5px;
display: inline-block;
&:last-child{
@ -125,13 +123,11 @@
}
.post-actions{
display: flex;
align-items: center;
@include flex-center;
}
.post-comments{
display: flex;
align-items: center;
@include flex-center;
}
.post-commenters{
@ -143,8 +139,8 @@
.post-load-more{
display: block;
text-align: center;
border: 1px solid $light-border;
border-radius: 3px;
@include border;
@include border-radius;
font-size: 1.25rem;
padding: 10px 20px;
@include blueHover;

View file

@ -1,6 +1,8 @@
$hmargin: 10px;
$vmargin: 15px;
$border: 1px solid $light-border;
@mixin blueHover{
&:hover{
background: $blue;
@ -9,3 +11,16 @@ $vmargin: 15px;
text-decoration: none;
}
}
@mixin flex-center{
display: flex;
align-items: center;
}
@mixin border-radius{
border-radius: .25rem;
}
@mixin border{
border: $border;
}

View file

@ -4,45 +4,37 @@
@import "global";
@import "categories";
@import "cheatsheet";
@import "comments";
@import "common";
@import "header";
@import "newsletter";
@import "other";
@import "posts";
body{
background: #eee;
color: $black;
}
.wrapper{
padding: 15px;
}
.main{
background: #fff;
padding: 15px;
margin: 10px 0;
border: 1px #ccc solid;
}
.post-views, .logo, .nav, .alt-accounts-log-in-buttons{
margin-bottom: 15px;
}
.post-views ul, .categories ul, .post-categories ul, .post-commenters ul{
list-style-type: none;
margin: 0;
padding: 0;
}
// .post-views, .logo, .nav, .alt-accounts-log-in-buttons{
// margin-bottom: 15px;
// }
.post-views li, .categories li, .post-categories li, .post-commenters li{
display: inline-block;
margin-right: 5px;
border: 1px solid #ddd;
padding: 3px 5px;
background: #efefef;
}
// .post-views ul, .categories ul, .post-categories ul, .post-commenters ul{
// list-style-type: none;
// margin: 0;
// padding: 0;
// }
// .post-views li, .categories li, .post-categories li, .post-commenters li{
// display: inline-block;
// margin-right: 5px;
// border: 1px solid #ddd;
// padding: 3px 5px;
// background: #efefef;
// }
.comment-node{
border-left: 10px #efefef solid;
@ -69,40 +61,6 @@ code{
padding: 3px 6px;
}
.cheatsheet h1{
margin-bottom: 20px;
}
.cheatsheet-wrapper{
display: flex;
}
.cheatsheet-block{
flex: 1;
margin-right: 20px;
}
.cheatsheet-block:last-of-type{
margin-right: 0;
}
.cheatsheet ul{
list-style-type: none;
margin-bottom: 20px;
padding-left: 0px;
}
.cheatsheet ul li{
margin-bottom: 10px;
}
.cheatsheet h2{
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #ddd;
}
.cheatsheet h3{
margin-bottom: 10px;
font-weight: bold;
}
.cheatsheet code{
font-size: 13px;
}
.avatar{
height: 24px;

View file

@ -25,8 +25,10 @@ Package.onUse(function (api) {
'lib/stylesheets/_variables.scss',
'lib/stylesheets/_global.scss',
'lib/stylesheets/_categories.scss',
'lib/stylesheets/_cheatsheet.scss',
'lib/stylesheets/_comments.scss',
'lib/stylesheets/_common.scss',
'lib/stylesheets/_header.scss',
'lib/stylesheets/_other.scss',
'lib/stylesheets/_posts.scss',
'lib/stylesheets/_newsletter.scss',
'lib/stylesheets/_users.scss',