Merge pull request #6760 from bocoup/2021-annual-report

2021 annual report
This commit is contained in:
Sarah Otts 2022-05-03 16:38:33 -04:00 committed by GitHub
commit b7b504d6d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 552 additions and 337 deletions

View file

@ -0,0 +1,18 @@
const PropTypes = require('prop-types');
const React = require('react');
require('./tag.scss');
const Tag = props => (
<div className={`${props.type} ${props.color} bubble`}>
<span>{props.text}</span>
</div>
);
Tag.propTypes = {
type: PropTypes.string,
text: PropTypes.string,
color: PropTypes.string
};
module.exports = Tag;

View file

@ -0,0 +1,74 @@
@import "../../colors";
$green: #2B732B;
.bubble {
background-color: rgba(0,0,0,.15);
color: #fff;
font-weight: 500;
border-radius: 50px;
padding: 8px 36px;
font-size: 1rem;
margin: 15px auto;
width: max-content;
display: flex;
justify-content: center;
align-items: center;
img{
margin: 0px 8px;
width: 30px;
height: 30px;
}
&.increase{
span{
display: flex;
justify-content: center;
align-items: center;
&:before{
content: '';
width: 30px;
height: 30px;
background-image: url("/images/annual-report/2020/Symbols-UI/Arrow_up.svg");
background-size: contain;
display: inline-block;
margin-right: 10px;
}
}
}
&.spotlight{
&:before{
content: '';
width: 30px;
height: 30px;
background-image: url("/images/annual-report/2020/Symbols-UI/LightBulb_spotlightstory.svg");
background-size: contain;
display: inline-block;
margin-right: 10px;
}
}
&.snapshot{
&:before{
content: '';
width: 30px;
height: 30px;
background-image: url("/images/annual-report/2020/Symbols-UI/Camera_snapshots.svg");
background-size: contain;
display: inline-block;
margin-right: 10px;
}
}
&.darken{
background-color: rgba(0, 0, 0, 0.15);
}
&.blue{
background-color: $motion-blue-3;
}
&.purple{
background-color: $ui-purple-dark;
}
&.green{
background-color: $green;
}
}

View file

