mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-12-12 00:31:11 -05:00
feat: [UEPR-88] added modal for written guides
This commit is contained in:
parent
c27046698a
commit
1b76b929b4
16 changed files with 455 additions and 57 deletions
143
src/components/cards-modal/cards-modal.jsx
Normal file
143
src/components/cards-modal/cards-modal.jsx
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
import React, {useCallback, useState} from 'react';
|
||||||
|
import ReactModal from 'react-modal';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Button from '../forms/button.jsx';
|
||||||
|
import {FormattedMessage, useIntl} from 'react-intl';
|
||||||
|
import ModalNavigation from '../modal-navigation/modal-navigation.jsx';
|
||||||
|
|
||||||
|
import './cards-modal.scss';
|
||||||
|
|
||||||
|
const GUIDES_SECTIONS = [
|
||||||
|
{
|
||||||
|
titleId: 'ideas.modalSectionTitleSpritesAndSounds',
|
||||||
|
imgSrc: '/images/ideas/sprites-sounds.svg',
|
||||||
|
cards: [
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameCreateSprite',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_CreateOriginalSpriteLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameRemix',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_RemixRe-imagineSpritesLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameBringDrawingsIntoScratch',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_BringYourDrawingsIntoScratchLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameSound',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_SoundsAddRecordText-to-SpeechLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameCreateAsset',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_CreateanAssetPackLink'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
titleId: 'ideas.modalSectionTitleAdvancedTopics',
|
||||||
|
imgSrc: '/images/ideas/advanced-topics.svg',
|
||||||
|
cards: [
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameConditionalStatements',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_ConditionalStatementsLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameVariablesLists',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_VariablesandListsLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameCustomBlocks',
|
||||||
|
hrefId: 'guides.ScratchLearningResource_MyBlocksLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameFaceSensing',
|
||||||
|
hrefId: 'cards.paperplanes-turtlegraphics-cardsLink'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cardId: 'ideas.modalCardNameComputationalConcepts',
|
||||||
|
hrefId: 'cards.facesensing-cardsLink'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const CardsModal = ({isOpen, onClose = () => {}}) => {
|
||||||
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
|
const intl = useIntl();
|
||||||
|
const onNextPage = useCallback(() => {
|
||||||
|
if (currentPage < GUIDES_SECTIONS.length - 1) {
|
||||||
|
setCurrentPage(currentPage + 1);
|
||||||
|
}
|
||||||
|
}, [currentPage]);
|
||||||
|
const onBackPage = useCallback(() => {
|
||||||
|
if (currentPage > 0) {
|
||||||
|
setCurrentPage(currentPage - 1);
|
||||||
|
}
|
||||||
|
}, [currentPage]);
|
||||||
|
|
||||||
|
if (!isOpen) return null;
|
||||||
|
return (
|
||||||
|
<ReactModal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onRequestClose={onClose}
|
||||||
|
className="cards-modal-container"
|
||||||
|
overlayClassName="cards-modal-overlay"
|
||||||
|
>
|
||||||
|
<div className="cards-modal-header">
|
||||||
|
<div className="cards-title">
|
||||||
|
<FormattedMessage id={'ideas.modalTitle'} />
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
className="close-button"
|
||||||
|
isCloseType
|
||||||
|
onClick={onClose}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="cards-modal-section-title">
|
||||||
|
<FormattedMessage id={GUIDES_SECTIONS[currentPage].titleId} />
|
||||||
|
</div>
|
||||||
|
<div className="cards-modal-section-content">
|
||||||
|
<img
|
||||||
|
className="section-img"
|
||||||
|
src={GUIDES_SECTIONS[currentPage].imgSrc}
|
||||||
|
/>
|
||||||
|
<div className="cards-modal-cards-list">
|
||||||
|
{GUIDES_SECTIONS[currentPage].cards.map(card => (
|
||||||
|
<div
|
||||||
|
key={card.cardId}
|
||||||
|
className="card"
|
||||||
|
>
|
||||||
|
<FormattedMessage id={card.cardId} />
|
||||||
|
<a
|
||||||
|
href={intl.formatMessage({
|
||||||
|
id: card.hrefId
|
||||||
|
})}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<Button>
|
||||||
|
<img src="/images/ideas/download-icon.svg" />
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ModalNavigation
|
||||||
|
currentPage={currentPage}
|
||||||
|
totalDots={GUIDES_SECTIONS.length}
|
||||||
|
nextButtonImageSrc="/images/ideas/right-arrow.svg"
|
||||||
|
prevButtonImageSrc="/images/ideas/left-arrow.svg"
|
||||||
|
onNextPage={onNextPage}
|
||||||
|
onBackPage={onBackPage}
|
||||||
|
className="cards-modal-navigation"
|
||||||
|
/>
|
||||||
|
</ReactModal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CardsModal.propTypes = {
|
||||||
|
isOpen: PropTypes.bool,
|
||||||
|
onClose: PropTypes.func
|
||||||
|
};
|
150
src/components/cards-modal/cards-modal.scss
Normal file
150
src/components/cards-modal/cards-modal.scss
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
@import "../../colors";
|
||||||
|
@import "../../frameless";
|
||||||
|
|
||||||
|
.cards-modal-overlay {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 510;
|
||||||
|
|
||||||
|
background-color: $box-shadow-light-gray;
|
||||||
|
border-color: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards-modal-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 640px;
|
||||||
|
|
||||||
|
box-shadow: 0 0 0 4px $ui-blue-25percent;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards-modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 10px;
|
||||||
|
background-color: $ui-blue;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
|
||||||
|
.cards-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
color: $ui-white;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button {
|
||||||
|
position: unset;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards-modal-section-title {
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
color: $header-gray;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 2rem;
|
||||||
|
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
margin: 0.75rem 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards-modal-section-content {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 1.25rem;
|
||||||
|
gap: 1.25rem;
|
||||||
|
|
||||||
|
.section-img {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards-modal-cards-list {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card + .card {
|
||||||
|
border-top: 1px solid $box-shadow-light-gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards-modal-navigation {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin: 1.75rem 0;
|
||||||
|
|
||||||
|
.navigation-button {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dotRow{
|
||||||
|
width: 32px;
|
||||||
|
height: 16px;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot{
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 2px solid $ui-blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active{
|
||||||
|
background-color: $ui-blue;
|
||||||
|
box-shadow: 0 0 0 4px $ui-blue-25percent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards-modal-container:focus {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: $mobileIntermediate) {
|
||||||
|
.cards-modal-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,13 +36,25 @@ export const CommunityGuidelinesModal = props => {
|
||||||
<CommunityGuidelines
|
<CommunityGuidelines
|
||||||
userId={props.userId}
|
userId={props.userId}
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
onNextPage={currentPage < communityGuidelines.length - 1 ? onNextPage : onComplete}
|
onNextPage={
|
||||||
nextButtonText={currentPage === communityGuidelines.length - 1 ?
|
currentPage < communityGuidelines.length - 1 ?
|
||||||
<FormattedMessage id={'communityGuidelines.buttons.finish'} /> :
|
onNextPage :
|
||||||
null}
|
onComplete
|
||||||
|
}
|
||||||
|
nextButtonText={
|
||||||
|
currentPage === communityGuidelines.length - 1 ? (
|
||||||
|
<FormattedMessage id={'communityGuidelines.buttons.finish'} />
|
||||||
|
) : (
|
||||||
|
<FormattedMessage id={'communityGuidelines.buttons.next'} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
prevButtonText={
|
||||||
|
<FormattedMessage id={'communityGuidelines.buttons.back'} />
|
||||||
|
}
|
||||||
onBackPage={currentPage > 0 ? onBackPage : null}
|
onBackPage={currentPage > 0 ? onBackPage : null}
|
||||||
/>
|
/>
|
||||||
</ReactModal>);
|
</ReactModal>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
CommunityGuidelinesModal.propTypes = {
|
CommunityGuidelinesModal.propTypes = {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, {useEffect} from 'react';
|
import React, {useEffect} from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
import thumbnailUrl from '../../lib/user-thumbnail.js';
|
import thumbnailUrl from '../../lib/user-thumbnail.js';
|
||||||
import OnboardingNavigation from '../onboarding-navigation/onboarding-navigation.jsx';
|
import ModalNavigation from '../modal-navigation/modal-navigation.jsx';
|
||||||
|
|
||||||
import './community-guidelines.scss';
|
import './community-guidelines.scss';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
@ -65,6 +65,7 @@ export const CommunityGuidelines = ({
|
||||||
userId,
|
userId,
|
||||||
currentPage,
|
currentPage,
|
||||||
nextButtonText,
|
nextButtonText,
|
||||||
|
prevButtonText,
|
||||||
onNextPage,
|
onNextPage,
|
||||||
onBackPage
|
onBackPage
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -108,10 +109,11 @@ export const CommunityGuidelines = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<OnboardingNavigation
|
<ModalNavigation
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
totalDots={communityGuidelines.length}
|
totalDots={communityGuidelines.length}
|
||||||
nextButtonText={nextButtonText}
|
nextButtonText={nextButtonText}
|
||||||
|
prevButtonText={prevButtonText}
|
||||||
onNextPage={onNextPage}
|
onNextPage={onNextPage}
|
||||||
onBackPage={onBackPage}
|
onBackPage={onBackPage}
|
||||||
/>
|
/>
|
||||||
|
@ -123,7 +125,8 @@ CommunityGuidelines.propTypes = {
|
||||||
currentPage: PropTypes.number,
|
currentPage: PropTypes.number,
|
||||||
userId: PropTypes.string,
|
userId: PropTypes.string,
|
||||||
constructHeader: PropTypes.func,
|
constructHeader: PropTypes.func,
|
||||||
nextButtonText: PropTypes.string,
|
nextButtonText: PropTypes.node,
|
||||||
|
prevButtonText: PropTypes.node,
|
||||||
onNextPage: PropTypes.func,
|
onNextPage: PropTypes.func,
|
||||||
onBackPage: PropTypes.func
|
onBackPage: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,10 @@ $pass-bg: $ui-aqua;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.transparent {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
&.large {
|
&.large {
|
||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
import React, {useEffect, useMemo} from 'react';
|
import React, {useEffect, useMemo} from 'react';
|
||||||
import Button from '../forms/button.jsx';
|
import Button from '../forms/button.jsx';
|
||||||
import {FormattedMessage} from 'react-intl';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import './onboarding-navigation.scss';
|
import './modal-navigation.scss';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
const OnboardingNavigation = ({
|
const ModalNavigation = ({
|
||||||
currentPage,
|
currentPage,
|
||||||
totalDots,
|
totalDots,
|
||||||
onNextPage,
|
onNextPage,
|
||||||
onBackPage,
|
onBackPage,
|
||||||
nextButtonText
|
nextButtonText,
|
||||||
|
prevButtonText,
|
||||||
|
nextButtonImageSrc,
|
||||||
|
prevButtonImageSrc,
|
||||||
|
className
|
||||||
}) => {
|
}) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
new Image().src = '/images/onboarding/right-arrow.svg';
|
new Image().src = nextButtonImageSrc;
|
||||||
new Image().src = '/images/onboarding/left-arrow.svg';
|
new Image().src = prevButtonImageSrc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const dots = useMemo(() => {
|
const dots = useMemo(() => {
|
||||||
|
@ -32,49 +35,62 @@ const OnboardingNavigation = ({
|
||||||
}, [currentPage, totalDots]);
|
}, [currentPage, totalDots]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="navigation">
|
<div className={classNames('navigation', className)}>
|
||||||
{
|
{
|
||||||
<Button
|
<Button
|
||||||
onClick={onBackPage}
|
onClick={onBackPage}
|
||||||
className={classNames({
|
className={classNames('navigation-button', {
|
||||||
hidden: !onBackPage
|
hidden: !onBackPage,
|
||||||
|
transparent: !prevButtonText
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className="left-arrow"
|
className="left-arrow"
|
||||||
alt=""
|
alt=""
|
||||||
src="/images/onboarding/left-arrow.svg"
|
src={prevButtonImageSrc}
|
||||||
/>
|
/>
|
||||||
<span className="navText">
|
<span className="navText">
|
||||||
{<FormattedMessage
|
{prevButtonText}
|
||||||
id={'communityGuidelines.buttons.back'}
|
|
||||||
/>}
|
|
||||||
</span>
|
</span>
|
||||||
</Button> }
|
</Button> }
|
||||||
{(currentPage >= 0 && totalDots) &&
|
{(currentPage >= 0 && totalDots) &&
|
||||||
<div className="dotRow">
|
<div className="dotRow">
|
||||||
{dots}
|
{dots}
|
||||||
</div>}
|
</div>}
|
||||||
<Button onClick={onNextPage}>
|
<Button
|
||||||
|
onClick={onNextPage}
|
||||||
|
className={classNames('navigation-button', {
|
||||||
|
transparent: !nextButtonText
|
||||||
|
})}
|
||||||
|
>
|
||||||
<span className="navText">
|
<span className="navText">
|
||||||
{nextButtonText || <FormattedMessage id={'communityGuidelines.buttons.next'} />}
|
{nextButtonText}
|
||||||
</span>
|
</span>
|
||||||
<img
|
<img
|
||||||
className="right-arrow"
|
className="right-arrow"
|
||||||
alt=""
|
alt=""
|
||||||
src="/images/onboarding/right-arrow.svg"
|
src={nextButtonImageSrc}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
OnboardingNavigation.propTypes = {
|
ModalNavigation.propTypes = {
|
||||||
currentPage: PropTypes.number,
|
currentPage: PropTypes.number,
|
||||||
totalDots: PropTypes.number,
|
totalDots: PropTypes.number,
|
||||||
onNextPage: PropTypes.func,
|
onNextPage: PropTypes.func,
|
||||||
onBackPage: PropTypes.func,
|
onBackPage: PropTypes.func,
|
||||||
nextButtonText: PropTypes.node
|
nextButtonText: PropTypes.node,
|
||||||
|
prevButtonText: PropTypes.node,
|
||||||
|
nextButtonImageSrc: PropTypes.string,
|
||||||
|
prevButtonImageSrc: PropTypes.string,
|
||||||
|
className: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OnboardingNavigation;
|
ModalNavigation.defaultProps = {
|
||||||
|
nextButtonImageSrc: '/images/onboarding/right-arrow.svg',
|
||||||
|
prevButtonImageSrc: '/images/onboarding/left-arrow.svg'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModalNavigation;
|
|
@ -1,7 +1,7 @@
|
||||||
@import "../../colors";
|
@import "../../colors";
|
||||||
@import "../../frameless";
|
@import "../../frameless";
|
||||||
|
|
||||||
.button{
|
.navigation-button{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -35,6 +35,7 @@
|
||||||
.dotRow{
|
.dotRow{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
width: 244px;
|
width: 244px;
|
||||||
min-width: 0px;
|
min-width: 0px;
|
||||||
padding: 0px 5px;
|
padding: 0px 5px;
|
|
@ -14,7 +14,7 @@ import Button from '../../components/forms/button.jsx';
|
||||||
import Modal from '../../components/modal/base/modal.jsx';
|
import Modal from '../../components/modal/base/modal.jsx';
|
||||||
import NotAvailable from '../../components/not-available/not-available.jsx';
|
import NotAvailable from '../../components/not-available/not-available.jsx';
|
||||||
import WarningBanner from '../../components/title-banner/warning-banner.jsx';
|
import WarningBanner from '../../components/title-banner/warning-banner.jsx';
|
||||||
import OnboardingNavigation from '../../components/onboarding-navigation/onboarding-navigation.jsx';
|
import ModalNavigation from '../../components/modal-navigation/modal-navigation.jsx';
|
||||||
import {
|
import {
|
||||||
CommunityGuidelines,
|
CommunityGuidelines,
|
||||||
communityGuidelines
|
communityGuidelines
|
||||||
|
@ -285,10 +285,11 @@ const BecomeAScratcher = ({user, invitedScratcher, scratcher, sessionStatus}) =>
|
||||||
<FormattedMessage id={'becomeAScratcher.toBeAScratcher.communityGuidelines'} />
|
<FormattedMessage id={'becomeAScratcher.toBeAScratcher.communityGuidelines'} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<OnboardingNavigation
|
<ModalNavigation
|
||||||
onNextPage={nextPage}
|
onNextPage={nextPage}
|
||||||
onBackPage={backPage}
|
onBackPage={backPage}
|
||||||
nextButtonText={<FormattedMessage id={'becomeAScratcher.buttons.communityGuidelines'} />}
|
nextButtonText={<FormattedMessage id={'becomeAScratcher.buttons.communityGuidelines'} />}
|
||||||
|
prevButtonText={<FormattedMessage id={'communityGuidelines.buttons.back'} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const FormattedMessage = require('react-intl').FormattedMessage;
|
const FormattedMessage = require('react-intl').FormattedMessage;
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
const {useState, useCallback} = require('react');
|
||||||
|
|
||||||
const Button = require('../../components/forms/button.jsx');
|
const Button = require('../../components/forms/button.jsx');
|
||||||
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
||||||
|
@ -9,6 +10,7 @@ const Page = require('../../components/page/www/page.jsx');
|
||||||
const render = require('../../lib/render.jsx');
|
const render = require('../../lib/render.jsx');
|
||||||
|
|
||||||
const {useIntl} = require('react-intl');
|
const {useIntl} = require('react-intl');
|
||||||
|
const {CardsModal} = require('../../components/cards-modal/cards-modal.jsx');
|
||||||
|
|
||||||
require('./ideas.scss');
|
require('./ideas.scss');
|
||||||
|
|
||||||
|
@ -87,6 +89,10 @@ const physicalIdeasData = [
|
||||||
|
|
||||||
const Ideas = () => {
|
const Ideas = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const onOpen = useCallback(() => setIsOpen(true), [setIsOpen]);
|
||||||
|
const onClose = useCallback(() => setIsOpen(false), [setIsOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -154,6 +160,31 @@ const Ideas = () => {
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="youtube-videos">
|
||||||
|
<div className="inner">
|
||||||
|
<div
|
||||||
|
className="download-cards"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className="pass"
|
||||||
|
onClick={onOpen}
|
||||||
|
>
|
||||||
|
<img src="/images/ideas/download-icon.svg" />
|
||||||
|
</Button>
|
||||||
|
<FormattedMessage
|
||||||
|
id="ideas.downloadGuides"
|
||||||
|
values={{
|
||||||
|
strong: chunks => <strong>{chunks}</strong>,
|
||||||
|
a: chunks => <a onClick={onOpen}>{chunks}</a>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CardsModal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="physical-ideas">
|
<div className="physical-ideas">
|
||||||
<div className="inner">
|
<div className="inner">
|
||||||
<div className="section-header">
|
<div className="section-header">
|
||||||
|
|
|
@ -40,6 +40,36 @@ $base-bg: $ui-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.youtube-videos {
|
||||||
|
.inner {
|
||||||
|
.download-cards {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
margin-bottom: 3.5rem;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
text-align: start;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.physical-ideas {
|
.physical-ideas {
|
||||||
.inner {
|
.inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
"cards.pong-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/pong-cards.pdf",
|
"cards.pong-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/pong-cards.pdf",
|
||||||
"cards.fly-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/fly-cards.pdf",
|
"cards.fly-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/fly-cards.pdf",
|
||||||
"cards.imagine-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/imagine-cards.pdf",
|
"cards.imagine-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/imagine-cards.pdf",
|
||||||
|
"cards.paperplanes-turtlegraphics-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/paperplanes-turtlegraphics-cards.pdf",
|
||||||
|
"cards.facesensing-cardsLink": "https://resources.scratch.mit.edu/www/cards/en/facesensing-cards.pdf",
|
||||||
"guides.NameGuideLink": "https://resources.scratch.mit.edu/www/guides/en/NameGuide.pdf",
|
"guides.NameGuideLink": "https://resources.scratch.mit.edu/www/guides/en/NameGuide.pdf",
|
||||||
"guides.AnimateGuideLink": "https://resources.scratch.mit.edu/www/guides/en/AnimateGuide.pdf",
|
"guides.AnimateGuideLink": "https://resources.scratch.mit.edu/www/guides/en/AnimateGuide.pdf",
|
||||||
"guides.MusicGuideLink": "https://resources.scratch.mit.edu/www/guides/en/MusicGuide.pdf",
|
"guides.MusicGuideLink": "https://resources.scratch.mit.edu/www/guides/en/MusicGuide.pdf",
|
||||||
|
@ -19,5 +21,13 @@
|
||||||
"guides.VideoGuideLink": "https://resources.scratch.mit.edu/www/guides/en/VideoGuide.pdf",
|
"guides.VideoGuideLink": "https://resources.scratch.mit.edu/www/guides/en/VideoGuide.pdf",
|
||||||
"guides.PongGuideLink": "https://resources.scratch.mit.edu/www/guides/en/PongGuide.pdf",
|
"guides.PongGuideLink": "https://resources.scratch.mit.edu/www/guides/en/PongGuide.pdf",
|
||||||
"guides.FlyGuideLink": "https://resources.scratch.mit.edu/www/guides/en/FlyGuide.pdf",
|
"guides.FlyGuideLink": "https://resources.scratch.mit.edu/www/guides/en/FlyGuide.pdf",
|
||||||
"guides.ImagineGuideLink": "https://resources.scratch.mit.edu/www/guides/en/ImagineGuide.pdf"
|
"guides.ImagineGuideLink": "https://resources.scratch.mit.edu/www/guides/en/ImagineGuide.pdf",
|
||||||
|
"guides.ScratchLearningResource_CreateOriginalSpriteLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_CreateOriginalSprite.pdf",
|
||||||
|
"guides.ScratchLearningResource_RemixRe-imagineSpritesLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_RemixRe-imagineSprites.pdf",
|
||||||
|
"guides.ScratchLearningResource_BringYourDrawingsIntoScratchLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_BringYourDrawingsIntoScratch.pdf",
|
||||||
|
"guides.ScratchLearningResource_SoundsAddRecordText-to-SpeechLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_SoundsAddRecordText-to-Speech.pdf",
|
||||||
|
"guides.ScratchLearningResource_CreateanAssetPackLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_CreateanAssetPack.pdf",
|
||||||
|
"guides.ScratchLearningResource_ConditionalStatementsLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_ConditionalStatements.pdf",
|
||||||
|
"guides.ScratchLearningResource_VariablesandListsLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_VariablesandLists.pdf",
|
||||||
|
"guides.ScratchLearningResource_MyBlocksLink": "https://resources.scratch.mit.edu/www/guides/en/ScratchLearningResource_MyBlocks.pdf"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,11 @@
|
||||||
"ideas.headerMessage": "What will you create?",
|
"ideas.headerMessage": "What will you create?",
|
||||||
"ideas.headerImageDescription": "Outlandish creations from pixelated unicorns to drumbeat waveforms to levitating tacos to buckets of rainbows.",
|
"ideas.headerImageDescription": "Outlandish creations from pixelated unicorns to drumbeat waveforms to levitating tacos to buckets of rainbows.",
|
||||||
"ideas.headerButtonMessage": "Choose a tutorial",
|
"ideas.headerButtonMessage": "Choose a tutorial",
|
||||||
"ideas.gettingStartedTitle": "Getting Started",
|
"ideas.startHereText": "New to Scratch? Start here!",
|
||||||
"ideas.gettingStartedText": "New to Scratch? Try the Getting Started tutorial.",
|
|
||||||
"ideas.startHereText": "New to Scratch? Stay here!",
|
|
||||||
"ideas.gettingStartedButtonText": "Try Getting Started Tutorial",
|
"ideas.gettingStartedButtonText": "Try Getting Started Tutorial",
|
||||||
"ideas.seeTutorialsLibraryButtonText": "See Tutorials Library",
|
"ideas.seeTutorialsLibraryButtonText": "See Tutorials Library",
|
||||||
"ideas.gettingStartedImageDescription": "An illustrated boy plants his flag on top of a freshly painted mountaintop.",
|
"ideas.gettingStartedImageDescription": "An illustrated boy plants his flag on top of a freshly painted mountaintop.",
|
||||||
"ideas.seeTutorialsLibraryImageDescription": "An illustration of three tutorial thumbnails.",
|
"ideas.seeTutorialsLibraryImageDescription": "An illustration of three tutorial thumbnails.",
|
||||||
"ideas.tryIt": "Try it!",
|
|
||||||
"ideas.activityGuidesTitle": "Activity Guides",
|
|
||||||
"ideas.activityGuidesText": "What do you want to make with Scratch? For each activity, you can try the Tutorial, download a set of Coding Cards, or view the Educator Guide.",
|
|
||||||
"ideas.animateANameTitle": "Animate a Name",
|
"ideas.animateANameTitle": "Animate a Name",
|
||||||
"ideas.animateANameDescription": "Animate the letters of your name, initials, or favorite word.",
|
"ideas.animateANameDescription": "Animate the letters of your name, initials, or favorite word.",
|
||||||
"ideas.animateANameImageDescription": "The name ANYA in all caps and blocked letters is poised to wiggle",
|
"ideas.animateANameImageDescription": "The name ANYA in all caps and blocked letters is poised to wiggle",
|
||||||
|
@ -30,12 +25,7 @@
|
||||||
"ideas.videoSensingTitle": "Video Sensing",
|
"ideas.videoSensingTitle": "Video Sensing",
|
||||||
"ideas.videoSensingDescription": "Interact with a project using the Video Sensing extension.",
|
"ideas.videoSensingDescription": "Interact with a project using the Video Sensing extension.",
|
||||||
"ideas.videoSensingImageDescription": "A virtual hand dodges a spurt of flame in an attempt to pet a dragon.",
|
"ideas.videoSensingImageDescription": "A virtual hand dodges a spurt of flame in an attempt to pet a dragon.",
|
||||||
"ideas.seeAllTutorials": "See All Tutorials",
|
|
||||||
"ideas.cardsTitle": "Get the Entire Collection of Coding Cards",
|
|
||||||
"ideas.cardsText": "With the Scratch Coding Cards, you can learn to create interactive games, stories, music, animations, and more!",
|
|
||||||
"ideas.cardsIllustrationDescription": "An assortment of fun, animated characters and objects leap out of a stack of cards.",
|
"ideas.cardsIllustrationDescription": "An assortment of fun, animated characters and objects leap out of a stack of cards.",
|
||||||
"ideas.starterProjectsTitle": "Starter Projects",
|
|
||||||
"ideas.starterProjectsText": "You can play with Starter Projects and remix them to make your own creations.",
|
|
||||||
"ideas.starterProjectsImageDescription": "An illustration of the Scratch Code Editor.",
|
"ideas.starterProjectsImageDescription": "An illustration of the Scratch Code Editor.",
|
||||||
"ideas.starterProjectsButton": "Explore Starter Projects",
|
"ideas.starterProjectsButton": "Explore Starter Projects",
|
||||||
"ideas.tryTheTutorial": "Try the tutorial",
|
"ideas.tryTheTutorial": "Try the tutorial",
|
||||||
|
@ -47,31 +37,30 @@
|
||||||
"ideas.makeyMakeyHeader": "Have a MakeyMakey?",
|
"ideas.makeyMakeyHeader": "Have a MakeyMakey?",
|
||||||
"ideas.makeyMakeyBody": "Turn anything into a key that connects with your Scratch project!",
|
"ideas.makeyMakeyBody": "Turn anything into a key that connects with your Scratch project!",
|
||||||
"ideas.desktopEditorHeader": "Scratch App Download",
|
"ideas.desktopEditorHeader": "Scratch App Download",
|
||||||
"ideas.desktopEditorBody": "To create projects without an Internet connection, you can <a href=\"/download\">download the Scratch app</a>.",
|
|
||||||
"ideas.desktopEditorBodyHTML": "To create projects without an Internet connection, you can <a>download the Scratch app</a>.",
|
"ideas.desktopEditorBodyHTML": "To create projects without an Internet connection, you can <a>download the Scratch app</a>.",
|
||||||
"ideas.questionsHeader": "Questions",
|
"ideas.questionsHeader": "Questions",
|
||||||
"ideas.questionsBody": "Have more questions? See the <a href=\"/info/faq\">Frequently Asked Questions</a> or visit the <a href=\"/discuss/7/\">Help with Scripts Forum</a>.",
|
|
||||||
"ideas.questionsBodyHTML": "Have more questions? See the <faq>Frequently Asked Questions</faq> or visit the <forum>Help with Scripts Forum</forum>.",
|
"ideas.questionsBodyHTML": "Have more questions? See the <faq>Frequently Asked Questions</faq> or visit the <forum>Help with Scripts Forum</forum>.",
|
||||||
"ideas.cardsPurchase": "Purchase Printed Set",
|
|
||||||
"ideas.MakeItFlyTitle": "Make It Fly",
|
"ideas.MakeItFlyTitle": "Make It Fly",
|
||||||
"ideas.MakeItFlyDescription": "Choose any character and make it fly!",
|
"ideas.MakeItFlyDescription": "Choose any character and make it fly!",
|
||||||
"ideas.MakeItFlyImageDescription": "The scratch cat flies over the skyline. Alongside a flying taco.",
|
"ideas.MakeItFlyImageDescription": "The scratch cat flies over the skyline. Alongside a flying taco.",
|
||||||
"ideas.RaceTitle": "Race to the Finish",
|
|
||||||
"ideas.RaceDescription": "Make a game where two characters race each other.",
|
|
||||||
"ideas.HideAndSeekTitle": "Hide and Seek",
|
|
||||||
"ideas.HideAndSeekDescription": "Make a hide-and-seek game with characters that appear and disappear.",
|
|
||||||
"ideas.FashionTitle": "Fashion Game",
|
|
||||||
"ideas.FashionDescription": "Make a game where you dress a character with different clothes and styles.",
|
|
||||||
"ideas.PongTitle": "Pong Game",
|
"ideas.PongTitle": "Pong Game",
|
||||||
"ideas.PongDescription": "Make a bouncing ball game with sounds, points, and other effects.",
|
"ideas.PongDescription": "Make a bouncing ball game with sounds, points, and other effects.",
|
||||||
"ideas.PongImageDescription": "A ball bounces off a digital paddle.",
|
"ideas.PongImageDescription": "A ball bounces off a digital paddle.",
|
||||||
"ideas.ImagineTitle": "Imagine a World",
|
"ideas.ImagineTitle": "Imagine a World",
|
||||||
"ideas.ImagineDescription": "Imagine a world where anything is possible.",
|
"ideas.ImagineDescription": "Imagine a world where anything is possible.",
|
||||||
"ideas.ImagineImageDescription": "A girl stands proudly in front of a thought bubble as big as the Earth and as intricate as butterfly wings.",
|
"ideas.ImagineImageDescription": "A girl stands proudly in front of a thought bubble as big as the Earth and as intricate as butterfly wings.",
|
||||||
"ideas.DanceTitle": "Let's Dance",
|
"ideas.modalTitle": "Written Guides",
|
||||||
"ideas.DanceDescription": "Design an animated dance scene with music and dance moves.",
|
"ideas.modalSectionTitleSpritesAndSounds": "Sprites and Sounds",
|
||||||
"ideas.CatchTitle": "Catch Game",
|
"ideas.modalSectionTitleAdvancedTopics": "Advanced Topics",
|
||||||
"ideas.CatchDescription": "Make a game where you catch things falling from the sky.",
|
"ideas.modalCardNameCreateSprite": "Create a Sprite with the Paint Editor",
|
||||||
"ideas.VirtualPetTitle": "Virtual Pet",
|
"ideas.modalCardNameRemix": "Remix and Re-Imagine Sprites",
|
||||||
"ideas.VirtualPetDescription": "Create an interactive pet that can eat, drink, and play."
|
"ideas.modalCardNameBringDrawingsIntoScratch": "Bring Your Drawings Into Scratch",
|
||||||
|
"ideas.modalCardNameSound": "Sound: Add, Record, and Use Text to Speech Blocks",
|
||||||
|
"ideas.modalCardNameCreateAsset": "Create Your Own Asset Pack",
|
||||||
|
"ideas.modalCardNameConditionalStatements": "Conditional Statements",
|
||||||
|
"ideas.modalCardNameVariablesLists": "Variables and Lists",
|
||||||
|
"ideas.modalCardNameCustomBlocks": "Make Your Custom My Blocks",
|
||||||
|
"ideas.modalCardNameFaceSensing": "Scratch Lab Face Sensing Coding Cards",
|
||||||
|
"ideas.modalCardNameComputationalConcepts": "Turtle Graphics Coding Cards",
|
||||||
|
"ideas.downloadGuides": "<strong>Computer doesn’t allow Youtube?</strong> Download <a>written guides</a> for these topics."
|
||||||
}
|
}
|
||||||
|
|
1
static/images/ideas/advanced-topics.svg
Normal file
1
static/images/ideas/advanced-topics.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 14 KiB |
3
static/images/ideas/left-arrow.svg
Normal file
3
static/images/ideas/left-arrow.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="19" viewBox="0 0 24 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.558139 10.7977L7.83016 18.2108C8.42768 18.7845 9.26604 18.9379 9.9863 18.6192C10.7066 18.3028 11.1512 17.604 11.1512 16.7943L11.1512 13.9825L21.2718 12.5494C22.8212 12.344 24 10.97 24 9.35284C24 9.21355 23.9907 9.0719 23.9745 8.93261C23.7499 7.4736 22.6336 6.34747 21.2603 6.17041L11.1512 4.6996L11.1512 2.01058C11.1512 1.19137 10.6788 0.461858 9.94924 0.152587C9.21509 -0.156686 8.4022 0.0109341 7.83016 0.594066L0.558139 8.00716C0.199169 8.37545 -8.6648e-07 8.87123 -8.20042e-07 9.40242C-7.73604e-07 9.93361 0.199169 10.4294 0.558139 10.7977Z" fill="#4C97FF"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 718 B |
3
static/images/ideas/right-arrow.svg
Normal file
3
static/images/ideas/right-arrow.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="19" viewBox="0 0 24 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.4419 10.7977L16.1698 18.2108C15.5723 18.7845 14.734 18.9379 14.0137 18.6192C13.2934 18.3028 12.8488 17.604 12.8488 16.7943L12.8488 13.9825L2.72817 12.5494C1.17881 12.344 6.82997e-07 10.97 8.24376e-07 9.35284C8.36553e-07 9.21355 0.00926484 9.0719 0.0254754 8.93261C0.250121 7.4736 1.3664 6.34747 2.73975 6.17041L12.8488 4.6996L12.8488 2.01058C12.8488 1.19137 13.3212 0.461858 14.0508 0.152587C14.7849 -0.156686 15.5978 0.0109341 16.1698 0.594066L23.4419 8.00716C23.8008 8.37545 24 8.87123 24 9.40242C24 9.93361 23.8008 10.4294 23.4419 10.7977Z" fill="#4C97FF"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 717 B |
1
static/images/ideas/sprites-sounds.svg
Normal file
1
static/images/ideas/sprites-sounds.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.6 KiB |
Loading…
Reference in a new issue