Merge pull request from rschamp/intro

Add homepage intro component
This commit is contained in:
Andrew Sliwinski 2015-09-10 17:13:09 -07:00
commit 724551b40c
8 changed files with 378 additions and 1 deletions

View file

@ -37,6 +37,7 @@
"jsx-loader": "0.13.2",
"node-sass": "3.3.2",
"react": "0.13.3",
"react-modal": "0.3.0",
"react-slick": "0.7.0",
"sass-loader": "2.0.1",
"slick-carousel": "1.5.8",

View file

@ -0,0 +1,93 @@
var React = require('react');
var Modal = require('../modal/modal.jsx');
require('./intro.scss');
Modal.setAppElement(document.getElementById('view'));
module.exports = React.createClass({
propTypes: {
projectCount: React.PropTypes.number
},
getDefaultProps: function() {
return {
projectCount: 10569070
};
},
getInitialState: function () {
return {
videoOpen: false
};
},
showVideo: function () {
this.setState({videoOpen: true});
},
closeVideo: function () {
this.setState({videoOpen: false});
},
render: function () {
return (
<div className='intro'>
<div className="content">
<h1>
Create stories, games, and animations<br />
Share with others around the world
</h1>
<div className="sprites">
<a className='sprite sprite-1' href='/projects/editor/?tip_bar=getStarted'>
<img
className='costume costume-1'
src='//cdn.scratch.mit.edu/scratchr2/static/images/cat-a.png' />
<img
className='costume costume-2'
src='//cdn.scratch.mit.edu/scratchr2/static/images/cat-b.png' />
<div className='circle'></div>
<div className='text'>TRY IT OUT</div>
</a>
<a className='sprite sprite-2' href='/starter_projects/'>
<img
className='costume costume-1'
src='//cdn.scratch.mit.edu/scratchr2/static/images/tera-a.png' />
<img
className='costume costume-2'
src='//cdn.scratch.mit.edu/scratchr2/static/images/tera-b.png' />
<div className='circle'></div>
<div className='text'>SEE EXAMPLES</div>
</a>
<a className='sprite sprite-3' href='#'>
<img
className='costume costume-1'
src='//cdn.scratch.mit.edu/scratchr2/static/images/gobo-a.png' />
<img
className='costume costume-2'
src='//cdn.scratch.mit.edu/scratchr2/static/images/gobo-b.png' />
<div className='circle'></div>
<div className='text'>JOIN SCRATCH</div>
<div className='text subtext'>( it&rsquo;s free )</div>
</a>
</div>
<div className='description'>
A creative learning community with
<span className='project-count'> {this.props.projectCount.toLocaleString()} </span>
projects shared
</div>
<div className='links'>
<a href='/about/'>ABOUT SCRATCH</a>
<a href='/educators/'>FOR EDUCATORS</a>
<a className='last' href='/parents/'>FOR PARENTS</a>
</div>
</div>
<div className='video'>
<div className='play-button' onClick={this.showVideo}></div>
<img src='//cdn.scratch.mit.edu/scratchr2/static/images/hp-video-screenshot.png' />
</div>
<Modal
className='video-modal'
isOpen={this.state.videoOpen}
onRequestClose={this.closeVideo}>
<iframe src='//player.vimeo.com/video/65583694?title=0&amp;byline=0&amp;portrait=0' />
</Modal>
</div>
);
}
});

View file

