Update Blog Layout
Summary: Updated the blog's styling to make it more readable. * BlogPageLayout (blog index) - Only excerpts from each article are now shown, as opposed to the entire article. * BlogPost - Broken up into headers, footers. Reorder header so that the blog post title is closer to the content. Adds support for hero images (visible from the blog index). Adds Facebook, Twitter social share buttons. List items are properly spaced now. Blog index: ![screencapture-localhost-8079-react-native-blog-1471905976431](https://cloud.githubusercontent.com/assets/165856/17874405/4ee4fc22-6880-11e6-8344-2ed823f6000e.png) Single blog post: ![screencapture-localhost-8079-react-native-blog-2016-08-12-react-native-meetup-san-francisco-html-1471905997923](https://cloud.githubusercontent.com/assets/165856/17874407/52af9e7a-6880-11e6-99f0-91f90331aced.png) Closes https://github.com/facebook/react-native/pull/9532 Differential Revision: D3758524 Pulled By: bestander fbshipit-source-id: 6385a3e98a3a44343c3b1d3105a32023b748c2c6
This commit is contained in:
Родитель
a718f14af7
Коммит
777a9c0a0e
|
@ -2,6 +2,7 @@
|
|||
title: Introducing Hot Reloading
|
||||
author: Martín Bigio
|
||||
authorURL: https://twitter.com/martinbigio
|
||||
authorTwitter: martinbigio
|
||||
---
|
||||
|
||||
React Native's goal is to give you the best possible developer experience. A big part of it is the time it takes between you save a file and be able to see the changes. Our goal is to get this feedback loop to be under 1 second, even as your app grows.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
title: Toward Better Documentation
|
||||
author: Kevin Lacker
|
||||
authorURL: https://twitter.com/lacker
|
||||
authorTwitter: lacker
|
||||
---
|
||||
|
||||
Part of having a great developer experience is having great documentation. A lot goes into creating good docs - the ideal documentation is concise, helpful, accurate, complete, and delightful. Recently we've been working hard to make the docs better based on your feedback, and we wanted to share some of the improvements we've made.
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
title: San Francisco Meetup Recap
|
||||
author: Héctor Ramos
|
||||
authorURL: https://twitter.com/hectorramos
|
||||
authorTwitter: hectorramos
|
||||
hero: /react-native/blog/img/rnmsf-august-2016-hero.jpg
|
||||
---
|
||||
|
||||
![](/react-native/blog/img/rnmsf-august-2016-hero.jpg)
|
||||
|
||||
Last week I had the opportunity to attend the [React Native Meetup](http://www.meetup.com/React-Native-San-Francisco/photos/27168649/#452793854) at Zynga’s San Francisco office. With around 200 people in attendance, it served as a great place to meet other developers near me that are also interested in React Native.
|
||||
|
||||
I was particularly interested in learning more about how React and React Native are used at companies like Zynga, Netflix, and Airbnb. The agenda for the night would be as follows:
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
var Marked = require('Marked');
|
||||
var React = require('React');
|
||||
var BlogPostHeader = require('BlogPostHeader');
|
||||
var BlogPostFooter = require('BlogPostFooter');
|
||||
var ReadMoreLink = require('ReadMoreLink');
|
||||
|
||||
var BlogPost = React.createClass({
|
||||
render: function() {
|
||||
|
@ -28,16 +31,27 @@ var BlogPost = React.createClass({
|
|||
][parseInt(match[2], 10) - 1];
|
||||
var day = parseInt(match[3], 10);
|
||||
|
||||
var postedOnDate = month + ' ' + day + ', ' + year;
|
||||
|
||||
var footer = <BlogPostFooter post={post} postedOnDate={postedOnDate} />;
|
||||
|
||||
if (this.props.excerpt) {
|
||||
var excerptLength = 50;
|
||||
var words = content.trim().split(' ');
|
||||
if (words.length > excerptLength) {
|
||||
content = words.slice(0,excerptLength).join(' ') + '...';
|
||||
footer = <ReadMoreLink href={'/react-native/blog/' + post.path} />;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="article">
|
||||
<h1>{post.title}</h1>
|
||||
<p className="meta">
|
||||
{month} {day}, {year} by{' '}
|
||||
<a href={post.authorURL} target="_blank">{post.author}</a>
|
||||
</p>
|
||||
<hr />
|
||||
<Marked>{content}</Marked>
|
||||
</div>
|
||||
<article>
|
||||
<BlogPostHeader post={post} postedOnDate={postedOnDate} />
|
||||
<div className="entry-content">
|
||||
<Marked>{content}</Marked>
|
||||
</div>
|
||||
{footer}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule BlogPostFooter
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
|
||||
var BlogPostFooter = React.createClass({
|
||||
render: function() {
|
||||
var post = this.props.post;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<aside className="author-info">
|
||||
<p className="posted-on">Posted on {this.props.postedOnDate}</p>
|
||||
<p className="name-title">
|
||||
<a href={post.authorURL} target="_blank">
|
||||
{post.author}
|
||||
</a>
|
||||
</p>
|
||||
</aside>
|
||||
<aside className="entry-share">
|
||||
<h3 className="small-title">Share this post</h3>
|
||||
<div className="social-buttons">
|
||||
<div
|
||||
className="fb-like"
|
||||
data-layout="standard"
|
||||
data-share="true"
|
||||
data-width="225"
|
||||
data-show-faces="false">
|
||||
</div>
|
||||
<a href="https://twitter.com/share" className="twitter-share-button" data-text={post.title} data-url={"http://facebook.github.io/react-native/blog/" + post.path} data-via={post.authorTwitter} data-related="reactnative" data-show-count="false">Tweet</a>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = BlogPostFooter;
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule BlogPostHeader
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
|
||||
var BlogPostHeader = React.createClass({
|
||||
render: function() {
|
||||
var post = this.props.post;
|
||||
|
||||
var hero;
|
||||
if (post.hero) {
|
||||
hero = <img src={post.hero} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="entry-header">
|
||||
{hero}
|
||||
<h4 className="entry-authordate">
|
||||
<a href={post.authorURL} target="_blank"
|
||||
className="author">
|
||||
{post.author}
|
||||
</a>
|
||||
{' — '}
|
||||
<span className="date">{this.props.postedOnDate}</span>
|
||||
</h4>
|
||||
<h1 className="entry-title">{post.title}</h1>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = BlogPostHeader;
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ReadMoreLink
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
|
||||
var ReadMoreLink = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<footer className="entry-readmore">
|
||||
<a href={this.props.href} className="btn">
|
||||
Read more
|
||||
</a>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ReadMoreLink;
|
|
@ -46,7 +46,8 @@ var Site = React.createClass({
|
|||
<script type="text/javascript">{'try{Typekit.load();}catch(e){}'}</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script dangerouslySetInnerHTML={{__html: `window.fbAsyncInit = function() {FB.init({appId:'1677033832619985',xfbml:true,version:'v2.7'});};(function(d, s, id){var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) {return;}js = d.createElement(s); js.id = id;js.src = '//connect.facebook.net/en_US/sdk.js';fjs.parentNode.insertBefore(js, fjs);}(document, 'script','facebook-jssdk'));`}} />
|
||||
<script dangerouslySetInnerHTML={{__html: `window.twttr=(function(d,s, id){var js,fjs=d.getElementsByTagName(s)[0],t=window.twttr||{};if(d.getElementById(id))return t;js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js, fjs);t._e = [];t.ready = function(f) {t._e.push(f);};return t;}(document, "script", "twitter-wjs"));`}} />
|
||||
<div className="container">
|
||||
<div className="nav-main">
|
||||
<div className="wrap">
|
||||
|
|
|
@ -39,7 +39,12 @@ var BlogPageLayout = React.createClass({
|
|||
{MetadataBlog.files
|
||||
.slice(page * perPage, (page + 1) * perPage)
|
||||
.map((post) => {
|
||||
return <BlogPost post={post} content={post.content} />
|
||||
return (
|
||||
<div>
|
||||
<BlogPost post={post} content={post.content} excerpt={true} />
|
||||
<hr />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<div className="docs-prevnext">
|
||||
|
|
|
@ -28,7 +28,9 @@ var BlogPostLayout = React.createClass({
|
|||
<section className="content wrap documentationContent">
|
||||
<BlogSidebar title={this.props.metadata.title} />
|
||||
<div className="inner-content">
|
||||
<BlogPost post={this.props.metadata} content={this.props.children} />
|
||||
<BlogPost
|
||||
post={this.props.metadata}
|
||||
content={this.props.children} />
|
||||
</div>
|
||||
</section>
|
||||
</Site>
|
||||
|
|
|
@ -1649,6 +1649,117 @@ input#algolia-doc-search:focus {
|
|||
|
||||
/** Blog **/
|
||||
|
||||
.article {
|
||||
margin: 0 0 40px 0;
|
||||
.entry-header {
|
||||
margin: 40px 0 0 0;
|
||||
}
|
||||
|
||||
.entry-header h1 {
|
||||
margin: 0;
|
||||
font-size: 33px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.entry-header h4 {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.entry-header .author {
|
||||
color: #5A6b77;
|
||||
}
|
||||
|
||||
.entry-header .date {
|
||||
color: #66637A;
|
||||
}
|
||||
|
||||
.entry-readmore {
|
||||
margin: 12px 0 0;
|
||||
}
|
||||
|
||||
.entry-share {
|
||||
padding: 36px 0;
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.small-title {
|
||||
font-size: 10px;
|
||||
color: #66637A;
|
||||
letter-spacing: .4rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.entry-share .small-title {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.social-buttons {
|
||||
padding-top: 7px;
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
article {
|
||||
margin: 0 0 40px 0;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
article h2 {
|
||||
font-size: 26px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
article li {
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.author-info {
|
||||
margin-top: 26px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
padding-bottom: 20px
|
||||
}
|
||||
|
||||
.posted-on {
|
||||
font-size: 12px;
|
||||
color: rgba(102,99,122,.29);
|
||||
margin-bottom: 0;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.name-title {
|
||||
margin-top: 2px;
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
margin: 3px 0 5px;
|
||||
color: #5A6B77;
|
||||
}
|
||||
|
||||
.name-title a {
|
||||
color: #5A6B77;
|
||||
}
|
||||
|
||||
|
||||
.btn {
|
||||
background: 0 0;
|
||||
color: #05A5D1;
|
||||
min-width: 0;
|
||||
border: 1px solid #05A5D1;
|
||||
display: inline-block;
|
||||
padding: 9px 18px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.btn a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче