mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-02-17 00:21:20 -05:00
Merge pull request #3241 from benjiwheeler/join-flow-info-button
Join flow info button
This commit is contained in:
commit
2e506de6be
7 changed files with 168 additions and 0 deletions
46
src/components/info-button/info-button.jsx
Normal file
46
src/components/info-button/info-button.jsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
const bindAll = require('lodash.bindall');
|
||||
const PropTypes = require('prop-types');
|
||||
const React = require('react');
|
||||
|
||||
require('./info-button.scss');
|
||||
|
||||
class InfoButton extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'handleHideMessage',
|
||||
'handleShowMessage'
|
||||
]);
|
||||
this.state = {
|
||||
visible: false
|
||||
};
|
||||
}
|
||||
handleHideMessage () {
|
||||
this.setState({visible: false});
|
||||
}
|
||||
handleShowMessage () {
|
||||
this.setState({visible: true});
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div
|
||||
className="info-button"
|
||||
onClick={this.handleShowMessage}
|
||||
onMouseOut={this.handleHideMessage}
|
||||
onMouseOver={this.handleShowMessage}
|
||||
>
|
||||
{this.state.visible && (
|
||||
<div className="info-button-message">
|
||||
{this.props.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
InfoButton.propTypes = {
|
||||
message: PropTypes.string
|
||||
};
|
||||
|
||||
module.exports = InfoButton;
|
78
src/components/info-button/info-button.scss
Normal file
78
src/components/info-button/info-button.scss
Normal file
|
@ -0,0 +1,78 @@
|
|||
@import "../../colors";
|
||||
@import "../../frameless";
|
||||
|
||||
.info-button {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin-left: .375rem;
|
||||
border-radius: 50%;
|
||||
background-color: $ui-blue;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: "?";
|
||||
color: $ui-white;
|
||||
font-family: verdana;
|
||||
font-weight: 400;
|
||||
top: -.125rem;
|
||||
left: .325rem;
|
||||
font-size: .75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.info-button-message {
|
||||
$arrow-border-width: 1rem;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translate(1rem, -1rem);
|
||||
width: 16.5rem;
|
||||
min-height: 1rem;
|
||||
margin-left: $arrow-border-width;
|
||||
border: 1px solid $active-gray;
|
||||
border-radius: 5px;
|
||||
padding: .75rem;
|
||||
overflow: visible;
|
||||
background-color: $ui-blue;
|
||||
color: $type-white;
|
||||
line-height: 1.25rem;
|
||||
text-align: left;
|
||||
font-size: .875rem;
|
||||
z-index: 1;
|
||||
|
||||
&:before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
left: -$arrow-border-width / 2;
|
||||
|
||||
transform: rotate(45deg);
|
||||
|
||||
border-bottom: 1px solid $active-gray;
|
||||
border-left: 1px solid $active-gray;
|
||||
border-radius: 5px;
|
||||
|
||||
background-color: $ui-blue;
|
||||
width: $arrow-border-width;
|
||||
height: $arrow-border-width;
|
||||
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$intermediate-and-smaller} {
|
||||
.info-button-message {
|
||||
position: relative;
|
||||
transform: none;
|
||||
margin: inherit;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -88,6 +88,7 @@ class BirthDateStep extends React.Component {
|
|||
<JoinFlowStep
|
||||
description={this.props.intl.formatMessage({id: 'registration.private'})}
|
||||
headerImgSrc="/images/hoc/getting-started.jpg"
|
||||
infoMessage={this.props.intl.formatMessage({id: 'registration.birthDateStepInfo'})}
|
||||
title={this.props.intl.formatMessage({id: 'registration.birthDateStepTitle'})}
|
||||
waiting={isSubmitting}
|
||||
onSubmit={handleSubmit}
|
||||
|
|
|
@ -82,6 +82,7 @@ class GenderStep extends React.Component {
|
|||
<JoinFlowStep
|
||||
className="join-flow-gender-step"
|
||||
description={this.props.intl.formatMessage({id: 'registration.genderStepDescription'})}
|
||||
infoMessage={this.props.intl.formatMessage({id: 'registration.genderStepInfo'})}
|
||||
title={this.props.intl.formatMessage({id: 'registration.genderStepTitle'})}
|
||||
waiting={isSubmitting}
|
||||
onSubmit={handleSubmit}
|
||||
|
|
|
@ -5,6 +5,7 @@ const PropTypes = require('prop-types');
|
|||
const NextStepButton = require('./next-step-button.jsx');
|
||||
const ModalTitle = require('../modal/base/modal-title.jsx');
|
||||
const ModalInnerContent = require('../modal/base/modal-inner-content.jsx');
|
||||
const InfoButton = require('../info-button/info-button.jsx');
|
||||
|
||||
require('./join-flow-step.scss');
|
||||
|
||||
|
@ -13,6 +14,7 @@ const JoinFlowStep = ({
|
|||
className,
|
||||
description,
|
||||
headerImgSrc,
|
||||
infoMessage,
|
||||
innerContentClassName,
|
||||
nextButton,
|
||||
onSubmit,
|
||||
|
@ -42,6 +44,9 @@ const JoinFlowStep = ({
|
|||
{description && (
|
||||
<div className="join-flow-description">
|
||||
{description}
|
||||
{infoMessage && (
|
||||
<InfoButton message={infoMessage} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
|
@ -59,6 +64,7 @@ JoinFlowStep.propTypes = {
|
|||
className: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
headerImgSrc: PropTypes.string,
|
||||
infoMessage: PropTypes.string,
|
||||
innerContentClassName: PropTypes.string,
|
||||
nextButton: PropTypes.node,
|
||||
onSubmit: PropTypes.func,
|
||||
|
|
|
@ -141,6 +141,7 @@
|
|||
"parents.FaqResourcesQ": "What resources are available for learning Scratch?",
|
||||
"parents.introDescription": "Scratch is a programming language and an online community where children can program and share interactive media such as stories, games, and animation with people from all over the world. As children create with Scratch, they learn to think creatively, work collaboratively, and reason systematically. Scratch is designed and maintained by the Lifelong Kindergarten group at the MIT Media Lab.",
|
||||
|
||||
"registration.birthDateStepInfo": "This helps us understand the age range of people who use Scratch. We use this to confirm account ownership if you contact our team. This information will not be made public on your account.",
|
||||
"registration.birthDateStepTitle": "When were you born?",
|
||||
"registration.checkOutResources": "Get Started with Resources",
|
||||
"registration.checkOutResourcesDescription": "Explore materials for educators and facilitators written by the Scratch Team, including <a href='/educators#resources'>tips, tutorials, and guides</a>.",
|
||||
|
@ -156,6 +157,7 @@
|
|||
"registration.createUsername": "Create a username",
|
||||
"registration.genderStepTitle": "What's your gender?",
|
||||
"registration.genderStepDescription": "Scratch welcomes people of all genders. We will always keep this information private.",
|
||||
"registration.genderStepInfo": "This helps us understand who uses Scratch, so that we can broaden participation. This information will not be made public on your account.",
|
||||
"registration.genderOptionAnother": "Another gender:",
|
||||
"registration.genderOptionPreferNotToSay": "Prefer not to say",
|
||||
"registration.emailStepTitle": "What's your email?",
|
||||
|
|
34
test/unit/components/info-button.test.jsx
Normal file
34
test/unit/components/info-button.test.jsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
import {mountWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import InfoButton from '../../../src/components/info-button/info-button';
|
||||
|
||||
describe('InfoButton', () => {
|
||||
test('Info button defaults to not visible', () => {
|
||||
const component = mountWithIntl(
|
||||
<InfoButton
|
||||
message="Here is some info about something!"
|
||||
/>
|
||||
);
|
||||
expect(component.find('div.info-button-message').exists()).toEqual(false);
|
||||
});
|
||||
test('clicking on info button makes info message visible', () => {
|
||||
const component = mountWithIntl(
|
||||
<InfoButton
|
||||
message="Here is some info about something!"
|
||||
/>
|
||||
);
|
||||
component.find('div.info-button').simulate('click');
|
||||
expect(component.find('div.info-button-message').exists()).toEqual(true);
|
||||
});
|
||||
test('after message is visible, mouseOut makes it vanish', () => {
|
||||
const component = mountWithIntl(
|
||||
<InfoButton
|
||||
message="Here is some info about something!"
|
||||
/>
|
||||
);
|
||||
component.find('div.info-button').simulate('click');
|
||||
expect(component.find('div.info-button-message').exists()).toEqual(true);
|
||||
component.find('div.info-button').simulate('mouseOut');
|
||||
expect(component.find('div.info-button-message').exists()).toEqual(false);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue