2018 Hour of Code Banners

* add Top and Middle HoC banners
* banners share styles
* add new assets for banners
* update presentation to check date to determine whether to show the HoC banners.
This commit is contained in:
chrisgarrity 2018-11-07 16:02:43 -05:00
parent dded9e9c0f
commit f2f4a6ac7c
9 changed files with 315 additions and 22 deletions

View file

@ -0,0 +1,113 @@
@import "../../../colors";
@import "../../../frameless";
$tile-height: 244px;
.hoc-banner {
display: flex;
position: relative;
background-color: $ui-aqua;
background-image: url("/images/hoc/bg-pattern.png");
background-size: cover;
padding: 0;
height: 25rem;
overflow: hidden;
justify-content: center;
&.mod-middle-banner {
background-color: $ui-purple;
}
.hoc-container {
margin: auto;
width: $desktop;
height: 25rem;
justify-content: flex-start;
.hoc-title-container {
margin: 1.5rem 0;
width: 100%;
justify-content: space-between;
}
}
.hoc-banner-images {
display: flex;
width: $desktop;
justify-content: space-between;
}
.hoc-banner-image {
border: 2px solid $ui-aqua;
border-radius: 16px;
background-color: $ui-white;
width: $cols4;
height: $tile-height;
overflow: hidden;
box-sizing: border-box;
justify-content: flex-start;
&.mod-middle-image {
border: 2px solid $ui-purple;
}
img {
width: $cols4;
height: auto;
}
.hoc-image-text {
margin: auto auto;
color: $ui-blue;
font-size: 1rem;
font-weight: bold;
}
}
.hoc-header{
color: $ui-white;
}
.hoc-header {
font-size: 2rem;
}
.hoc-more-activities {
border-radius: 10px;
background-color: $ui-white;
padding: .5rem 1rem;
color: $ui-blue;
font-size: .75rem;
font-weight: bold;
img {
margin-right: .25rem;
width: 20px;
height: 20px;
vertical-align: text-bottom;
}
}
}
@media only screen and (min-width: $tablet) and (max-width: $desktop) {
.hoc-banner {
height: 23.5rem;
.hoc-container {
bottom: 4rem;
width: $tablet;
}
.hoc-banner-images {
width: $tablet;
}
.hoc-banner-image {
width: $cols4;
}
}
.hoc-hideable {
display: none;
}
}

View file

@ -0,0 +1,63 @@
const FormattedMessage = require('react-intl').FormattedMessage;
const injectIntl = require('react-intl').injectIntl;
const React = require('react');
const MediaQuery = require('react-responsive').default;
const frameless = require('../../../lib/frameless');
const FlexRow = require('../../../components/flex-row/flex-row.jsx');
const TitleBanner = require('../../../components/title-banner/title-banner.jsx');
require('./hoc-banner.scss');
const MiddleBanner = () => (
<TitleBanner className="hoc-banner mod-middle-banner">
<FlexRow className="hoc-container column">
<FlexRow className="hoc-title-container">
<h1 className="hoc-header">
<FormattedMessage id="hocbanner.title" />
</h1>
<a
className="hoc-more-activities button"
href="/tips"
>
<img src="/svgs/tutorials.svg" />
<FormattedMessage id="hocbanner.moreActivities" />
</a>
</FlexRow>
<FlexRow className="hoc-banner-images">
<a href="http://localhost:8333/projects/editor/?tip_bar=name">
<FlexRow className="hoc-banner-image mod-middle-image column">
<img src="/images/ttt/animate-your-name.jpg" />
<div className="hoc-image-text">
<FormattedMessage id="hocbanner.name" />
</div>
</FlexRow>
</a>
<a href="http://localhost:8333/projects/editor/?tip_bar=fly">
<FlexRow className="hoc-banner-image mod-middle-image column">
<img src="/images/ttt/make-it-fly.jpg" />
<div className="hoc-image-text">
<FormattedMessage id="hocbanner.fly" />
</div>
</FlexRow>
</a>
<MediaQuery
key="frameless-desktop"
minWidth={frameless.desktop}
>
<a href="http://localhost:8333/projects/editor/?tip_bar=pong">
<FlexRow className="hoc-banner-image mod-middle-image column">
<img src="/images/ttt/pong-game.jpg" />
<div className="hoc-image-text">
<FormattedMessage id="hocbanner.pong" />
</div>
</FlexRow>
</a>
</MediaQuery>
</FlexRow>
</FlexRow>
</TitleBanner>
);
module.exports = injectIntl(MiddleBanner);