@ -0,0 +1,203 @@
.intro {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
align-content: flex-start;
margin-top: 20px;
margin-bottom: 20px;
.content {
display: inline-block;
width: calc(66% - 20px);
h1 {
color: #F9A739;
font-weight: 400;
}
}
.sprites {
position: relative;
clear: both;
overflow: hidden;
&:after {
display: block;
visibility: hidden;
content: " ";
clear: both;
height: 0;
}
}
.sprite {
position: relative;
float: left;
width: 193px;
height: 136px;
overflow: hidden;
.costume, .circle, .text {
position: absolute;
}
.costume {
z-index: 2;
left: 0;
}
.costume-2 {
display: none;
}
&:hover .costume-1 {
display: none;
}
&:hover .costume-2 {
display: block;
}
.circle {
z-index: 0;
border-radius: 50%;
display: block;
width: 112px;
height: 112px;
box-shadow: 0px 0px 5px #fff;
top: 15px;
left: 43px;
}
$text-bg-color: #F1F3F4;
.text {
z-index: 1;
font-size: 12px;
font-weight: 700;
left: 35px;
padding-left: 40px;
padding-right: 10px;
white-space: nowrap;
background-color: $text-bg-color;
border: 2px solid $text-bg-color;
}
.subtext {
background-color: transparent;
font-weight: 400;
font-size: 12px;
text-shadow: none;
border: none;
}
$sprite-1-bgcolor: #9C0;
$sprite-2-bgcolor: #C2479D;
$sprite-3-bgcolor: #199ED7;
&.sprite-1 .circle { background-color: $sprite-1-bgcolor; }
&.sprite-2 .circle { background-color: $sprite-2-bgcolor; }
&.sprite-3 .circle { background-color: $sprite-3-bgcolor; }
&:hover.sprite-1 .circle { box-shadow: 0 0 10px 2px $sprite-1-bgcolor; }
&:hover.sprite-2 .circle { box-shadow: 0 0 10px 2px $sprite-2-bgcolor; }
&:hover.sprite-3 .circle { box-shadow: 0 0 10px 2px $sprite-3-bgcolor; }
&.sprite-1 .text { color: $sprite-1-bgcolor; top: 60px; left: 50px; }
&.sprite-2 .text { color: $sprite-2-bgcolor; top: 77px; left: 50px; }
&.sprite-3 .text { color: $sprite-3-bgcolor; top: 37px; left: 45px; }
&.sprite-3 .subtext {
top: 63px;
left: 60px;
color: #fff;
}
}
.description {
font-size: 17px;
margin-top: 10px;
}
.project-count {
color: hsl(318, 50%, 52%);
font-weight: 700;
font-size: 18px;
}
.links {
font-size: 12px;
margin-top: 20px;
a {
border-right: 1px solid #000;
padding: 0 5px;
&:last-child {
border-right: 0;
}
}
}
.video {
display: inline-block;
height: 208px;
width: 34%;
position: relative;
padding: 10px;
border: 1px solid #eee;
border-radius: 5px;
background-color: #f7f7f7;
text-align: center;
box-shadow: 0 2px 3px;
}
.play-button {
border-radius: 20px;
display: block;
width: 70px;
height: 50px;
left: calc(50% - 35px);
top: calc(50% - 25px);
background-color: #666;
border: 5px solid #ccc;
opacity: 0.8;
&, &:after {
position: absolute;
cursor: pointer;
margin: 0;
padding: 0;
}
&:after {
left: 28px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
pointer-events: none;
border-color: rgba(255, 255, 255, 0);
border-left-color: #fff;
border-width: 18px;
top: 37px;
margin-top: -30px;
}
}
}
.video-modal {
$video-width: 570px;
$video-height: 357px;
$padding: 15px;
width: $video-width;
height: $video-height;
padding: $padding;
top: 50%;
bottom: auto;
left: 50%;
right: auto;
margin-left: -($video-width + $padding * 2)/2;
margin-top: -($video-height + $padding * 2)/2;
iframe {
width: $video-width;
height: $video-height;
border: 0;
}
}

View file

@ -0,0 +1,22 @@
var React = require('react');
var Modal = require('react-modal');
require('./modal.scss');
module.exports = React.createClass({
statics: {
setAppElement: Modal.setAppElement
},
requestClose: function() {
return this.refs.modal.portal.requestClose();
},
render: function() {
return (
<Modal ref='modal' {... this.props}>
<div className='modal-close' onClick={this.requestClose}></div>
{this.props.children}
</Modal>
);
}
});

View file

@ -0,0 +1,50 @@
/* Copied from the un-styleable react-modal */
.ReactModal__Overlay {
background-color: rgba(0, 0, 0, 0.75);
z-index: 100;
}
.ReactModal__Content {
position: absolute;
top: 40px;
left: 40px;
right: 40px;
bottom: 40px;
background: #fff;
overflow: visible;
-webkit-overflow-scrolling: touch;
border-radius: 6px;
outline: none;
padding: 20px;
}
@media (max-width: 768px) {
.ReactModal__Content {
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
padding: 10px;
}
}
.modal-close {
$modal-close-size: 20px;
position: absolute;
right: 0;
top: 0;
border-radius: $modal-close-size/2;
border: 2px solid #ddd;
background-color: #666;
color: #fff;
width: $modal-close-size;
height: $modal-close-size;
margin-top: -$modal-close-size/2;
margin-right: -$modal-close-size/2;
text-align: center;
line-height: $modal-close-size;
font-size: $modal-close-size;
cursor: pointer;
&:before {
content: "x";
}
}

View file

@ -1,5 +1,6 @@
#navigation {
position: fixed;
z-index: 10;
display: block;
top: 0;
left: 0;

View file

@ -20,6 +20,11 @@ h1, h2, h3, h4 {
font-weight: 700;
}
h1 {
font-size: 1.625rem;
line-height: 2.125rem;
}
h4 {
font-size: 1.0rem;
line-height: 1.1rem;

View file

@ -5,6 +5,7 @@ var Session = require('../../mixins/session.jsx');
var Box = require('../../components/box/box.jsx');
var Carousel = require('../../components/carousel/carousel.jsx');
var Intro = require('../../components/intro/intro.jsx');
var News = require('../../components/news/news.jsx');
require('./splash.scss');
@ -16,6 +17,7 @@ var View = React.createClass({
],
getInitialState: function () {
return {
projectCount: 10569070,
activity: [],
news: [],
featured: require('./featured.json')
@ -29,7 +31,7 @@ var View = React.createClass({
render: function () {
return (
<div className="inner">
<div className="intro"></div>
<Intro projectCount={this.state.projectCount} />
<div className="activity"></div>
<News />
{this.state.featured.map(function(set){