@ -24,8 +24,8 @@ $timeline-breakpoint: "only screen and (max-width : 1030px)";
}
a{
position: absolute;
right: 15px;
top: 15px;
right: 12px;
top: 1px;
}
img{

View file

@ -17,7 +17,9 @@ const TextAndMediaSnippet = require('../../../components/text-and-media-snippet/
const TimelineCard = require('../../../components/timeline-card/timeline-card.jsx');
const PeopleGrid = require('../../../components/people-grid/people-grid.jsx');
const People = require('./people.json');
const Tag = require('../../../components/tag/tag.jsx');
const VideoPreview = require('../../../components/video-preview/video-preview.jsx');
const VideoPreviewYouTube = require('./video-preview-youtube/video-preview-youtube.jsx');
const Supporters = require('./supporters.json');
import {TwitterTweetEmbed} from 'react-twitter-embed';
const Organizations = require('./orgs.json');
@ -72,19 +74,20 @@ const COUNTRIES2 = [
const CountryOrgList = props => (
<ul className="org-list-ul">
{/* eslint-disable */}
{/* circle back to this */}
{Organizations.filter(org => org.country === props.country).map((org, i) => {
return <li className="organization" key={i}>{org.name}</li>;
})}
{/* eslint-enable */}
</ul>
)
);
const CreateOrgList = props => (
<div className="org-list">
{/* eslint-disable */}
{props.array.map((country, i) => {
return <div className="country-org-list"><h5 key={i}>{country}</h5><CountryOrgList country={country} /></div>;
return <div className="country-org-list" key={i}><h5>{country}</h5><CountryOrgList country={country} /></div>;
})}
{/* eslint-enable */}
</div>
);
@ -451,6 +454,7 @@ class AnnualReport extends React.Component {
</p>
</div>
<div className="four-up">
{/* eslint-disable max-len */}
<div className="one-p four-up-creative-expression">
<div className="four-up-title creative-expression">
<h3>
@ -477,6 +481,7 @@ class AnnualReport extends React.Component {
</div>
<p className="inner"><FormattedMessage id="annualReport.2021.playfulEngagementDescription" /></p>
</div>
{/* eslint-enable max-len */}
</div>
</div>
<div
@ -514,9 +519,13 @@ class AnnualReport extends React.Component {
<h4>
<FormattedMessage id="annualReport.2021.reachProjectCreators" />
</h4>
<div className="increase bubble">
<FormattedMessage id="annualReport.2021.reachProjectCreatorsIncrease" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.reachProjectCreatorsIncrease'}
)}
color="darken"
type="increase"
/>
</div>
<div className="reach-datapoint">
<FormattedMessage
@ -532,9 +541,13 @@ class AnnualReport extends React.Component {
<h4>
<FormattedMessage id="annualReport.2021.reachProjectsCreated" />
</h4>
<div className="increase bubble">
<FormattedMessage id="annualReport.2021.reachProjectsCreatedIncrease" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.reachProjectsCreatedIncrease'}
)}
color="darken"
type="increase"
/>
</div>
<div className="reach-datapoint">
<FormattedMessage
@ -550,9 +563,13 @@ class AnnualReport extends React.Component {
<h4>
<FormattedMessage id="annualReport.2021.reachNewUsers" />
</h4>
<div className="increase bubble">
<FormattedMessage id="annualReport.2021.reachNewUsersIncrease" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.reachNewUsersIncrease'}
)}
color="darken"
type="increase"
/>
</div>
</div>
<div className="reach-numbers">
@ -570,7 +587,9 @@ class AnnualReport extends React.Component {
values={{
numberOfCountries: (
<b>
{/* eslint-disable max-len */}
<FormattedMessage id="annualReport.2021.reachScratchAroundTheWorldBold" />
{/* eslint-enable max-len */}
</b>
)
}}
@ -676,18 +695,13 @@ class AnnualReport extends React.Component {
<h4>
<FormattedMessage id="annualReport.2021.reachDownloads" />
</h4>
<div className="increase bubble dark">
<FormattedMessage
id="annualReport.2021.reachDownloadsIncrease"
values={{
million: (
<div className="million">
<FormattedMessage id="annualReport.2021.reachMillion" />
</div>
)
}}
/>
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.reachDownloadsIncrease'}
)}
color="darken"
type="increase dark"
/>
</div>
</div>
<MediaQuery minWidth={frameless.mobile}>
@ -746,8 +760,6 @@ class AnnualReport extends React.Component {
</div>
</div>
<div className="initiatives-subsection-content SEC">
{/* eslint-disable max-len */}
{/* <div className="inner"> */}
<div className="content two-up">
<div className="p-content">
<h4>
@ -827,9 +839,13 @@ class AnnualReport extends React.Component {
<MediaQuery minWidth={frameless.tabletPortrait}>
<div className="content flex-content">
<div className="text">
<div className="spotlight bubble SEC">
<FormattedMessage id="annualReport.2021.spotlightStory" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.spotlightStory'}
)}
color="blue"
type="spotlight"
/>
<h4>
<FormattedMessage id="annualReport.2021.SECSpotlightTitle" />
</h4>
@ -844,12 +860,14 @@ class AnnualReport extends React.Component {
</p>
</div>
<div className="images">
{/* eslint-disable max-len */}
<img
src="/images/annual-report/2021/1_SEC Section/Bridges to Science.svg"
alt={this.props.intl.formatMessage(
{id: 'annualReport.2021.altSECSpotlightImage'}
)}
/>
{/* eslint-enable max-len */}
</div>
</div>
</MediaQuery>
@ -859,9 +877,13 @@ class AnnualReport extends React.Component {
>
<div className="content flex-content">
<div className="text">
<div className="spotlight bubble SEC">
<FormattedMessage id="annualReport.2021.spotlightStory" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.spotlightStory'}
)}
color="green"
type="spotlight"
/>
<h4>
<FormattedMessage id="annualReport.2021.SECSpotlightTitle" />
</h4>
@ -870,12 +892,14 @@ class AnnualReport extends React.Component {
</p>
</div>
<div className="images">
{/* eslint-disable max-len */}
<img
src="/images/annual-report/2021/1_SEC Section/Bridges to Science.svg"
alt={this.props.intl.formatMessage(
{id: 'annualReport.2021.altSECSpotlightImage'}
)}
/>
{/* eslint-enable max-len */}
</div>
<div className="text">
<p>
@ -932,13 +956,17 @@ class AnnualReport extends React.Component {
</div>
</div>
<div className="world access">
<div className="spotlight bubble access">
<FormattedMessage id="annualReport.2021.spotlightStory" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.spotlightStory'}
)}
color="green"
type="spotlight"
/>
<h4>
<FormattedMessage id="annualReport.2021.accessASL" />
</h4>
<p class="subhed">
<p className="subhed">
<FormattedMessage
id="annualReport.2021.accessASLText"
/>
@ -950,6 +978,7 @@ class AnnualReport extends React.Component {
{id: 'annualReport.2021.altAccessibility'}
)}
/>
{/* eslint-enable */}
<p>
<FormattedMessage
id="annualReport.2021.accessASLText2"
@ -970,6 +999,7 @@ class AnnualReport extends React.Component {
</p>
<div className="video-container SEC">
<div className="video-background SEC">
{/* eslint-disable max-len */}
<MediaQuery minWidth={frameless.tabletPortrait}>
<VideoPreview
buttonMessage={
@ -978,7 +1008,7 @@ class AnnualReport extends React.Component {
thumbnail="/images/annual-report/2021/2_Access Section/Deaf Kids Code Video.png"
videoId="i2g46ikddf"
thumbnailWidth="580"
videoHeight={580 * .568}
videoHeight={String(580 * .568)}
videoWidth="580"
alt={
this.props.intl.formatMessage(
@ -998,7 +1028,7 @@ class AnnualReport extends React.Component {
thumbnail="/images/annual-report/2021/2_Access Section/Deaf Kids Code Video.png"
videoId="i2g46ikddf"
thumbnailWidth="400"
videoHeight={400 * .568}
videoHeight={String(400 * .568)}
videoWidth="400"
alt={
this.props.intl.formatMessage(
@ -1015,7 +1045,7 @@ class AnnualReport extends React.Component {
thumbnail="/images/annual-report/2021/2_Access Section/Deaf Kids Code Video.png"
videoId="i2g46ikddf"
thumbnailWidth="300"
videoHeight={300 * .568}
videoHeight={String(300 * .568)}
videoWidth="300"
alt={
this.props.intl.formatMessage(
@ -1024,6 +1054,7 @@ class AnnualReport extends React.Component {
}
/>
</MediaQuery>
{/* eslint-enable max-len */}
</div>
</div>
</div>
@ -1047,6 +1078,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessDEICommitteeText"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
<MediaQuery maxWidth={frameless.tabletPortrait - 1}>
{/* eslint-disable max-len */}
@ -1067,6 +1099,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessDEICommitteeText"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
</div>
</div>
@ -1094,6 +1127,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessDEICommitteeAccessibilityText2"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
<MediaQuery maxWidth={frameless.tabletPortrait - 1}>
{/* eslint-disable max-len */}
@ -1115,6 +1149,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessDEICommitteeAccessibilityText2"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
</div>
</div>
@ -1142,6 +1177,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessDEICommitteeG-JEDIText2"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
<MediaQuery maxWidth={frameless.tabletPortrait - 1}>
{/* eslint-disable max-len */}
@ -1163,6 +1199,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessDEICommitteeG-JEDIText2"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
</div>
</div>
@ -1212,16 +1249,20 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessDEICommitteeEquityXDesignText2"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
</div>
</div>
</div>
{/* 10 new languages */}
{/* eslint-disable max-len */}
<div className="inner">
<div className="snapshot bubble access left-align languages">
<FormattedMessage id="annualReport.2021.accessSnapshot" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.accessSnapshot'}
)}
color="green"
type="snapshot left-align languages"
/>
<div className="flex-content">
<div className="text-and-media-snippet regular">
<div className="half">
@ -1239,7 +1280,6 @@ class AnnualReport extends React.Component {
>
<iframe
src="https://scratch.mit.edu/projects/430997530/embed"
allowTransparency="true"
width="360"
height={((360 * .76) + 45)}
frameBorder="0"
@ -1250,7 +1290,6 @@ class AnnualReport extends React.Component {
<MediaQuery maxWidth={frameless.desktop - 1}>
<iframe
src="https://scratch.mit.edu/projects/430997530/embed"
allowTransparency="true"
width="300"
height={((300 * .76) + 45)}
frameBorder="0"
@ -1281,6 +1320,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessSouthAfricaText"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
<MediaQuery maxWidth={frameless.tabletPortrait - 1}>
{/* eslint-disable max-len */}
@ -1299,6 +1339,7 @@ class AnnualReport extends React.Component {
id="annualReport.2021.accessSouthAfricaText"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
</div>
</div>
@ -1317,14 +1358,20 @@ class AnnualReport extends React.Component {
</div>
<div className="initiatives-subsection-content">
<div className="world">
<div className="snapshot bubble community">
<FormattedMessage id="annualReport.2021.accessSnapshot" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.accessSnapshot'}
)}
color="purple"
type="snapshot"
/>
{/* eslint-disable max-len */}
<h4>
<FormattedMessage id="annualReport.2021.communityScratchConference" />
</h4>
<p>
<FormattedMessage id="annualReport.2021.communityScratchConferenceText1"
<FormattedMessage
id="annualReport.2021.communityScratchConferenceText1"
values={{
more_bold: (
<b>
@ -1332,8 +1379,9 @@ class AnnualReport extends React.Component {
</b>
)
}}
/>
/>
</p>
{/* eslint-enable max-len */}
</div>
<div className="tweet-container">
<div className="tweets">
@ -1358,9 +1406,6 @@ class AnnualReport extends React.Component {
{/* eslint-disable max-len */}
<TextAndMediaSnippet
className="regular"
// title={this.props.intl.formatMessage(
// {id: 'annualReport.2021.communityVolunteerTranslators'}
// )}
alt={this.props.intl.formatMessage(
{id: 'annualReport.2021.altcommunityVolunteerTranslators'}
)}
@ -1371,14 +1416,12 @@ class AnnualReport extends React.Component {
id="annualReport.2021.communityVolunteerTranslatorsText"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
<MediaQuery maxWidth={frameless.desktop - 1}>
{/* eslint-disable max-len */}
<TextAndMediaSnippet
className="regular"
// title={this.props.intl.formatMessage(
// {id: 'annualReport.2021.communityVolunteerTranslators'}
// )}
alt={this.props.intl.formatMessage(
{id: 'annualReport.2021.altcommunityVolunteerTranslators'}
)}
@ -1389,18 +1432,21 @@ class AnnualReport extends React.Component {
id="annualReport.2021.communityVolunteerTranslatorsText"
/>
</TextAndMediaSnippet>
{/* eslint-enable */}
</MediaQuery>
<p>
<p className="contain-p">
<FormattedMessage
id="annualReport.2021.communityVolunteerTranslatorsText2"
/>
</p>
</div>
<div className="thank-you-image">
{/* eslint-disable max-len */}
<img
src="/images/annual-report/2021/3_Community Section/Thank You Translators.svg"
alt={this.props.intl.formatMessage({id: 'annualReport.2021.altcommunityThankYou'})}
/>
{/* eslint-enable max-len */}
</div>
</div>
@ -1412,9 +1458,6 @@ class AnnualReport extends React.Component {
<FormattedMessage id="annualReport.2021.communityScratchCommunityIntro" />
</p>
</div>
<div className="inner">
</div>
{/* go into timeline section */}
<div className="sparkles">
@ -1461,6 +1504,7 @@ class AnnualReport extends React.Component {
src="/images/annual-report/2021/3_Community Section/Timeline/jan to feb.svg"
alt={this.props.intl.formatMessage({id: 'annualReport.2021.altConnectingLine'})}
/>
{/* eslint-disable max-len */}
<TimelineCard
className="left"
link="https://scratch.mit.edu/studios/28738118/"
@ -1484,7 +1528,6 @@ class AnnualReport extends React.Component {
/>
<TimelineCard
className="left"
// link="https://www.youtube.com/watch?v=uR5C173yrJs"
date={this.props.intl.formatMessage(
{id: 'annualReport.2021.yearInReviewCard3Date'}
)}
@ -1510,7 +1553,6 @@ class AnnualReport extends React.Component {
/>
<TimelineCard
className="right"
// link="https://scratch.mit.edu/projects/400944766/"
date={this.props.intl.formatMessage(
{id: 'annualReport.2021.yearInReviewCard4Date'}
)}
@ -1590,7 +1632,7 @@ class AnnualReport extends React.Component {
attribution="@twingamerdudesreal"
/>
<img
className="connector"
className="connector left"
src="/images/annual-report/2021/3_Community Section/Timeline/oct to dec.svg"
alt={this.props.intl.formatMessage({id: 'annualReport.2021.altConnectingLine'})}
/>
@ -1606,9 +1648,6 @@ class AnnualReport extends React.Component {
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.yearInReviewCard8Text'}
)}
alt={this.props.intl.formatMessage(
{id: 'annualReport.2021.altCard8'}
)}
/>
<TimelineCard
className="center"
@ -1625,7 +1664,7 @@ class AnnualReport extends React.Component {
alt={this.props.intl.formatMessage(
{id: 'annualReport.2021.altCard9'}
)}
image="/images/annual-report/2021/3_Community Section/Timeline/Scratchtober.png"
image="/images/annual-report/2021/3_Community Section/Timeline/Year in Review.png"
projectBy={this.props.intl.formatMessage(
{id: 'annualReport.2021.projectBy'}
)}
@ -1654,15 +1693,20 @@ class AnnualReport extends React.Component {
<FormattedMessage id="annualReport.2021.OctIlloAttr" />
</p>
</div>
{/* eslint-enable max-len */}
</div>
<div className="initiatives-subsection-content lab">
<div className="wide inner community">
<div className="content two-wide split">
<div className="text">
<div className="snapshot bubble community">
<FormattedMessage id="annualReport.2021.spotlightStory" />
</div>
<Tag
text={this.props.intl.formatMessage(
{id: 'annualReport.2021.spotlightStory'}
)}
color="purple"
type="snapshot"
/>
<h4>
<FormattedMessage id="annualReport.2021.communityScratchLabTitle" />
</h4>
@ -1674,14 +1718,16 @@ class AnnualReport extends React.Component {
</p>
</MediaQuery>
</div>
{/* eslint-disable max-len */}
<div className="images">
<img
src="/images/annual-report/2021/3_Community Section/Scratch Lab logo.png"
alt={this.props.intl.formatMessage({id: 'annualReport.2021.altScratchLogoText'})}
/>
</div>
{/* eslint-enable max-len */}
<MediaQuery
maxWidth={frameless.tabletPortrait - 1}
maxWidth={frameless.tabletPortrait - 1}
>
<p>
<FormattedMessage id="annualReport.2021.communityScratchLabText" />
@ -1702,7 +1748,7 @@ class AnnualReport extends React.Component {
thumbnail="/images/annual-report/2021/3_Community Section/Scratch Lab video.png"
videoId="go1wqxifjk"
thumbnailWidth="580"
videoHeight={580 * .568}
videoHeight={String(580 * .568)}
videoWidth="580"
alt={
this.props.intl.formatMessage(
@ -1722,7 +1768,7 @@ class AnnualReport extends React.Component {
thumbnail="/images/annual-report/2021/3_Community Section/Scratch Lab video.png"
videoId="go1wqxifjk"
thumbnailWidth="400"
videoHeight={400 * .568}
videoHeight={String(400 * .568)}
videoWidth="400"
alt={
this.props.intl.formatMessage(
@ -1739,7 +1785,7 @@ class AnnualReport extends React.Component {
thumbnail="/images/annual-report/2021/3_Community Section/Scratch Lab video.png"
videoId="go1wqxifjk"
thumbnailWidth="300"
videoHeight={300 * .568}
videoHeight={String(300 * .568)}
videoWidth="300"
alt={
this.props.intl.formatMessage(
@ -1759,6 +1805,7 @@ class AnnualReport extends React.Component {
<FormattedMessage id="annualReport.2021.communityScratchLabText4" />
</p>
<div className="sds-list">
{/* eslint-disable max-len */}
<div className="sds-tile">
<img
src="/images/annual-report/2021/3_Community Section/Scratch Lab hat.png"
@ -1777,10 +1824,11 @@ class AnnualReport extends React.Component {
alt={this.props.intl.formatMessage({id: 'annualReport.2021.altStar'})}
/>
</div>
{/* eslint-enable max-len */}
</div>
</div>
<div style={{width: "100%"}}>
<h4 style={{textAlign: "center"}}>
<div style={{width: '100%'}}>
<h4 style={{textAlign: 'center'}}>
<FormattedMessage id="annualReport.2021.communitySnapshot2Title" />
</h4>
<div className="content two-wide split yt">
@ -1789,7 +1837,9 @@ class AnnualReport extends React.Component {
>
<div className="text">
<p>
{/* eslint-disable max-len */}
<FormattedMessage id="annualReport.2021.communitySnapshot2Text" />
{/* eslint-enable max-len */}
</p>
</div>
</MediaQuery>
@ -1827,23 +1877,23 @@ class AnnualReport extends React.Component {
>
<div className="text">
<p>
{/* eslint-disable max-len */}
<FormattedMessage id="annualReport.2021.communitySnapshot2Text" />
{/* eslint-enable max-len */}
</p>
</div>
</MediaQuery>
</div>
{/* <p>
<FormattedMessage id="annualReport.2021.communitySnapshot2Text" />
</p> */}
{/* eslint-disable max-len */}
<MediaQuery minWidth={frameless.tabletPortrait}>
<VideoPreview
<VideoPreviewYouTube
buttonMessage={
this.props.intl.formatMessage({id: 'annualReport.2021.watchVideo'})
}
thumbnail="/images/annual-report/2021/3_Community Section/YT video spotlight video.png"
videoId="https://www.youtube.com/watch?v=uv8mbL-MC58&t=116s"
videoId="uv8mbL-MC58"
thumbnailWidth="580"
videoHeight={580 * .568}
videoHeight={String(580 * .568)}
videoWidth="580"
alt={
this.props.intl.formatMessage(
@ -1856,14 +1906,14 @@ class AnnualReport extends React.Component {
maxWidth={frameless.tabletPortrait - 1}
minWidth={frameless.mobile}
>
<VideoPreview
<VideoPreviewYouTube
buttonMessage={
this.props.intl.formatMessage({id: 'annualReport.2021.watchVideo'})
}
thumbnail="/images/annual-report/2021/3_Community Section/YT video spotlight video.png"
videoId="https://www.youtube.com/watch?v=uv8mbL-MC58&t=116s"
videoId="uv8mbL-MC58"
thumbnailWidth="400"
videoHeight={400 * .568}
videoHeight={String(400 * .568)}
videoWidth="400"
alt={
this.props.intl.formatMessage(
@ -1873,14 +1923,14 @@ class AnnualReport extends React.Component {
/>
</MediaQuery>
<MediaQuery maxWidth={frameless.mobile - 1}>
<VideoPreview
<VideoPreviewYouTube
buttonMessage={
this.props.intl.formatMessage({id: 'annualReport.2021.watchVideo'})
}
thumbnail="/images/annual-report/2021/3_Community Section/YT video spotlight video.png"
videoId="https://www.youtube.com/watch?v=uv8mbL-MC58&t=116s"
videoId="uv8mbL-MC58"
thumbnailWidth="300"
videoHeight={300 * .568}
videoHeight={String(300 * .568)}
videoWidth="300"
alt={
this.props.intl.formatMessage(
@ -1889,15 +1939,17 @@ class AnnualReport extends React.Component {
}
/>
</MediaQuery>
{/* eslint-enable max-len */}
</div>
<div className="community-sds">
<p>
<FormattedMessage id="annualReport.2021.communitySnapshot2Text2" />
</p>
<div className="sds-list">
{/* eslint-disable max-len */}
<div className="sds-tile">
<a
href="https://www.youtube.com/watch?v=zM9MYI6bVMk&t=114s"
href="https://www.youtube.com/watch?v=zM9MYI6bVMk"
target="_blank"
rel="noopener noreferrer"
>
@ -1910,7 +1962,7 @@ class AnnualReport extends React.Component {
</div>
<div className="sds-tile">
<a
href="https://www.youtube.com/watch?v=4v1CIKehF6E&t=3s"
href="https://www.youtube.com/watch?v=4v1CIKehF6E"
target="_blank"
rel="noopener noreferrer"
>
@ -1923,7 +1975,7 @@ class AnnualReport extends React.Component {
</div>
<div className="sds-tile">
<a
href="https://www.youtube.com/watch?v=TZu2QwkYQm0&t=114s"
href="https://www.youtube.com/watch?v=TZu2QwkYQm0"
target="_blank"
rel="noopener noreferrer"
>
@ -1934,13 +1986,13 @@ class AnnualReport extends React.Component {
<FormattedMessage id="annualReport.2021.tutorial3" />
</a>
</div>
{/* eslint-enable max-len */}
</div>
</div>
</div>
</div>
</div>
{/* eslint-enable max-len */}
</div>
<div
@ -2125,7 +2177,7 @@ class AnnualReport extends React.Component {
<h2>
<FormattedMessage id="annualReport.2021.leadershipTitle" />
</h2>
<h3>
<h3 style={{margin: '0 25px'}}>
<FormattedMessage id="annualReport.2021.leadershipBoard" />
</h3>
<FlexRow className="leadership-board">

View file

@ -10,7 +10,10 @@ $masthead-breakpoint-wave: "only screen and (max-width : 1060px)";
$timeline-breakpoint: "only screen and (max-width : 1030px)";
$ui-purple-dark: hsla(260, 55%, 55%, 1);
// $motion-blue-3 #3373CC
body{
background-color: $annual-report-aqua;
}
.access .button{
background-color: $annual-report-green;
@ -32,8 +35,6 @@ h1 {
}
h2 {
// font-size: 3.25rem;
// line-height: 3.75rem;
font-size: 2.9rem;
line-height: 3.2rem;
}
@ -307,6 +308,12 @@ a, a:link, a:visited, a:active{
margin-bottom: -75px;
background-image: url("/images/annual-report/2021/1_SEC Section/quote (blue).svg");
}
@media #{$medium-and-smaller}{
max-width: 460px;
width: 100%;
margin-bottom: 15px;
}
}
&.green{
font-weight: 500;
@ -316,6 +323,9 @@ a, a:link, a:visited, a:active{
margin-bottom: -75px;
background-image: url("/images/annual-report/2021/2_Access Section/quote (green).svg");
}
@media #{$medium-and-smaller}{
margin-bottom: 15px;
}
}
}
@ -353,6 +363,12 @@ a, a:link, a:visited, a:active{
&.right{
text-align: right;
margin-bottom: 30px;
@media #{$medium-and-smaller}{
margin-bottom: 40px;
}
}
@media #{$medium-and-smaller}{
margin-bottom: 40px;
}
}
@ -601,7 +617,7 @@ a, a:link, a:visited, a:active{
}
}
background-color: $annual-report-green;
background-color: $annual-report-aqua;
color: $ui-white;
h2, h3, h4, p {
@ -704,90 +720,14 @@ a, a:link, a:visited, a:active{
}
.bubble {
background-color: rgba(0,0,0,.15);
color: #fff;
font-weight: 500;
border-radius: 50px;
padding: 8px 36px;
font-size: 1rem;
margin: 15px auto;
width: max-content;
display: flex;
justify-content: center;
align-items: center;
img{
margin: 0px 8px;
width: 30px;
height: 30px;
}
&.left-align{
margin: 0 0 20px 0;
}
&.increase{
&.dark{
// background-color: darken($annual-report-teal, 15%);
.million{
font-size: 1rem;
margin: 0 3px;
span:before{
display: none;
}
}
}
span{
display: flex;
justify-content: center;
align-items: center;
&:before{
content: '';
width: 30px;
height: 30px;
background-image: url("/images/annual-report/2020/Symbols-UI/Arrow_up.svg");
background-size: contain;
display: inline-block;
margin-right: 10px;
}
margin: 50px 0 20px 0;
@media #{$medium-and-smaller}{
margin: 50px auto 20px auto;
}
}
&.spotlight{
&:before{
content: '';
width: 30px;
height: 30px;
background-image: url("/images/annual-report/2020/Symbols-UI/LightBulb_spotlightstory.svg");
background-size: contain;
display: inline-block;
margin-right: 10px;
}
}
&.snapshot{
&:before{
content: '';
width: 30px;
height: 30px;
background-image: url("/images/annual-report/2020/Symbols-UI/Camera_snapshots.svg");
background-size: contain;
display: inline-block;
margin-right: 10px;
}
}
&.SEC{
background-color: $motion-blue-3;
}
&.community{
background-color: $ui-purple-dark;
}
&.access{
background-color: $annual-report-green;
&.languages{
margin-top: 50px;
margin-bottom: -10px;
@media #{$intermediate-and-smaller}{
margin: 50px auto 10px;
}
}
&.green{
padding: 8px 36px;
}
}
@ -962,7 +902,7 @@ img.comment-viz{
}
.reach-scratch-jr {
background-color: $annual-report-green;
background-color: $annual-report-aqua;
color: $ui-white;
padding: 100px 0;
@ -1467,6 +1407,14 @@ img.comment-viz{
&.stacked{
margin-top: 0px;
padding-top: 0px;
@media #{$medium-and-smaller}{
max-width: 460px;
width: 100%;
}
@media #{$small}{
max-width: calc(100% - 50px);
width: 100%;
}
}
@media #{$big} {
max-width: 840px;
@ -1714,7 +1662,6 @@ img.comment-viz{
}
.connector{
margin: -40px auto -30px;
// margin-left: calc((100% - 980px)/2 + 200px);
z-index: 1;
&.left{
margin-left: calc((100% - 980px)/2 + 245px);
@ -1887,6 +1834,11 @@ img.comment-viz{
max-width: 650px;
margin: auto;
margin-top: 70px;
@media #{$small}{
width: calc(100% - 50px);
max-width: 300px;
margin: auto;
}
}
}
.text-and-media-snippet{
@ -2175,14 +2127,6 @@ img.comment-viz{
@media #{$small}{
height: 300px;
}
&.access {
background-image: url("/images/annual-report/2020/access/createalongs_splash.svg");
}
&.SEC {
background-image: url("/images/annual-report/2020/SEC/aroundtheworld_splash.svg");
}
}
.video-thumbnail .button{
@ -2313,6 +2257,10 @@ img.comment-viz{
text-align: left;
}
}
@media #{$medium-and-smaller}{
width: calc(100% - 50px);
margin: auto;
}
}
.signature{
@ -2338,9 +2286,17 @@ img.comment-viz{
}
p.contain-p{
@media #{$small}{
width: calc(100% - 50px);
max-width: 300px;
margin: auto;
}
}
.thank-you-image{
max-width: 600px;
width: 100%;
width: calc(100% - 50px);
margin: 50px auto;
img{
width: 100%;
@ -2362,11 +2318,15 @@ img.comment-viz{
@media #{$medium} {
max-width: 460px;
}
@media #{$small} {
max-width: 300px;
@media #{$medium-and-smaller}{
width: calc(100% - 50px);
margin: 50px auto;
}
// @media #{$small} {
// max-width: 300px;
// }
img.illo{
margin: 40px 0;
width: 100%;
@ -2423,6 +2383,10 @@ img.comment-viz{
display: flex;
flex-direction: column;
align-items: center;
@media #{$medium-and-smaller}{
width: calc(100% - 50px);
// margin: 50px auto;
}
}
.subsection-tag {
@ -2515,7 +2479,8 @@ img.comment-viz{
.supporters-list-side {
margin: 0 1.25rem 0 0;
width: 300px;
max-width: 300px;
width: 100%;
li {
margin: 0 0 .75rem 0;
@ -2645,7 +2610,8 @@ img.comment-viz{
.board-member {
text-align: center;
width: 300px;
max-width: 300px;
width: 100%;
margin-top: 44px;
line-height: 1.5rem;
}
@ -2693,7 +2659,7 @@ img.comment-viz{
}
.donate-section {
background-color: $annual-report-green;
background-color: $annual-report-aqua;
.donate-info {
justify-content: center;
@ -2736,7 +2702,9 @@ img.comment-viz{
}
@media #{$small} {
width: 300px;
max-width: 300px;
width: calc(100% - 50px);
margin: auto;
}

View file

@ -1,59 +0,0 @@
const classNames = require('classnames');
const PropTypes = require('prop-types');
const React = require('react');
require('./country-blurb.scss');
// Class names regular and reverse indicate whether the image should
// be placed on the right of left of the text in wider layouts.
// At smaller widths, the image will always be stacked on top.
// Because the right column would typically stack under the left
// I've named this class reverse since it is using flexbox reverse
// column layout to get the image to always appear on top of the text.
const CountryBlurb = props => (
<div className={classNames('country-blurb', props.className)}>
<div className="half">
<div className="country-info">
<img
src={props.icon}
alt={props.iconAlt}
/>
<div className="country-text">
<h4>{props.title}</h4>
<div className="location">
<img
src={props.listIcon}
alt="location icon"
/>
<span>{props.country}</span>
</div>
</div>
</div>
<p>
{props.children}
</p>
</div>
<div className="half">
<img
className="large"
src={props.largeImage}
alt={props.alt}
/>
</div>
</div>
);
CountryBlurb.propTypes = {
children: PropTypes.node,
icon: PropTypes.string,
title: PropTypes.string,
listIcon: PropTypes.string,
country: PropTypes.string,
className: PropTypes.string,
largeImage: PropTypes.string,
alt: PropTypes.string,
iconAlt: PropTypes.string
};
module.exports = CountryBlurb;

View file

@ -1,65 +0,0 @@
@import "../../../../frameless";
.country-blurb{
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
margin-bottom: 62px;
&.reverse {
flex-direction: row-reverse;
@media #{$intermediate-and-smaller} {
flex-direction: column-reverse;
}
}
@media #{$intermediate-and-smaller} {
// If we want to support both image on top and image on bottom,
// we can use the regular & reverse classNames
flex-direction: column-reverse;
}
.half{
max-width: 460px;
img.large{
max-width: 380px;
}
}
p{
font-size: 1rem;
text-align: left;
}
}
.country-info{
display: flex;
align-items: center;
img{
width: 65px;
height: 65px;
margin-right: 15px;
}
.country-text{
h4{
margin: 0 0 5px 0;
}
.location{
display: flex;
justify-content: flex-start;
align-items: center;
font-size: 1.25rem;
line-height: 1.5rem;
img{
width: 18px;
height: 18px;
margin-right: 5px;
}
}
}
}

View file

@ -61,7 +61,7 @@
"annualReport.2021.reachScratchJrBlurb": "ScratchJr is an introductory programming environment that enables young children (ages 5-7) to create their own interactive stories and games.",
"annualReport.2021.reachDownloadsMillion": "5 {million}",
"annualReport.2021.reachDownloads": "Downloads in 2021",
"annualReport.2021.reachDownloadsIncrease": "2 {million} from 2020",
"annualReport.2021.reachDownloadsIncrease": "2 million from 2020",
"annualReport.2021.themesTitle": "Emerging Themes",
"annualReport.2021.themesDescription": "Amidst ongoing uncertainty from COVID-19, Scratch continued to serve as a key space for young people to connect and create together. In 2021, we focused our efforts on building a strong foundation to equitably support our growing global community and our growing Scratch Team. Our work was centered around three major themes: fostering community, increasing access and accessibility, and developing the Scratch Education Collaborative (SEC).",
@ -223,7 +223,7 @@
"annualReport.2021.supportersIntro": "Thank you to our generous supporters. Your contribution helps us expand creative learning opportunities for children of all ages, from all backgrounds, around the globe.",
"annualReport.2021.ourSupporters": "Our Supporters",
"annualReport.2021.ourSupportersText": "We want to thank all Scratch supporters who, throughout the years, have helped us create amazing learning experiences for millions of young people around the world. The following list is based on giving to Scratch Foundation from January 1, 2021 to December 31, 2021.",
"annualReport.2021.ourSupportersText": "We want to thank all Scratch supporters who, throughout the years, have helped us amazing learning experiences for millions of young people around the world. The following list is based on giving to Scratch Foundation from January 1, 2021 to December 31, 2021.",
"annualReport.2021.supportersFoundingTitle": "Founding Partners — $10,000,000+",
"annualReport.2021.supportersFoundingText": "We are especially grateful to our Founding Partners who have each provided at least $10,000,000 in cumulative support, since the start of Scratch in 2003.",
@ -282,23 +282,43 @@
"annualReport.2021.altMitchHeadshot": "Founder Mitch Resnick",
"annualReport.2021.altCalendar": "A calendar displaying the year 2021.",
"annualReport.2021.altWorldVisualization": "An illustrated version of the globe.",
"annualReport.2021.altSaudiArabiaVisualization": "",
"annualReport.2021.altSECVideoPreview": "",
"annualReport.2021.altSaudiArabiaVisualization": "A bar chart showing that there were more than twice as many new Scratch users in 2021 as there were in 2020.",
"annualReport.2021.altScratchHorizontalCommand": "A yellow Scratch programming component.",
"annualReport.2021.altSECVideoPreview": "The Scratch interface appears on the left and a girl signing appears on the right.",
"annualReport.2021.altScratchJr": "Text reading Scratch jr",
"annualReport.2021.altHorizontalLoop": "A yellow horizontal Scratch programming component.",
"annualReport.2021.altaccessDEICommitteeEquityXDesign": "Two hands lining up physical Scratch components.",
"annualReport.2021.altcommunityVolunteerTranslators": "Hands reaching up in front of a purple background with text bubbles floating above them.",
"annualReport.2021.altScratchLogoText": "A green rectangle with the words 'Scratch Lab' writton on it.",
"annualReport.2021.altScratchLabVideo": "A screenshot of a Scratch project with a play button on top.",
"annualReport.2021.altHat": "A person wearing a yellow hat and pink heart sunglasses.",
"annualReport.2021.altScratchText": "A rainbow Scratch component displaying the text, 'Here we go!'",
"annualReport.2021.altStar": "A girl with a yellow star in front of her face.",
"annualReport.2021.altMouseTrail": "Multiple cut outs of a squirrel head placed randomly on top of each other.",
"annualReport.2021.altSECWorkshops": "People playing together",
"annualReport.2021.altArrowUp": "An arrow pointing up.",
"annualReport.2021.altTranslated": "A scratch component saying \"Hello\" and listing languages that scratch is available in.",
"annualReport.2021.altAboutMe": "The words 'About me' placed over an easel, hedgehog, mango, and soccer ball.",
"annualReport.2021.altClickerGame": "A math game showing an apple, an orange, and a cut up bowl of fruit.",
"annualReport.2021.altLookingForward1": "Interlocking hexagons displaying a swirl, start, and heart.",
"annualReport.2021.altLookingForward2": "A sign post with one arrow poining right displaying a swirl and one arrow pointing left displaying a heart.",
"annualReport.2021.altLookingForward3": "Colorful blocks lined up to create steps with a plant growing on top.",
"annualReport.2021.altSparkle": "White sparkle decoration",
"annualReport.2021.altDownArrow": "Purple arrow pointing down",
"annualReport.2021.altCard1": "",
"annualReport.2021.altCard2": "",
"annualReport.2021.altCard3": "",
"annualReport.2021.altCard4": "",
"annualReport.2021.altCard5": "",
"annualReport.2021.altCard6": "",
"annualReport.2021.altCard7": "",
"annualReport.2021.altCard8": "",
"annualReport.2021.altCard9": "",
"annualReport.2021.altConnectingLine": "A dotted line connecting timeline elements.",
"annualReport.2021.altApril": "A pen and Scratch components placed on top of a purple background.",
"annualReport.2021.altMay": "A birthday cake in front of a banner of flags displaying various types of LGBTQ+ pride.",
"annualReport.2021.altJune": "A potato, birthday had, and sunglasses on top of a purple background.",
"annualReport.2021.altCard1": "A colorful blob floats in front of a black and gray background next to the words 'A dream In a world of nightmares.'",
"annualReport.2021.altCard2": "A black woman is wearing a yellow headband and gold hoop earrings.",
"annualReport.2021.altCard3": "The scratch cat mascot swings in front of buildings accompanied by text reading 'I think Scratch Cat is a superhero.'",
"annualReport.2021.altCard5": "A smiling block stands next to a text bubble reading 'no matter how anyone dresses, what pronouns they use, or who they love, you should always respect them!'",
"annualReport.2021.altCard6": "A potato wearing sunglasses sits in front of a purple background.",
"annualReport.2021.altCard7": "A colorful birthday hat sits on top of a neon cube.",
"annualReport.2021.altCard9": "'2022' sits in front of a rainbow of ovals.",
"annualReport.2021.altDonateIllustration": "Two hands form the shape of a heart with their fingers inside of a cut out heart shape."
}

View file

@ -23,7 +23,7 @@
"Vista Equity Partners"
],
"imagination": [
"Alex & Ginsburg",
"Alex & Hillary Ginsburg",
"AT&T Aspire",
"James Hill",
"Inversoft/CleanSpeak",

View file

@ -0,0 +1,101 @@
const bindAll = require('lodash.bindall');
const PropTypes = require('prop-types');
const React = require('react');
const VideoYoutube = require('../video-youtube/video-youtube.jsx');
// const Spinner = require('../../../../components/spinner/spinner.jsx');
const classNames = require('classnames');
require('./video-preview-youtube.scss');
class VideoPreviewYouTube extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleShowVideo',
'handleVideoLoaded'
]);
this.state = {
videoOpen: false,
spinnerVisible: false
};
}
handleShowVideo () {
this.setState({
videoOpen: true,
spinnerVisible: true
});
}
handleVideoLoaded () {
this.setState({spinnerVisible: false});
}
render () {
return (
// Adding a width to this div allows the videoFoam property on the embedded video
// to fill the size of the div once fullscreen has been entered and exited
<div
className="video-preview"
style={{width: `${this.props.videoWidth}px`}}
>
{this.state.videoOpen ?
(
<div className="spinner-video-container">
<VideoYoutube
className="video"
height={this.props.videoHeight}
videoId={this.props.videoId}
width={this.props.videoWidth}
onVideoStart={this.handleVideoLoaded}
/>
</div>
) : (
<div
className="video-thumbnail"
onClick={this.handleShowVideo}
>
{/* Load an invisible spinner so that the image has a chance to load before it's needed */}
<img
className={classNames('loading-spinner', 'hidden-spinner')}
src="/svgs/modal/spinner-white.svg"
/>
<img
src={this.props.thumbnail}
style={{
width: `${this.props.thumbnailWidth}px` || 'auto',
height: `${this.props.thumbnailHeight}px` || 'auto'
}}
alt={this.props.alt}
/>
{this.props.buttonMessage.length > 0 &&
<a
onClick={this.handleShowVideo}
>
<div className="button">
{this.props.buttonMessage}
</div>
</a>
}
</div>
)
}
</div>
);
}
}
VideoPreviewYouTube.propTypes = {
buttonMessage: PropTypes.string.isRequired,
thumbnail: PropTypes.string.isRequired,
thumbnailHeight: PropTypes.string,
thumbnailWidth: PropTypes.string,
videoHeight: PropTypes.string,
videoId: PropTypes.string.isRequired,
videoWidth: PropTypes.string,
alt: PropTypes.string
};
module.exports = VideoPreviewYouTube;

View file

@ -0,0 +1,55 @@
.video-preview {
display: flex;
justify-content: center;
align-items: center;
.video-player {
height: auto;
border: none;
border-radius: .75rem;
}
}
.video-thumbnail {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
img {
cursor: pointer;
}
.button {
margin-top: 20px;
}
}
.loading-spinner {
margin: auto;
width: 5rem;
height: 5rem;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.hidden-spinner {
visibility: hidden;
}
.spinner-video-container {
width: 100%;
height: 100%;
position: relative;
}
.iframe-video-not-started {
visibility: hidden;
}
.iframe-video-started {
visibility: visible;
}

View file

@ -0,0 +1,42 @@
const PropTypes = require('prop-types');
const React = require('react');
const classNames = require('classnames');
require('./video-youtube.scss');
// eslint-disable-next-line react/prefer-stateless-function
class VideoYoutube extends React.Component {
render () {
return (
<div className={classNames('video-player', this.props.className)}>
<iframe
allowFullScreen
className="wistia_embed"
frameBorder="0" // deprecated attribute
height={this.props.height}
scrolling="no" // deprecated attribute
src={`https://www.youtube.com/embed/${this.props.videoId}?autoplay=1`}
title={this.props.title}
width={this.props.width}
/>
</div>
);
}
}
VideoYoutube.defaultProps = {
height: '225',
title: '',
width: '400'
};
VideoYoutube.propTypes = {
className: PropTypes.string,
height: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
videoId: PropTypes.string.isRequired,
width: PropTypes.string.isRequired
};
module.exports = VideoYoutube;

View file

@ -0,0 +1,9 @@
@import "../../../../colors";
@import "../../../../frameless";
.video-player {
border: .25rem solid $box-shadow-light-gray;
border-radius: .75rem;
height: 225px;
overflow: hidden;
}