View file

@ -0,0 +1,63 @@
const FormattedMessage = require('react-intl').FormattedMessage;
const injectIntl = require('react-intl').injectIntl;
const React = require('react');
const MediaQuery = require('react-responsive').default;
const frameless = require('../../../lib/frameless');
const FlexRow = require('../../../components/flex-row/flex-row.jsx');
const TitleBanner = require('../../../components/title-banner/title-banner.jsx');
require('./hoc-banner.scss');
const TopBanner = () => (
<TitleBanner className="hoc-banner">
<FlexRow className="hoc-container column">
<FlexRow className="hoc-title-container">
<h1 className="hoc-header">
<FormattedMessage id="hocbanner.title" />
</h1>
<a
className="hoc-more-activities button"
href="https://beta.scratch.mit.edu/?tutorial=all"
>
<img src="/svgs/tutorials.svg" />
<FormattedMessage id="hocbanner.moreActivities" />
</a>
</FlexRow>
<FlexRow className="hoc-banner-images">
<MediaQuery
key="frameless-desktop"
minWidth={frameless.desktop}
>
<a href="https://beta.scratch.mit.edu/?tutorial=getStarted">
<FlexRow className="hoc-banner-image column">
<img src="/images/hoc/getting-started.jpg" />
<div className="hoc-image-text">
<FormattedMessage id="hocbanner.gettingStarted" />
</div>
</FlexRow>
</a>
</MediaQuery>
<a href="https://beta.scratch.mit.edu/?tutorial=animations-that-talk">
<FlexRow className="hoc-banner-image column">
<img src="/images/hoc/create-animations-that-talk.png" />
<div className="hoc-image-text">
<FormattedMessage id="hocbanner.animationTalk" />
</div>
</FlexRow>
</a>
<a href="https://beta.scratch.mit.edu/?tutorial=animate-an-adventure-game">
<FlexRow className="hoc-banner-image column">
<img src="/images/hoc/create-an-adventure-game.jpg" />
<div className="hoc-image-text">
<FormattedMessage id="hocbanner.adventureGame" />
</div>
</FlexRow>
</a>
</FlexRow>
</FlexRow>
</TitleBanner>
);
module.exports = injectIntl(TopBanner);

View file

