Created a reusable newsletter signup form and widget

This commit is contained in:
Piotr Janosz
2019-07-07 18:56:31 +02:00
committed by fabioberger
parent 7bad1d2921
commit d56fb374a7
5 changed files with 101 additions and 165 deletions

View File

@@ -1,82 +0,0 @@
import React from 'react';
import styled from 'styled-components';
import { Heading, Paragraph } from 'ts/components/text';
import { colors } from 'ts/style/colors';
export interface INewsletterSignupProps {
heading?: string;
description?: string;
url?: string;
}
export const NewsletterSignup: React.FC<INewsletterSignupProps> = props => {
// @TODO: Add newsletter signup loading / success / error states
return (
<NewsletterSignupWrapper href={props.url}>
<Heading marginBottom="8px">{props.heading}</Heading>
<Paragraph marginBottom="25px">{props.description}</Paragraph>
<InputWrapper>
<Label htmlFor="emailSignup">Email Address</Label>
<Input id="emailSignup" type="email" placeholder="Email Address" />
<Submit>
<svg width="22" height="17" viewBox="0 0 22 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
opacity=".5"
d="M13.066 0l-1.068 1.147 6.232 6.557H0v1.592h18.23l-6.232 6.557L13.066 17l8.08-8.5-8.08-8.5z"
fill="#5C5C5C"
/>
</svg>
</Submit>
</InputWrapper>
</NewsletterSignupWrapper>
);
};
NewsletterSignup.defaultProps = {
heading: 'Sign up for the Newsletter',
description: 'Body font about the newseletter',
};
const NewsletterSignupWrapper = styled.a`
background-color: ${colors.backgroundLight};
padding: 40px 30px 50px;
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
margin-bottom: 1.875rem;
`;
const Label = styled.label`
visibility: hidden;
opacity: 0;
position: absolute;
width: 0;
`;
const InputWrapper = styled.div`
padding: 0 40px;
position: relative;
`;
const Input = styled.input`
background-color: transparent;
border: 0;
border-bottom: 1px solid #cfcfcf;
font-size: 1.1rem;
font-weight: 300;
width: 100%;
outline: none;
`;
const Submit = styled.button`
background-color: transparent;
border: 0;
cursor: pointer;
appearance: none;
position: absolute;
height: 100%;
width: 50px;
right: 40px;
`;

View File

@@ -0,0 +1,38 @@
import React from 'react';
import styled from 'styled-components';
import { NewsletterForm } from 'ts/components/newsletter_form';
import { Heading, Paragraph } from 'ts/components/text';
import { colors } from 'ts/style/colors';
export interface INewsletterWidgetProps {
heading?: string;
description?: string;
url?: string;
}
export const NewsletterWidget: React.FC<INewsletterWidgetProps> = props => {
return (
<NewsletterSignupWrapper href={props.url}>
<Heading marginBottom="8px">{props.heading}</Heading>
<Paragraph marginBottom="25px">{props.description}</Paragraph>
<NewsletterForm color="#b1b1b1" />
</NewsletterSignupWrapper>
);
};
NewsletterWidget.defaultProps = {
heading: 'Sign up for the Newsletter',
description: 'Body font about the newseletter',
};
const NewsletterSignupWrapper = styled.a`
background-color: ${colors.backgroundLight};
padding: 40px 120px 50px;
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
margin-bottom: 1.875rem;
`;

View File

@@ -76,6 +76,7 @@ export const Footer: React.StatelessComponent = () => (
<FooterColumn width="35%">
<Logo />
<NewsletterForm />
<Text>Subscribe to our newsletter for updates in the 0x ecosystem</Text>
</FooterColumn>
<FooterColumn width="55%">
@@ -170,3 +171,11 @@ const Link = styled(SmartLink)`
opacity: 0.8;
}
`;
const Text = styled.p`
color: #656565;
font-size: 0.833333333rem;
font-weight: 300;
line-height: 1.2em;
margin-top: 15px;
`;

View File

@@ -1,13 +1,11 @@
import React, { useState } from 'react';
import styled, { withTheme } from 'styled-components';
import styled, { keyframes } from 'styled-components';
import { ThemeValuesInterface } from 'ts/components/siteWrap';
import { colors } from 'ts/style/colors';
import { errorReporter } from 'ts/utils/error_reporter';
import { utils } from 'ts/utils/utils';
interface IFormProps {
theme: ThemeValuesInterface;
color?: string;
}
interface IInputProps {
@@ -15,7 +13,7 @@ interface IInputProps {
name: string;
type: string;
label: string;
textColor: string;
color?: string;
required?: boolean;
}
@@ -23,21 +21,7 @@ interface IArrowProps {
isSubmitted: boolean;
}
const Input = React.forwardRef((props: IInputProps, ref: React.Ref<HTMLInputElement>) => {
const { name, label, type } = props;
const id = `input-${name}`;
return (
<InnerInputWrapper {...props}>
<label className="visuallyHidden" htmlFor={id}>
{label}
</label>
<StyledInput ref={ref} id={id} placeholder={label} type={type || 'text'} {...props} />
</InnerInputWrapper>
);
});
const Form: React.FC<IFormProps> = ({ theme }) => {
export const NewsletterForm: React.FC<IFormProps> = ({ color }) => {
const [isSubmitted, setIsSubmitted] = useState<boolean>(false);
const emailInput = React.createRef<HTMLInputElement>();
@@ -69,113 +53,100 @@ const Form: React.FC<IFormProps> = ({ theme }) => {
return (
<StyledForm onSubmit={handleSubmit}>
<InputWrapper>
{isSubmitted ? (
<SuccessText isSubmitted={isSubmitted}>🎉 Thank you for signing up!</SuccessText>
) : (
<Input
color={color}
isSubmitted={isSubmitted}
name="email"
type="email"
label="Email Address"
ref={emailInput}
required={true}
textColor={theme.textColor}
/>
)}
<SubmitButton>
<Arrow
isSubmitted={isSubmitted}
width="22"
height="17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M13.066 0l-1.068 1.147 6.232 6.557H0v1.592h18.23l-6.232 6.557L13.066 17l8.08-8.5-8.08-8.5z"
fill="#CBCBCB"
/>
</Arrow>
</SubmitButton>
<SuccessText isSubmitted={isSubmitted}>🎉 Thank you for signing up!</SuccessText>
</InputWrapper>
<Text>Subscribe to our newsletter for updates in the 0x ecosystem</Text>
<SubmitButton>
<Arrow
color={color}
isSubmitted={isSubmitted}
width="22"
height="17"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M13.066 0l-1.068 1.147 6.232 6.557H0v1.592h18.23l-6.232 6.557L13.066 17l8.08-8.5-8.08-8.5z" />
</Arrow>
</SubmitButton>
</StyledForm>
);
};
export const NewsletterForm = withTheme(Form);
const Input = React.forwardRef((props: IInputProps, ref: React.Ref<HTMLInputElement>) => {
const { name, label, type } = props;
const id = `input-${name}`;
return (
<>
<label className="visuallyHidden" htmlFor={id}>
{label}
</label>
<StyledInput ref={ref} id={id} placeholder={label} type={type || 'text'} {...props} />
</>
);
});
const INPUT_HEIGHT = '60px';
const StyledForm = styled.form`
appearance: none;
border: 0;
color: ${colors.white};
padding: 13px 0 14px;
margin-top: 27px;
position: relative;
margin-top: 24px;
`;
const StyledInput = styled.input<IInputProps>`
appearance: none;
background-color: transparent;
border: 0;
border-bottom: 1px solid #393939;
color: ${props => props.textColor || '#fff'};
font-size: 1.294117647rem;
padding: 15px 0;
border-bottom: 1px solid ${({ color }) => color || '#393939'};
color: ${({ theme }) => theme.textColor};
height: ${INPUT_HEIGHT};
font-size: 1.3rem;
outline: none;
width: 100%;
&::placeholder {
color: #b1b1b1; // #9D9D9D on light theme
color: #b1b1b1;
}
`;
const InputWrapper = styled.div`
position: relative;
`;
const InnerInputWrapper = styled.div<IArrowProps>`
opacity: ${props => props.isSubmitted && 0};
visibility: ${props => props.isSubmitted && 'hidden'};
transition: opacity 0.25s ease-in-out, visibility 0.25s ease-in-out;
transition-delay: 0.3s;
`;
const SubmitButton = styled.button`
width: 44px;
height: 44px;
height: ${INPUT_HEIGHT};
background-color: transparent;
border: 0;
position: absolute;
right: 0;
top: calc(50% - 22px);
top: 0;
overflow: hidden;
outline: 0;
`;
const Text = styled.p`
color: #656565;
font-size: 0.833333333rem;
font-weight: 300;
line-height: 1.2em;
margin-top: 15px;
// prettier-ignore
const fadeIn = keyframes`
from { opacity: 0; }
to { opacity: 1; }
`;
const SuccessText = styled.p<IArrowProps>`
color: #b1b1b1;
font-size: 1rem;
font-weight: 300;
line-height: 1.2em;
padding-top: 25px;
position: absolute;
left: 0;
top: 0;
text-align: left;
right: 50px;
opacity: ${props => (props.isSubmitted ? 1 : 0)};
visibility: ${props => (props.isSubmitted ? 'visible' : 'hidden')};
transition: opacity 0.25s ease-in-out, visibility 0.25s ease-in-out;
transition-delay: 0.55s;
line-height: ${INPUT_HEIGHT};
animation: ${fadeIn} 0.3s ease-in-out;
`;
const Arrow = styled.svg<IArrowProps>`
transform: ${props => props.isSubmitted && `translateX(44px)`};
fill: ${({ color }) => color};
transform: ${({ isSubmitted }) => isSubmitted && `translateX(44px)`};
transition: transform 0.25s ease-in-out;
`;

View File

@@ -6,7 +6,7 @@ import { FeatureLink } from 'ts/components/docs/feature_link';
import { HelpCallout } from 'ts/components/docs/help_callout';
import { HelpfulCta } from 'ts/components/docs/helpful_cta';
import { Hero } from 'ts/components/docs/hero';
import { NewsletterSignup } from 'ts/components/docs/newsletter_signup';
import { NewsletterWidget } from 'ts/components/docs/newsletter_widget';
import { Note } from 'ts/components/docs/note';
import { Notification } from 'ts/components/docs/notification';
import { Resource } from 'ts/components/docs/resource/resource';
@@ -195,7 +195,6 @@ export const DocsPageTemplate: React.FC = () => {
</Heading>
<StepLinks links={usefulLinks} />
<HelpCallout />
<NewsletterSignup />
<HelpfulCta />
<div>
<Heading asElement="h2" size="default">
@@ -237,6 +236,7 @@ export const DocsPageTemplate: React.FC = () => {
url="#"
/>
</div>
<NewsletterWidget />
</article>
</Columns>
</Section>