Skip to content

Commit

Permalink
Add data insights newsletter
Browse files Browse the repository at this point in the history
  • Loading branch information
rakyi committed Jul 23, 2024
1 parent 683aa16 commit c3db09d
Show file tree
Hide file tree
Showing 20 changed files with 391 additions and 32 deletions.
2 changes: 1 addition & 1 deletion packages/@ourworldindata/components/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type WithHrefProps = {
}

type WithOnClickProps = {
onClick: () => void
onClick?: () => void
href?: never
}

Expand Down
17 changes: 17 additions & 0 deletions packages/@ourworldindata/components/src/TextInput.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.text-input {
@include body-3-medium;
padding: 8px 16px;
color: $blue-90;
border: 1px solid $blue-20;
border-radius: 0;
height: 40px;

&:focus {
outline: none;
border: 1px solid $blue-40;
}

&::placeholder {
color: $blue-40;
}
}
19 changes: 19 additions & 0 deletions packages/@ourworldindata/components/src/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from "react"
import { forwardRef } from "react"
import cn from "classnames"

export type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
className?: string
}

export const TextInput = forwardRef<HTMLInputElement, InputProps>(
function Input({ className, ...props }: InputProps, ref) {
return (
<input
className={cn("text-input", className)}
ref={ref}
{...props}
/>
)
}
)
1 change: 1 addition & 0 deletions packages/@ourworldindata/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export { IndicatorProcessing } from "./IndicatorProcessing/IndicatorProcessing.j

export { Checkbox } from "./Checkbox.js"
export { IndicatorSources } from "./IndicatorSources/IndicatorSources.js"
export { TextInput } from "./TextInput.js"

export {
CodeSnippet,
Expand Down
12 changes: 12 additions & 0 deletions packages/@ourworldindata/components/src/styles/typography.scss
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,15 @@ body {
.label-2-medium {
@include label-2-medium;
}

@mixin note-1-medium {
font-family: $sans-serif-font-stack;
font-size: 0.75rem;
font-weight: 500;
letter-spacing: 0.01em;
line-height: 1.33;
}

.note-1-medium {
@include note-1-medium;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe(ColumnTypeNames.Quarter, () => {

it("should parse and format values correctly", () => {
const testValues = [
// Input string, parsed value, formatted output string
// TextInput string, parsed value, formatted output string
["2020-Q3", 8082, "Q3/2020"],
["2000-Q1", 8000, "Q1/2000"],
["02000-Q1", 8000, "Q1/2000"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ export class EntityPicker extends React.Component<{
switch (event.key) {
case "Enter":
if (event.keyCode === 229) {
// ignore the keydown event from an Input Method Editor(IME)
// ignore the keydown event from an TextInput Method Editor(IME)
// ref. https://www.w3.org/TR/uievents/#determine-keydown-keyup-keyCode
break
}
Expand Down
4 changes: 3 additions & 1 deletion site/DataInsightsIndexPageContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import React, { useState, useEffect } from "react"

Check warning on line 1 in site/DataInsightsIndexPageContent.tsx

View workflow job for this annotation

GitHub Actions / eslint

'useState' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 1 in site/DataInsightsIndexPageContent.tsx

View workflow job for this annotation

GitHub Actions / eslint

'useEffect' is defined but never used. Allowed unused vars must match /^_/u
import cx from "classnames"
import ReactDOM from "react-dom"
import {
Expand All @@ -16,6 +16,7 @@ import { DataInsightsIndexPageProps } from "./DataInsightsIndexPage.js"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js"
import { faArrowLeft, faArrowRight } from "@fortawesome/free-solid-svg-icons"
import { DebugProvider } from "./gdocs/DebugContext.js"
import DataInsightsNewsletterBanner from "./DataInsightsNewsletterBanner.js"

const Pagination = (props: { pageNumber: number; totalPageCount: number }) => {
const { pageNumber, totalPageCount } = props
Expand Down Expand Up @@ -141,6 +142,7 @@ export const DataInsightsIndexPageContent = (
totalPageCount={props.totalPageCount}
pageNumber={props.pageNumber}
/>
<DataInsightsNewsletterBanner />
</AttachmentsContext.Provider>
</DocumentContext.Provider>
)
Expand Down
18 changes: 18 additions & 0 deletions site/DataInsightsNewsletterBanner.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.data-insights-newsletter-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
transform: translateY(100%);
transition: transform 0.3s ease-out;
opacity: 0;
pointer-events: none;
background-color: $accent-pale-blue;
z-index: 1000;

&--visible {
transform: translateY(0);
opacity: 1;
pointer-events: auto;
}
}
24 changes: 24 additions & 0 deletions site/DataInsightsNewsletterBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from "react"
import { useState, useEffect } from "react"
import cx from "classnames"
import DataInsightsNewsletter from "./gdocs/components/DataInsightsNewsletter.js"

export default function DataInsightsNewsletterBanner() {
const [isVisible, setIsVisible] = useState(false)

useEffect(() => {
const timeoutId = setTimeout(() => {
setIsVisible(true)
}, 3000)
return () => clearTimeout(timeoutId)
}, [])

return (
<DataInsightsNewsletter
className={cx("data-insights-newsletter-banner", {
"data-insights-newsletter-banner--visible": isVisible,
})}
onClose={() => setIsVisible(false)}
/>
)
}
31 changes: 16 additions & 15 deletions site/NewsletterSubscription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from "react"
import { faTimes, faEnvelopeOpenText } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js"
import { SiteAnalytics } from "./SiteAnalytics.js"
import { TextInput } from "@ourworldindata/components"

const analytics = new SiteAnalytics()

Expand Down Expand Up @@ -64,14 +65,14 @@ export const NewsletterSubscriptionForm = ({
}: {
context?: NewsletterSubscriptionContext
}) => {
const IMMEDIATE = "1"
const DATA_INSIGHTS = "16"
const BIWEEKLY = "2"
const idImmediate = `mce-group[85302]-85302-0${
const idDataInsights = `mce-group[85302]-85302-0${
context ? "-" + context : ""
}`
const idBiweekly = `mce-group[85302]-85302-1${context ? "-" + context : ""}`

const [frequencies, setFrequencies] = useState([IMMEDIATE, BIWEEKLY])
const [frequencies, setFrequencies] = useState([DATA_INSIGHTS, BIWEEKLY])
const isSubmittable = frequencies.length !== 0

const updateFrequencies = (e: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -98,17 +99,17 @@ export const NewsletterSubscriptionForm = ({
<div className="owid-checkbox-block">
<input
type="checkbox"
value={IMMEDIATE}
name={`group[85302][${IMMEDIATE}]`}
id={idImmediate}
checked={frequencies.includes(IMMEDIATE)}
value={DATA_INSIGHTS}
name={`group[85302][${DATA_INSIGHTS}]`}
id={idDataInsights}
checked={frequencies.includes(DATA_INSIGHTS)}
onChange={updateFrequencies}
/>
<label htmlFor={idImmediate}>
<div className="label-title">Immediate updates</div>
<label htmlFor={idDataInsights}>
<div className="label-title">Daily Data Insights</div>
<div className="label-text">
Receive an email from us whenever we publish new work
(maximum 1 per day).
Receive our bite-sized insights on how the world is
changing, every weekday.
</div>
</label>
</div>
Expand All @@ -133,15 +134,15 @@ export const NewsletterSubscriptionForm = ({
<div className="alert">Please select at least one option.</div>
)}
<div className="NewsletterSubscription__email-submit">
<input
<TextInput
placeholder="Your email address"
type="email"
className="NewsletterSubscription__email"
name="EMAIL"
required={true}
/>
<button
aria-label="Subscribe to newsletter"
type="submit"
disabled={!isSubmittable}
onClick={() =>
analytics.logSiteClick(
Expand All @@ -154,8 +155,8 @@ export const NewsletterSubscriptionForm = ({
Subscribe
</button>
</div>
{/* This hidden field should not be the last element in the form as long as we use the row-gap mixin
to space elements vertically. When placed as the last element of the form, this hidden element becomes
{/* This hidden field should not be the last element in the form as long as we use the row-gap mixin
to space elements vertically. When placed as the last element of the form, this hidden element becomes
the target of the :last-child selector of the row-gap mixin, when it should be applied to the last visible
element instead */}
<input
Expand Down
2 changes: 1 addition & 1 deletion site/SiteNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const SiteNavigation = ({
}, 10)

setTimeout(() => {
const input = document.querySelector<HTMLElement>(".aa-Input")
const input = document.querySelector<HTMLElement>(".aa-TextInput")
if (input) {
input.focus()
input.setAttribute("required", "true")
Expand Down
8 changes: 0 additions & 8 deletions site/css/newsletter-subscription.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,8 @@
}

.NewsletterSubscription__email {
border: 1px solid $blue-20;
border-radius: 0;
height: inherit;
padding: 0 16px;
flex: 1;
width: 100%;
&::placeholder {
@include body-3-medium;
color: $blue-40;
}
}

.NewsletterSubscription__submit {
Expand Down
Loading

0 comments on commit c3db09d

Please sign in to comment.