@ -32,13 +32,20 @@ const RemixProjectMessage = require('./activity-rows/remix-project.jsx');
const ShareProjectMessage = require('./activity-rows/share-project.jsx'); const ShareProjectMessage = require('./activity-rows/share-project.jsx');
// Beta Banner Components // Beta Banner Components
const TopBanner = require('./beta/top-banner.jsx'); // const TopBanner = require('./beta/top-banner.jsx');
const SmallTopBanner = require('./beta/small-top-banner.jsx'); const SmallTopBanner = require('./beta/small-top-banner.jsx');
const MiddleBanner = require('./beta/middle-banner.jsx'); // const MiddleBanner = require('./beta/middle-banner.jsx');
const BETA_LAUNCH_TIME = 1533128400000; // August 1 at 9am ET const BETA_LAUNCH_TIME = 1533128400000; // August 1 at 9am ET
const SMALL_BANNER_TIME = 1534942800000; // August 22 at 9am ET const SMALL_BANNER_TIME = 1534942800000; // August 22 at 9am ET
// Hour of Code Banner Components
const TopBanner = require('./hoc/top-banner.jsx');
const MiddleBanner = require('./hoc/middle-banner.jsx');
const HOC_START_TIME = 1543813201000; // 12:01 am Dec 3rd
const HOC_END_TIME = 1544806799000; // 11:59 Dec 14th
require('./splash.scss'); require('./splash.scss');
class ActivityList extends React.Component { class ActivityList extends React.Component {
@ -279,21 +286,6 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
); );
} }
if (
this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length === 0 &&
Date.now() >= BETA_LAUNCH_TIME // Show middle banner on and after August 1
) {
rows.push(
<MediaQuery
key="frameless-tablet"
minWidth={frameless.tablet}
>
<MiddleBanner />
</MediaQuery>
);
}
if (this.props.featuredGlobal.scratch_design_studio && if (this.props.featuredGlobal.scratch_design_studio &&
this.props.featuredGlobal.scratch_design_studio.length > 4) { this.props.featuredGlobal.scratch_design_studio.length > 4) {
@ -439,6 +431,18 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
messages={messages} messages={messages}
/> />
] : []} ] : []}
{
this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length === 0 && // Only show top banner if user is not logged in
Date.now() >= HOC_START_TIME &&
Date.now() < HOC_END_TIME &&
<MediaQuery
key="frameless-tablet"
minWidth={frameless.tablet}
>
<TopBanner />
</MediaQuery>
}
{ {
this.props.sessionStatus === sessionActions.Status.FETCHED && this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length !== 0 && // Only show top banner if user is logged in Object.keys(this.props.user).length !== 0 && // Only show top banner if user is logged in
@ -487,14 +491,42 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
key="frameless-desktop" key="frameless-desktop"
minWidth={frameless.desktop} minWidth={frameless.desktop}
> >
{
(Date.now() < HOC_START_TIME && // Hide intro if HoC banner is showing
Date.now() > HOC_END_TIME) ?
[
<Intro <Intro
key="intro" key="intro"
messages={messages} messages={messages}
projectCount={this.props.projectCount} projectCount={this.props.projectCount}
/> />
] :
[]
}
</MediaQuery> </MediaQuery>
]) : [] ]) : []
} }
{featured.shift()}
{featured.shift()}
</div>
{
this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length !== 0 && // Only show if user is logged in
Date.now() >= HOC_START_TIME && // Show middle banner on and after Dec 3
Date.now() < HOC_END_TIME && // Hide middle banner after Dec 14
<MediaQuery
key="frameless-desktop"
minWidth={frameless.tablet}
>
<MiddleBanner />
</MediaQuery>
}
<div
className="inner mod-splash"
key="inner2"
>
{featured} {featured}
{this.props.isAdmin ? [ {this.props.isAdmin ? [

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

22
static/svgs/tutorials.svg Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.2 (67145) - http://www.bohemiancoding.com/sketch -->
<title>Tutorials/Light Bulb</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M19.0000002,9.48986925 C19.0000002,9.86977638 18.6906473,10.1592294 18.3125492,10.1592294 L17.2813727,10.1592294 C16.9014655,10.1592294 16.5939217,9.86977638 16.5939217,9.48986925 C16.5939217,9.10996211 16.9014655,8.80241823 17.2813727,8.80241823 L18.3125492,8.80241823 C18.6906473,8.80241823 19.0000002,9.10996211 19.0000002,9.48986925 Z M5.32243869,14.1574807 C5.59380093,14.428843 5.59380093,14.8449317 5.32243869,15.116294 L4.60061513,15.8580174 C4.4558886,15.9846531 4.29307126,16.0570164 4.11035401,16.0570164 C3.92944585,16.0570164 3.76662851,15.9846531 3.62371106,15.8580174 C3.36863055,15.5866552 3.36863055,15.1524756 3.62371106,14.8992042 L4.36362544,14.1574807 C4.63498768,13.8861185 5.06916727,13.8861185 5.32243869,14.1574807 Z M16.358922,3.12262561 C16.6121934,3.39217877 16.6121934,3.82816744 16.358922,4.07962978 L15.6171985,4.82135324 C15.4905628,4.94979804 15.3096546,5.0221613 15.1468373,5.0221613 C14.96412,5.0221613 14.8031118,4.94979804 14.6583852,4.82135324 C14.4051138,4.55180008 14.4051138,4.1176205 14.6583852,3.86253999 L15.4001087,3.12262561 C15.6515711,2.85126337 16.0875597,2.85126337 16.358922,3.12262561 Z M12.4138577,17.3409216 C12.5965749,18.5005429 11.9254057,19.477447 9.98968834,19.477447 C8.0557801,19.477447 7.38461082,18.5005429 7.56551898,17.3409216 C7.65597306,16.8343788 8.14623418,17.5236389 9.98968834,17.5580114 C11.8530424,17.5580114 12.3414944,16.8343788 12.4138577,17.3409216 Z M3.62280652,4.08017251 C3.36772601,3.82690108 3.36772601,3.39272149 3.62280652,3.12316833 C3.89235968,2.84999701 4.32834835,2.84999701 4.59971059,3.12316833 L5.32153415,3.86308271 C5.59470547,4.11816322 5.59470547,4.55234281 5.32153415,4.82189597 C5.19670752,4.94853168 5.01579936,5.02270403 4.85298201,5.02270403 C4.67026477,5.02270403 4.48935661,4.94853168 4.3627209,4.82189597 L3.62280652,4.08017251 Z M3.38798773,9.48986925 C3.38798773,9.86977638 3.08044385,10.1592294 2.71862753,10.1592294 L1.6693602,10.1592294 C1.30754387,10.1592294 1,9.86977638 1,9.48986925 C1,9.10996211 1.30754387,8.80241823 1.6693602,8.80241823 L2.71862753,8.80241823 C3.08044385,8.80241823 3.38798773,9.10996211 3.38798773,9.48986925 Z M9.32050905,2.19872763 L9.32050905,1.1693602 C9.32050905,0.789453058 9.60996211,0.5 9.98986925,0.5 C10.3697764,0.5 10.6773203,0.789453058 10.6773203,1.1693602 L10.6773203,2.19872763 C10.6773203,2.57863477 10.3697764,2.88617864 9.98986925,2.88617864 C9.60996211,2.88617864 9.32050905,2.57863477 9.32050905,2.19872763 Z M15.0021108,8.80259914 C15.1269374,10.1594103 14.7307485,11.4257675 13.9709342,12.3827716 C13.2635833,13.3072124 12.8113129,13.5062113 12.7932221,14.6278419 C12.7932221,15.206748 12.5037691,15.6771093 12.0334078,15.8941991 L12.0171261,15.8941991 C10.7326782,16.5273776 9.24742215,16.5092868 7.96297421,15.8941991 C7.51070381,15.6771093 7.22125075,15.206748 7.22125075,14.7002052 C7.22125075,13.5243021 6.75088953,13.343394 6.02725689,12.4026715 C5.35970577,11.5524032 4.95989874,10.4669542 4.95989874,9.30914199 C4.95989874,6.32415734 7.54869452,3.97235124 10.5879516,4.31607675 C12.9035761,4.58743899 14.785021,6.48697468 15.0021108,8.80259914 Z M16.358922,14.8993851 C16.6121934,15.1526565 16.6121934,15.5868361 16.358922,15.8581983 C16.2322863,15.984834 16.0513781,16.0571973 15.8686608,16.0571973 C15.7076526,16.0571973 15.5249353,15.984834 15.4001087,15.8581983 L14.6583852,15.1164749 C14.4051138,14.8451126 14.4051138,14.4290239 14.6583852,14.1576616 C14.9297475,13.8844903 15.362118,13.8844903 15.6171985,14.1576616 L16.358922,14.8993851 Z" id="path-1"></path>
</defs>
<g id="Tutorials/Light-Bulb" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Combined-Shape" fill="#4D97FF" xlink:href="#path-1"></use>
<g id="Color/White" mask="url(#mask-2)" fill="#4D97FF">
<g id="Color/1_Blue">
<g id="Color/Blue/1_Blue">
<rect id="Primary-Blue" x="0" y="0" width="20" height="20"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB