diff --git a/public/og-images/best-of-2022-share-image.jpg b/public/og-images/best-of-2022-share-image.jpg new file mode 100644 index 0000000..7d8db1c Binary files /dev/null and b/public/og-images/best-of-2022-share-image.jpg differ diff --git a/src/App.tsx b/src/App.tsx index bfa495c..1722224 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -59,6 +59,7 @@ const JordanTool = lazy(() => import('./pages/jordanTool')); const JordanOverview = lazy(() => import('./pages/jordanTool/overviewPage')); const BestOf2020 = lazy(() => import('./pages/stories/bestOf/2020')); const BestOf2021 = lazy(() => import('./pages/stories/bestOf/2021')); +const BestOf2022 = lazy(() => import('./pages/stories/bestOf/2022')); const NamibiaTool = lazy(() => import('./pages/namibiaTool')); const CustomProductSpaceTool = lazy(() => import('./pages/iframeTools/CreateYourProductSpace')); const CustomIndustrySpaceTool = lazy(() => import('./pages/iframeTools/CreateYourIndustrySpace')); @@ -137,6 +138,9 @@ function App() { } /> + } + /> } /> diff --git a/src/assets/GL_HKS_logo_transparentback.png b/src/assets/GL_HKS_logo_transparentback.png new file mode 100644 index 0000000..7d01f59 Binary files /dev/null and b/src/assets/GL_HKS_logo_transparentback.png differ diff --git a/src/assets/GL_HKS_logo_whiteback.png b/src/assets/GL_HKS_logo_whiteback.png new file mode 100644 index 0000000..42efb51 Binary files /dev/null and b/src/assets/GL_HKS_logo_whiteback.png differ diff --git a/src/assets/GL_logo_white.png b/src/assets/GL_logo_white.png new file mode 100644 index 0000000..0c71eb4 Binary files /dev/null and b/src/assets/GL_logo_white.png differ diff --git a/src/assets/applepodcast.svg b/src/assets/applepodcast.svg new file mode 100644 index 0000000..489bbfd --- /dev/null +++ b/src/assets/applepodcast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/email.svg b/src/assets/email.svg new file mode 100644 index 0000000..6778486 --- /dev/null +++ b/src/assets/email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/facebook.svg b/src/assets/facebook.svg new file mode 100644 index 0000000..18bc1e5 --- /dev/null +++ b/src/assets/facebook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/githubicon.svg b/src/assets/githubicon.svg new file mode 100644 index 0000000..5dd1cbb --- /dev/null +++ b/src/assets/githubicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/growth-lab-new-logo-2022.png b/src/assets/growth-lab-new-logo-2022.png new file mode 100644 index 0000000..9780623 Binary files /dev/null and b/src/assets/growth-lab-new-logo-2022.png differ diff --git a/src/assets/growth-lab-white.png b/src/assets/growth-lab-white.png new file mode 100644 index 0000000..30b8a87 Binary files /dev/null and b/src/assets/growth-lab-white.png differ diff --git a/src/assets/info-circle.svg b/src/assets/info-circle.svg new file mode 100644 index 0000000..f4dc5aa --- /dev/null +++ b/src/assets/info-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/link.svg b/src/assets/link.svg new file mode 100644 index 0000000..bb28450 --- /dev/null +++ b/src/assets/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/linkedin.svg b/src/assets/linkedin.svg new file mode 100644 index 0000000..3208945 --- /dev/null +++ b/src/assets/linkedin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/share.svg b/src/assets/share.svg new file mode 100644 index 0000000..ad8ac5b --- /dev/null +++ b/src/assets/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/twitter.svg b/src/assets/twitter.svg new file mode 100644 index 0000000..bb73ca8 --- /dev/null +++ b/src/assets/twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/youtube.svg b/src/assets/youtube.svg new file mode 100644 index 0000000..58eb897 --- /dev/null +++ b/src/assets/youtube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/navigation/DefaultHubHeader.tsx b/src/components/navigation/DefaultHubHeader.tsx index 4230104..a0983a4 100644 --- a/src/components/navigation/DefaultHubHeader.tsx +++ b/src/components/navigation/DefaultHubHeader.tsx @@ -4,6 +4,7 @@ import {Link} from 'react-router-dom'; import {Routes} from '../../routing/routes'; import CloudIconSvgPath from '../../assets/cloud-icon.svg'; import {activeLinkColor} from '../../pages/landingPage/Utils'; +import GrowthLabWhiteLogo from '../text/headers/GL_logo_white.png'; const Root = styled.div` left: 0; @@ -16,6 +17,7 @@ const Root = styled.div` align-items: center; text-transform: uppercase; box-sizing: border-box; + z-index: 100; `; const AppLink = styled(Link)` @@ -30,7 +32,7 @@ const Icon = styled.img` transform: translate(0, 1px); margin-right: 0.4rem; `; -const HarvardLine = styled.div``; +// const HarvardLine = styled.div``; const LogoLine = styled.div` display: inline-flex; align-items: center; @@ -57,6 +59,15 @@ const GrowthLabLink = styled.a` font-weight: 600; `; +const GrowthLabLogo = styled.img` + max-width: 100%; + height: 30px; + + @media (max-width: 920px) { + max-width: 250px; + } +`; + interface Props { staticPosition?: boolean; growthLabLinkColor?: string; @@ -76,7 +87,7 @@ export default (props: Props) => { to={Routes.Landing} style={{color: appLinkColor ? appLinkColor : '#fff'}} > - Harvard Growth Lab + {/* Harvard Growth Lab */} Viz Hub { target='_blank' style={{color: growthLabLinkColor ? growthLabLinkColor : '#000'}} > - Harvard Growth Lab + {/* Harvard Growth Lab */} + ); diff --git a/src/components/share/ShareModal.tsx b/src/components/share/ShareModal.tsx new file mode 100644 index 0000000..5111233 --- /dev/null +++ b/src/components/share/ShareModal.tsx @@ -0,0 +1,206 @@ +import React, {useState} from 'react'; +import Modal from './StandardModal'; +import styled, {keyframes} from 'styled-components/macro'; +import { + baseColor, + secondaryFont, + primaryFont, +} from '../../styling/styleUtils'; +// import useFluent from '../../../../hooks/useFluent'; +import raw from 'raw.macro'; +import getShareFunctions from './shareFn'; + +const iconGray = '#2D363F'; + +const linkSvg = raw('../../assets/link.svg'); +const twitterSvg = raw('../../assets/twitter.svg'); +const linkedinSvg = raw('../../assets/linkedin.svg'); +const facebookSvg = raw('../../assets/facebook.svg'); +const emailSvg = raw('../../assets/email.svg'); + +const growIn = keyframes` + 0% { + transform: scale(0.4); + } + + 100% { + transform: scale(1); + } +`; + +const Root = styled.div` + background-color: #fff; + position: relative; + animation: ${growIn} 0.1s normal forwards ease-in-out; + animation-iteration-count: 1; + color: ${baseColor}; + height: 100%; + padding: 2rem; + + @media screen and (max-height: 800px) { + overflow: visible; + } +`; + +const CloseButton = styled.button` + background-color: transparent; + border-none; + padding: 0.5rem; + text-transform: uppercase; + font-size: 1.25rem; + font-family: ${secondaryFont}; + position: absolute; + right: 0; + top: 0; +`; + +const SectionTitle = styled.div` + font-size: 1.25rem; + text-transform: uppercase; + margin-bottom: 0.75rem; + font-family: ${primaryFont}; +`; + +const SvgBase = styled.div` + svg { + width: 100%; + height: 100%; + + path { + fill: ${iconGray}; + } + } +`; + +const CopyUrlBar = styled.div` + min-height: 1rem; + max-width: 450px; + white-space: nowrap; + display: grid; + grid-template-columns: 1.45rem 1fr auto; + background-color: lightgray; + margin-bottom: 2rem; + cursor: pointer; +`; + +const CopyIcon = styled(SvgBase)` + padding-left: 0.45rem; +`; + +const UrlText = styled.div` + overflow: hidden; + padding: 0.45rem 0.55rem; +`; + +const CopyButton = styled.button` + font-family: ${primaryFont}; + text-transform: uppercase; + padding: 0.45rem 0.75rem; + background-color: ${iconGray}; + color: #fff; + font-size: 1.05rem; + letter-spacing: 0.5px; +`; + +const SocialMediaContainer = styled.div` + width: 100%; + display: flex; + align-items: center; +`; + +const SocialMediaButton = styled.button` + width: 2.875rem; + height: 2.875rem; + display: flex; + align-items: center; + margin-right: 1.5rem; + background-color: transparent; +`; + +interface Props { + onClose: () => void; + useTitle: string; +} + +export default (props: Props) => { + const { + onClose, + useTitle + } = props; + // const getString = useFluent(); + const [copied, setCopied] = useState(false); + const onCopy = () => { + navigator.clipboard.writeText(window.location.href); + setCopied(true); + setTimeout(() => setCopied(false), 5000); + }; + const copyText = copied ? 'Copied' : 'Copy'; + + const {shareFacebook, shareTwitter, shareLinkedIn, shareEmail} = getShareFunctions(window.location.href); + + let titleForSocial = 'Check out the Growth Lab Viz Hub'; + if(useTitle) { + titleForSocial = `Check out '${useTitle},' in Visual Insights from the Growth Lab's 2022 Research`; + } + return ( + + + + Direct Link + + + + + {window.location.href} + + + {copyText} + + + + Social Media Sharing + + + shareTwitter(titleForSocial)} + > + + + shareLinkedIn(titleForSocial, '')} + > + + + shareFacebook()} + > + + + shareEmail( + titleForSocial, titleForSocial, window.location.href, + )} + > + + + + + + + ); +}; diff --git a/src/components/share/StandardModal.tsx b/src/components/share/StandardModal.tsx new file mode 100644 index 0000000..c0f8ac9 --- /dev/null +++ b/src/components/share/StandardModal.tsx @@ -0,0 +1,135 @@ +import React, {useEffect, useRef, useState} from 'react'; +import { createPortal } from 'react-dom'; +import styled from 'styled-components/macro'; + +export const overlayPortalContainerId = 'overlayPortalContainerId'; + +const overlayPortalZIndex = 3000; + +export const OverlayPortal = () => ( +
+); + +export const mobileWidth = 600; // in px + +const Root = styled.div` + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100vw; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; +`; + +const Overlay = styled.div` + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.3); +`; + +interface Dimensions { + width: string; + height: string; +} + +const Container = styled.div<{dimensions: Dimensions}>` + position: relative; + max-height: 90%; + max-width: ${({dimensions: {width}}) => width}; + height: ${({dimensions: {height}}) => height}; + + @media screen and (max-width: ${mobileWidth}px), screen and (max-height: 800px) { + max-height: calc(100vh - 4rem); + max-width: calc(100vw - 4rem); + margin: auto; + overflow: auto; + } +`; + +const Content = styled.div` + overflow: auto; + + ::-webkit-scrollbar { + -webkit-appearance: none; + width: 7px; + } + ::-webkit-scrollbar-thumb { + border-radius: 4px; + background-color: rgba(0, 0, 0, .3); + } + ::-webkit-scrollbar-track { + background-color: rgba(0, 0, 0, .1); + } + + @media screen and (max-width: ${mobileWidth}px), screen and (max-height: 800px) { + overflow: visible; + } +`; + +export interface Props { + children: React.ReactNode; + onClose: (() => void) | undefined; + width: string; + height: string; +} + +const Modal = (props: Props) => { + const { + children, onClose, width, height, + } = props; + + const overlayPortalContainerNodeRef = useRef(null); + + const [isModalRendered, setIsModalRendered] = useState(false); + + useEffect(() => { + const node = document.querySelector(`#${overlayPortalContainerId}`); + if (node !== null) { + overlayPortalContainerNodeRef.current = node; + overlayPortalContainerNodeRef.current.focus(); + setIsModalRendered(true); + } + }, []); + + useEffect(() => { + const closeOnEsc = (e: KeyboardEvent) => e.key === 'Escape' && onClose ? onClose() : null; + document.addEventListener('keydown', closeOnEsc); + return () => document.removeEventListener('keydown', closeOnEsc); + }, [onClose]); + + let modal: React.ReactElement | null; + if (isModalRendered === true && overlayPortalContainerNodeRef.current !== null) { + modal = createPortal(( + + + + + {children} + + + + ), overlayPortalContainerNodeRef.current); + } else { + modal = null; + } + + return modal; +}; + +export default Modal; diff --git a/src/components/share/Tooltip.tsx b/src/components/share/Tooltip.tsx new file mode 100644 index 0000000..ebb4ad6 --- /dev/null +++ b/src/components/share/Tooltip.tsx @@ -0,0 +1,290 @@ +import React, { useLayoutEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom'; +import styled from 'styled-components'; +import raw from 'raw.macro'; + +const infoCircleSVG = raw('../../assets/info-circle.svg'); + +export enum TooltipPosition { + Automatic = 'automatic', + Bottom = 'bottom', +} + +export enum TooltipTheme { + Light = 'light', + Dark = 'dark', +} + +const lightBorderColor = '#dcdcdc'; // really light gray color for subtle borders between elements +const backgroundDark = '#2e353f'; // dark blue gray +const overlayPortalContainerId = 'overlayPortalContainerId'; + + +const farEndOfScreenToggleClass = 'tooltip-at-right-end-of-screen'; +export const arrowContainerClassName = 'tooltip-arrow-container-class'; +const flipArrowClassName = 'tooltip-arrow-flip-side-class'; + +//#region Styling +const Root = styled.span` + cursor: help; + width: 0.7rem; + height: 0.7rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 10000px; + margin: 0 0.4rem; +`; + +const MoreInformationI = styled.span` + display: inline-block; + width: 0.7rem; + height: 0.7rem; + line-height: 0; + + svg { + width: 100%; + height: 100%; + + circle { + fill: ${backgroundDark}; + } + + path { + fill: #fff; + } + } +`; + +const TooltipBase = styled.div<{$theme: TooltipTheme | undefined, $overrideStyles: boolean | undefined}>` + position: fixed; + z-index: 3000; + max-width: 16rem; + font-size: 0.7rem; + line-height: 1.4; + text-transform: none; + ${({$overrideStyles}) => $overrideStyles ? 'padding-bottom: 0.5rem;' : 'padding: 0.5rem;'} + opacity: 0; + transition: opacity 0.15s ease; + color: ${backgroundDark}; + background-color: ${({$theme}) => $theme === TooltipTheme.Dark ? backgroundDark : '#fff'}; + color: ${({$theme}) => $theme === TooltipTheme.Dark ? '#fff' : backgroundDark}; + border: 1px solid ${({$theme}) => $theme === TooltipTheme.Dark ? backgroundDark : lightBorderColor}; + border-radius: 4px; + box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.15); + pointer-events: none; + + &.${farEndOfScreenToggleClass} .${arrowContainerClassName} { + justify-content: flex-end; + padding-right: 0.7rem; + box-sizing: border-box; + } + + &.${flipArrowClassName} .${arrowContainerClassName} { + transform: translate(0, -100%); + top: 0; + + div { + &:before { + top: -1px; + transform: rotate(180deg); + } + + &:after { + transform: rotate(180deg); + } + } + } +`; + +const ArrowContainer = styled.div<{$position: TooltipPosition | undefined}>` + width: 100%; + height: 0.5rem; + display: flex; + justify-content: center; + position: absolute; + transform: ${({$position}) => $position === TooltipPosition.Bottom + ? 'translate(0, -100%)' + : 'translate(0, 100%)'}; + ${({$position}) => $position === TooltipPosition.Bottom + ? 'top: 0;' + : ''} +`; + +const Arrow = styled.div<{$theme: TooltipTheme | undefined, $position: TooltipPosition | undefined}>` + width: 0.5rem; + height: 0.5rem; + position: relative; + z-index: -1; + display: flex; + justify-content: center; + transform: translate(-150%, 0); + + &:before { + content: ''; + position: absolute; + top: ${({$position}) => $position === TooltipPosition.Bottom + ? '-1px' : '0' + }; + left: 0; + border-left: 9px solid transparent; + border-right: 9px solid transparent; + border-top: 9px solid ${({$theme}) => $theme === TooltipTheme.Dark ? backgroundDark : lightBorderColor}; + ${({$position}) => $position === TooltipPosition.Bottom + ? 'transform: rotate(180deg);' + : ''} + } + + &:after { + content: ''; + position: absolute; + top: 0; + left: 1px; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-top: 8px solid ${({$theme}) => $theme === TooltipTheme.Dark ? backgroundDark : '#fff'}; + ${({$position}) => $position === TooltipPosition.Bottom + ? 'transform: rotate(180deg);' + : ''} + } +`; + +const GenericSpan = styled.span` + cursor: help; +`; +//#endregion +let timeout: number; + +interface Props { + explanation: React.ReactNode | null; + children?: React.ReactNode; + cursor?: string; + theme?: TooltipTheme; + tooltipPosition?: TooltipPosition; + overrideStyles?: boolean; + delay?: number; +} + +const Tooltip = (props: Props) => { + const { + explanation, children, cursor, theme, tooltipPosition, overrideStyles, delay, + } = props; + const rootEl = useRef(null); + const tooltipEl = useRef(null); + const overlayPortalContainerNodeRef = useRef(null); + + const [isTooltipShown, setIsTooltipShown] = useState(false); + const [coords, setCoords] = useState<{top: number, left: number}>({top: 0, left: 0}); + + useLayoutEffect(() => { + const node = document.querySelector(`#${overlayPortalContainerId}`); + overlayPortalContainerNodeRef.current = node; + const tooltipElm = tooltipEl.current; + const rootElm = rootEl.current; + if (tooltipElm !== null && rootElm !== null) { + const {top, left} = coords; + const tooltipSpacing = 15; + const tooltipHeight = tooltipElm.offsetHeight; + const tooltipWidth = tooltipElm.offsetWidth; + let tooltipTopValue = top - tooltipSpacing - tooltipHeight; + let tooltipLeftValue = left - (tooltipWidth / 2); + if (tooltipTopValue < 0 || tooltipPosition === TooltipPosition.Bottom) { + // tooltip will be above the window + tooltipTopValue = top + (tooltipSpacing * 2); + tooltipElm.classList.add(flipArrowClassName); + } else { + tooltipElm.classList.remove(flipArrowClassName); + } + if (tooltipLeftValue < tooltipSpacing) { + tooltipLeftValue = tooltipSpacing; + } + if ((tooltipLeftValue + (tooltipWidth + tooltipSpacing)) > window.innerWidth) { + // tooltip will exceed the windows width + tooltipLeftValue = window.innerWidth - tooltipWidth - tooltipSpacing; + } + if (window.innerWidth - left < tooltipSpacing * 3) { + // tooltip is at the far end of the screen + tooltipElm.classList.add(farEndOfScreenToggleClass); + } else { + tooltipElm.classList.remove(farEndOfScreenToggleClass); + } + tooltipElm.style.cssText = ` + left: ${tooltipLeftValue}px; + top: ${tooltipTopValue}px; + opacity: 1; + `; + } + }, [isTooltipShown, coords, tooltipPosition]); + const overlayPortalContainerNode = overlayPortalContainerNodeRef.current; + + const arrow = overrideStyles ? null : ( + + + + ); + + let tooltip: React.ReactPortal | null; + if (isTooltipShown !== false && overlayPortalContainerNode !== null && explanation) { + tooltip = ReactDOM.createPortal(( + + {explanation} + {arrow} + + ), overlayPortalContainerNode); + } else { + tooltip = null; + } + + const onMouseEnter = (e: React.MouseEvent) => { + setCoords({top: e.clientY, left: e.clientX}); + if (delay) { + timeout = setTimeout(() => setIsTooltipShown(true), delay) as any; + } else { + setIsTooltipShown(true); + } + }; + const onMouseLeave = (e: React.MouseEvent) => { + setCoords({top: e.clientY, left: e.clientX}); + clearTimeout(timeout); + setIsTooltipShown(false); + }; + const onMouseMove = (e: React.MouseEvent) => { + setCoords({top: e.clientY, left: e.clientX}); + }; + + if (children !== undefined) { + return ( + + {children} + {tooltip} + + ); + } else { + return ( + + + {tooltip} + + ); + } +}; + +export default Tooltip; diff --git a/src/components/share/Utils.tsx b/src/components/share/Utils.tsx new file mode 100644 index 0000000..8cc4cba --- /dev/null +++ b/src/components/share/Utils.tsx @@ -0,0 +1,113 @@ +import { + secondaryFont, + baseColor, +} from '../../styling/styleUtils'; +import styled from 'styled-components/macro'; + +export const breakPointValues = { + width: { + medium: 1100, + mediumSmall: 900, + small: 800, + }, + height: { + medium: 768, + mediumSmall: 550, + small: 500, + }, +}; + + +const smallBreakpoint = 550; // in px +export const mediumSmallBreakpoint = 1050; // in px +export const columnsToRowsBreakpoint = breakPointValues.width.small; // in px + + +export const UtilityBarButtonBase = styled.button` +border: none; +margin: 0 0.25rem; +padding: 0 0.35rem; +color: ${baseColor}; +background-color: transparent; +font-size: 0.875rem; +font-family: ${secondaryFont}; +text-transform: uppercase; +display: flex; +align-items: center; +outline: 0 solid rgba(255, 255, 255, 0); +transition: outline 0.1s ease; +flex-shrink: 1; + +&:hover, &:focus { + background-color: #fff; + outline: 0.25rem solid #fff; + color: ${baseColor}; +} + +@media (max-width: ${mediumSmallBreakpoint}px) { + flex-direction: column; +} + +@media (max-width: ${columnsToRowsBreakpoint}px) { + flex-direction: row; +} + +@media (max-width: ${smallBreakpoint}px) { + flex-direction: column; +} +`; + +export const SvgBase = styled.span` +display: inline-block; +width: 1rem; +height: 1rem; +margin-right: 0.3rem; + +svg { + width: 100%; + height: 100%; + + path { + fill: ${baseColor}; + } +} + +@media (max-width: ${mediumSmallBreakpoint}px) { + margin-right: 0; + margin-bottom: 0.2rem; +} + +@media (max-width: ${columnsToRowsBreakpoint}px) { + margin-right: 0.3rem; + margin-bottom: 0; +} + +@media (max-width: ${smallBreakpoint}px) { + margin-right: 0; + margin-bottom: 0.2rem; +} +`; + +export const Text = styled.span` +width: min-content; + +@media (max-width: 1100px) { + max-width: 55px; +} + +@media (max-width: ${mediumSmallBreakpoint}px) and (min-width: ${columnsToRowsBreakpoint + 1}px) { + display: none; +} + +@media (max-width: ${columnsToRowsBreakpoint }px) { + text-align: center; +} +`; + + +export const TooltipContent = styled.div` + font-family: ${secondaryFont}; + letter-spacing: -0.3px; + text-transform: uppercase; + font-size: 0.6rem; +`; diff --git a/src/components/share/index.tsx b/src/components/share/index.tsx new file mode 100644 index 0000000..659272b --- /dev/null +++ b/src/components/share/index.tsx @@ -0,0 +1,83 @@ +import React, {useState, useEffect, createContext} from 'react'; +import Tooltip, {TooltipPosition} from './Tooltip'; +import raw from 'raw.macro'; +import { + UtilityBarButtonBase, + columnsToRowsBreakpoint, + mediumSmallBreakpoint, + Text, + TooltipContent, + SvgBase, +} from './Utils'; +import ShareModal from './ShareModal'; +import debounce from 'lodash/debounce'; +// import { useTimeout } from 'react-use'; + + +const shareIconSvg = raw('../../assets/share.svg'); + +interface IAppContext { + windowDimensions: {width: number, height: number}; +} + +const initialWindowDimension = {width: window.innerWidth, height: window.innerHeight}; +createContext({ + windowDimensions: initialWindowDimension, +}); + +const useWindowWidth = () => { + const [windowDimensions, setWindowDimensions] = useState(initialWindowDimension); + + useEffect(() => { + const updateWindowDimensions = debounce(() => { + setWindowDimensions({width: window.innerWidth, height: window.innerHeight}); + }, 500); + window.addEventListener('resize', updateWindowDimensions); + return () => { + window.removeEventListener('resize', updateWindowDimensions); + }; + }, []); + + return windowDimensions; + }; + +interface Props { + useTitle: string; +} + +const Share = (props: Props) => { + const windowDimensions = useWindowWidth(); + const [modalOpen, setModalOpen] = useState(false); + const openModal = () => setModalOpen(true); + const closeModal = () => setModalOpen(false); + const {useTitle} = props; + + const modal = modalOpen ? ( + + ) : null; + return ( + <> + columnsToRowsBreakpoint + ? SHARE + : null + } + cursor='pointer' + tooltipPosition={TooltipPosition.Bottom} + > + + + + SHARE + + + + {modal} + + ); +}; + +export default Share; diff --git a/src/components/share/shareFn.ts b/src/components/share/shareFn.ts new file mode 100644 index 0000000..48d1427 --- /dev/null +++ b/src/components/share/shareFn.ts @@ -0,0 +1,51 @@ +const getShareWindowParams = + (width: number, height: number) => + `menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=${height},width=${width}`; + +const getShareFunctions = (url: string) => { + return { + shareFacebook: () => { + const baseURL = 'https://www.facebook.com/sharer.php'; + const shareURL = `${baseURL}?u=${encodeURIComponent(url)}`; + window.open(shareURL, '', getShareWindowParams(360, 600)); + }, + + shareTwitter: (text: string) => { + const baseURL = 'https://twitter.com/intent/tweet'; + const shareURL = +`${baseURL}? +url=${encodeURIComponent(url)}& +text=${encodeURIComponent(text)}& +via=HarvardGrwthLab`; + window.open(shareURL, '', getShareWindowParams(420, 550)); + }, + + shareLinkedIn: (title: string, summary: string) => { + // Reference: + // https://developer.linkedin.com/docs/share-on-linkedin (under "customized URL") + const baseURL = 'https://www.linkedin.com/shareArticle'; + // const source = 'https://atlas.cid.harvard.edu/'; + const source = encodeURIComponent(url); + const shareURL = +`${baseURL} +?mini=true& +url=${encodeURIComponent(url)}& +title=${encodeURIComponent(title)}& +summary=${encodeURIComponent(summary)}& +source=${encodeURIComponent(source)}`; + window.open(shareURL, '', getShareWindowParams(570, 520)); + }, + + shareEmail: (subjectCopy: string, bodyBeforeLineBreakCopy: string, bodyAfterLineBreakCopy: string) => { + const subject = encodeURIComponent(subjectCopy); + const bodyBeforeLineBreak = encodeURIComponent(bodyBeforeLineBreakCopy); + const bodyAfterLineBreak = encodeURIComponent(bodyAfterLineBreakCopy); + + const href = `mailto:?subject=${subject}&body=${bodyBeforeLineBreak}%0D%0A%0D%0A${bodyAfterLineBreak}`; + + window.location.href = href; + }, + }; +}; + +export default getShareFunctions; diff --git a/src/components/text/StandardFooter.tsx b/src/components/text/StandardFooter.tsx index 105d7b3..87ce41d 100644 --- a/src/components/text/StandardFooter.tsx +++ b/src/components/text/StandardFooter.tsx @@ -7,7 +7,7 @@ import { primaryFont, } from '../../styling/styleUtils'; import styled from 'styled-components/macro'; -import GrowthLabLogoPNG from './headers/growth-lab.png'; +import GrowthLabLogoPNG from './headers/GL_HKS_logo_transparentback.png'; import FacebookIconSVG from './assets/facebook.svg'; import TwitterIconSVG from './assets/twitter.svg'; import LinkedinIconSVG from './assets/linkedin.svg'; diff --git a/src/components/text/headers/GL_HKS_logo_transparentback.png b/src/components/text/headers/GL_HKS_logo_transparentback.png new file mode 100644 index 0000000..7d01f59 Binary files /dev/null and b/src/components/text/headers/GL_HKS_logo_transparentback.png differ diff --git a/src/components/text/headers/GL_logo_white.png b/src/components/text/headers/GL_logo_white.png new file mode 100644 index 0000000..0c71eb4 Binary files /dev/null and b/src/components/text/headers/GL_logo_white.png differ diff --git a/src/components/text/headers/growth-lab-new-logo-2022.png b/src/components/text/headers/growth-lab-new-logo-2022.png new file mode 100644 index 0000000..9780623 Binary files /dev/null and b/src/components/text/headers/growth-lab-new-logo-2022.png differ diff --git a/src/metadata.js b/src/metadata.js index 2250438..21d247e 100644 --- a/src/metadata.js +++ b/src/metadata.js @@ -8,6 +8,7 @@ const Routes = { JordanOverview: '/jordan-project-overview', BestOf2020: '/best-of-2020', BestOf2021: '/best-of-2021', + BestOf2022: '/best-of-2022', NamibiaTool: '/namibia-tool', CustomProductSpace: '/custom-product-space', CustomIndustrySpace: '/custom-industry-space', @@ -82,6 +83,13 @@ const metadata = [ og_image: 'best-of-2021-share-image.jpg', favicon: defaultFavicon, }, + { + url: Routes.BestOf2022, + title: 'Visual Insights from the Growth Lab\'s 2022 Research | ' + defaultTitle, + description: "2022's most notable visual insights from faculty, fellows, researchers and staff at Harvard’s Growth Lab.", + og_image: 'best-of-2022-share-image.jpg', + favicon: defaultFavicon, + }, { url: Routes.NamibiaTool, title: 'Namibia’s Industry Targeting Dashboard | ' + defaultTitle, diff --git a/src/pages/landingPage/Utils.ts b/src/pages/landingPage/Utils.ts index d4f26f9..d5861e5 100644 --- a/src/pages/landingPage/Utils.ts +++ b/src/pages/landingPage/Utils.ts @@ -42,6 +42,8 @@ export const getCategoryString = (value: ProjectCategories | null) => { return 'Presentations'; } else if (value === ProjectCategories.SOFTWARE_PACKAGES) { return 'Software Packages'; + } else if (value === ProjectCategories.ANNUAL_BEST_OF) { + return 'Annual Best-Of' } else { return ''; } diff --git a/src/pages/landingPage/graphql/graphQLTypes.ts b/src/pages/landingPage/graphql/graphQLTypes.ts index 4319fe2..2ee8463 100644 --- a/src/pages/landingPage/graphql/graphQLTypes.ts +++ b/src/pages/landingPage/graphql/graphQLTypes.ts @@ -5,6 +5,7 @@ export enum ProjectCategories { PROTOTYPES_EXPERIMENTS = 'PROTOTYPES_EXPERIMENTS', PRESENTATIONS = 'PRESENTATIONS', SOFTWARE_PACKAGES = 'SOFTWARE_PACKAGES', + ANNUAL_BEST_OF = 'ANNUAL_BEST_OF' } export enum CardSizes { diff --git a/src/pages/landingPage/growth-lab-new-logo-2022.png b/src/pages/landingPage/growth-lab-new-logo-2022.png new file mode 100644 index 0000000..9780623 Binary files /dev/null and b/src/pages/landingPage/growth-lab-new-logo-2022.png differ diff --git a/src/pages/landingPage/hubViews/ListView.tsx b/src/pages/landingPage/hubViews/ListView.tsx index 1143a28..0ac12e5 100644 --- a/src/pages/landingPage/hubViews/ListView.tsx +++ b/src/pages/landingPage/hubViews/ListView.tsx @@ -56,7 +56,8 @@ interface Props { } const ListView = ({projects}: Props) => { - const atlasProjects: React.ReactElement[] = []; + const atlasProjects: React.ReactElement[] = []; + const annualBestOf: React.ReactElement[] = []; const countryDashboards: React.ReactElement[] = []; const visualStories: React.ReactElement[] = []; const softwarePackages: React.ReactElement[] = []; @@ -80,6 +81,8 @@ const ListView = ({projects}: Props) => { presentations.push(projectElm); } else if (project.projectCategory === ProjectCategories.PROTOTYPES_EXPERIMENTS) { prototypes.push(projectElm); + } else if (project.projectCategory === ProjectCategories.ANNUAL_BEST_OF) { + annualBestOf.push(projectElm); } else { undefinedProjects.push(projectElm); } @@ -91,6 +94,7 @@ const ListView = ({projects}: Props) => { Status Link {atlasProjects} + {annualBestOf} {countryDashboards} {visualStories} {softwarePackages} diff --git a/src/pages/landingPage/images/high-res/best-of-2022-card-background.jpg b/src/pages/landingPage/images/high-res/best-of-2022-card-background.jpg new file mode 100644 index 0000000..a345d52 Binary files /dev/null and b/src/pages/landingPage/images/high-res/best-of-2022-card-background.jpg differ diff --git a/src/pages/landingPage/images/low-res/best-of-2022-card-background-lo.jpg b/src/pages/landingPage/images/low-res/best-of-2022-card-background-lo.jpg new file mode 100644 index 0000000..17718f7 Binary files /dev/null and b/src/pages/landingPage/images/low-res/best-of-2022-card-background-lo.jpg differ diff --git a/src/pages/landingPage/index.tsx b/src/pages/landingPage/index.tsx index d0dc2b7..4850dce 100644 --- a/src/pages/landingPage/index.tsx +++ b/src/pages/landingPage/index.tsx @@ -127,6 +127,7 @@ const LandingPage = () => { if (loading) { contentView = ; } else if (error) { + console.log("error", error); contentView = ( { ); } else if (data !== undefined) { const {hubProjectsList, hubKeywordsList} = data; + console.log(hubKeywordsList); + if (activeView === View.grid) { contentView = ( diff --git a/src/pages/stories/bestOf/2022/2022-12-14_data2022.csv b/src/pages/stories/bestOf/2022/2022-12-14_data2022.csv new file mode 100644 index 0000000..a992a2e --- /dev/null +++ b/src/pages/stories/bestOf/2022/2022-12-14_data2022.csv @@ -0,0 +1,21 @@ +person responsible,Status,signoff,contingencies,"Additional comments, e.g., image quality",Original visualization image in G Drive,Original Filename in G Drive,Final file for visualization submission after all revisions,hash_id,order,team,title,description,data_source,research_link_url,research_link_text,image +FB,Done,X SG,Remove black border from around the continent,,https://drive.google.com/file/d/1HWUoZveBIOG7daEnhc6fS9ols6a1vGD3/view?usp=share_link,nam_choropleth.png,port_cities_southern_africa_travel_time_distance.png,port_cities_southern_africa_travel_time_distance,1,Namibia,Port Cities in Southern Africa: Travel Times and Distance from Major Agglomerations,"From 2012 onwards, the Walvis Bay port in Namibia suffered a collapse in containerized cargo, driven by plummeting transshipment volumes and a massive contraction in Angola’s imports. This figure shows Africa’s population at 20-kilometer aggregation and the area covered by 16-hour travel times to Walvis Bay and peer ports in south-, mid-western, and eastern Africa. The area covered by 16 hours of travel to the port of Walvis Bay reaches a limited market, even though it is relatively more extensive than most of its peer ports. In comparison, most of the population in Botswana, Zimbabwe, and Zambia have shorter routse to travel to the ports of Beira or Durban. This suggests that Namibia might need strategies to improve the inland reach and competitiveness of the port (railway connectivity, lower border delays, and improved turnaround times at the port).",AfriLearn R package,https://growthlab.cid.harvard.edu/policy-research/namibia,,port_cities_southern_africa_travel_time_distance.png +FB,Done,X SG,"RH: not straightforward to understand, countries can also differ in what they report so it's not obvious if it's a feature of the data or an actual pattern +was the visualization portion stretched? The nodes need to be circles +White border to circles to indicate readibility",x,https://drive.google.com/file/d/1xJKCLhCEGJDbCZaTAa_DWcjA2P6G74xP/view?usp=share_link,nam_port_city_space.png,port_city_space.png,port_city_space,2,Namibia,Port City Space,"While certain activities are prevalent across global port cities, there are also large sources of variation between them. This port space maps the similarities in the industrial composition between port cities within a 5km buffer zone. In general, the ports most similar to each other tend to be within the same country or region.",Dun & Bradstreet,,,port_city_space.png +Steven,Done,X SG,,,https://drive.google.com/file/d/1EY2iNo7KeF07rI1PuOkG-R8Ms406GZVh/view?usp=share_link,PieSanctions_np.jpg,,better_sanctions_on_russia_needed,3,Academic team,Better Sanctions on Russia are Needed,"In response to the Russian invasion of Ukraine, the EU, the U.S., and their partners have imposed wide-ranging economic sanctions. An important part of these sanctions are restrictions on exports to Russia. Growth Lab research shows that, in general, export restrictions are an effective policy instrument that achieves the objective of cutting Russia off from critical supplies for its economy. But current sanctions do not leverage their full potential and suffer from serious coordination problems among the anti-Putin coalition, enabling Russia to substitute between coalition suppliers. We show how the efficacy of these sanctions can be raised by ~60% through better coordination and concentrating sanctions on products with the highest impact on Russia.",https://www.globaltradealert.org/,https://growthlab.cid.harvard.edu/publications/design-effective-sanctions-case-bans-exports-russia,,better_sanctions_on_russia_needed.png +Alexia,Done,X SG,Add state boundaries to all states (Wyoming & neighbouring) ,,https://drive.google.com/file/d/113UppRgaFQi0-oP4rxl6VM1j5m6aumqC/view?usp=share_link,remote1921.png,remote_work_across_commuting_zones_wyoming.png,remote_work_across_commuting_zones_wyoming,4,Wyoming,Remote Work Across Commuting Zones (% of Total Employed) in 2019 and 2021,"These maps show the share of self-reported remote workers at the commuting zone level for 2019 and 2021 in Wyoming and surrounding states. Before the pandemic, very few people were working remotely across the region. Remote work grew enormously in many areas by 2021, creating significant variation across commuting zones. The commuting zones of Wyoming range between a minimum estimate of 7.1% in Rawlins and a maximum of 10.9% in Laramie. The commuting zones with the highest share of remote workers are Denver (28%) and Fort Collins (21%) in Colorado and Provo (21%), and Salt Lake City (21%) in Utah. All these commuting zones include larger urban agglomerations, which have tended to support more remote work globally.",American Community Survey,https://growthlab.cid.harvard.edu/files/growthlab/files/wyoming-growth-perspective_full-draft_11-9-2022.pdf,,remote_work_across_commuting_zones_wyoming.png +Alexia,Done,X SG,Take out text for axis in middle and take out the node labels => send to Nil to redo manually,,https://drive.google.com/file/d/1jGNICxrhzLMfewMBHbukQIDF9ugJC9xN/view?usp=share_link,lhf_v_distancedecay.png,ethiopia_diversification_opportunities_vs_sensitivity_remoteness.png,ethiopia_diversification_opportunities_vs_sensitivity_remoteness,5,Ethiopia,Ethiopia’s Diversification Opportunities vs. Sensitivity to Remoteness,"Ethiopia is a remote, landlocked country with large internal distances, limited transportation infrastructure, and neighboring countries with very low purchasing power. This graph plots potential diversification opportunities by their score on a complexity analysis that prioritizes products with similar capabilities required to those that Ethiopia currently has (y-axis) against how sensitive these products are to remoteness (x-axis). The colors indicate product sectors, excluding agriculture and minerals. Many nearby diversification opportunities are very sensitive to remoteness (top right quadrant), indicating that producers may struggle to overcome transport costs to access inputs and reach markets. Only a narrower set of opportunities are more resilient to remote circumstances (top left quadrant).",UN Comtrade,https://growthlab.cid.harvard.edu/policy-research/ethiopia,Ethiopia Research Compendium (may be online soon),ethiopia_diversification_opportunities_vs_sensitivity_remoteness.png +FB,Done,SG,"RH: needs clarification if these are roads/tertiary roads; only display data every 10 years, not every year; axes need to be cleaned up",,https://drive.google.com/file/d/15vOEB3kTZlkgeKl3jAtjOGU23hpUKiui/view?usp=share_link,Deforestation_moving_into_the_forest_from_roads.png,deforestation_moving_inwards_into_forest_from_roads.png,deforestation_moving_inwards_into_forest_from_roads,6,Colombia Amazonia,Deforestation Moving Inwards into the Forest from Roads,"Deforestation in the Colombian Amazon has been increasingly concentrated along tertiary roads, and this chart highlights this association by utilizing a cumulative distribution function. This chart measures how the distance between tree cover loss incidents and the road network has changed over time. The research finds that 80% of deforestation in the Colombian Amazon occurred within 7.2 km of roads.","Global Forest Watch (Year of forest loss), OpenStreetMaps / INVIAS (Road network)",,,deforestation_moving_inwards_into_forest_from_roads.png +Alexia,Done ,X SG,"RH: colors need to indicate the share of professionals in the total employment; put color background for quadrant behind the circles, not mixed",,https://drive.google.com/file/d/1Z4zORaNz1qqmGq65PZ0PFPIi3fD8ymwY/view?usp=share_link,kaz_sector_growth_prof.png,sector_growth_sector_share_specialist_professionals_kazakhstan.png,sector_growth_sector_share_specialist_professionals_kazakhstan,7,Kazakhstan,"Sector Growth vs. Growth in the Sector Share of Specialist-Professionals 2016-2019, Percent",This graph represents the GDP growth of Kazakhstan's economic sectors as well as the growth in the share of professional occupations in the workforce of these sectors. It shows that sectors that grew the most also tend to have experienced a large increase in the share of professionals in their workforce. The graph suggests that the country experienced a skills-biased growth. The size of bubbles is proportional to the sector’s 2019 GDP.,Bureau of National Statistics of Kazakhstan,https://growthlab.cid.harvard.edu/policy-research/kazakhstan,,sector_growth_sector_share_specialist_professionals_kazakhstan.png +Alexia,Done,,,Dotted red line is the dollar poverty level,https://drive.google.com/file/d/1r8Z5KI7S1gr4vc8okrmHrJBtiLfNXWz3/view?usp=share_link,povcal_val.jpg,south_africa_income_consumption_deciles.png,south_africa_income_consumption_deciles,8,South Africa,"Rich as the Richest, Poor as the Poorest: Inequality in South Africa","This graph shows the distribution of average monthly per capita consumption by decile for all countries, highlighting South Africa, Greece, and Cameroon. The graph shows how unequal South Africa is in a striking way. The poorest in South Africa (1st decile) compare to the poorest in Cameroon, a country much poorer than South Africa in terms of overall GDP per capita. But the richest in South Africa (10th decile) are as rich as the richest in Greece, a country with a much higher GDP per capita.",,https://growthlab.cid.harvard.edu/publications/diagnosing-south-africa-high-unemployment-and-low-informality,,south_africa_income_consumption_deciles.png +FB,Done,X SG,,,https://drive.google.com/file/d/1BtidKiMeb1hiLK1I80Df78cI-Gls0RVb/view?usp=share_link,kaz_nonmin_prod_intro_pc_copy.png,competitive_non-mineral_exports_per_capita_kazakhstan.png,competitive_non-mineral_exports_per_capita_kazakhstan,9,Kazakhstan,"Competitive Non-Mineral Exports Per Capita by Product Year of Introduction, 2019","Kazakhstan’s export basket remains concentrated in many of the same products that were prominent two decades earlier. The country had a comparative advantage in very few non-mineral products that were introduced intensively after 2000. In 2019, non-mineral exports per capita were $875, and approximately $610 is comprised of products for which Kazakhstan has a global comparative advantage. This contrasts with other major oil exporters such as the UAE, Oman, and Kuwait, who not only export much higher values of non-mineral products per capita, but who have also more rapidly diversified and expanded their non-mineral exports in the last two decades to have a comparative advantage in many chemicals, processed metals, transportation equipment, and other products.","Atlas of Economic Complexity, World Bank WDI, and author's calculations",https://growthlab.cid.harvard.edu/policy-research/kazakhstan,,competitive_non-mineral_exports_per_capita_kazakhstan.png +FB,Done,X SG,RH: clean up 45 degree line,,https://drive.google.com/file/d/1uUHPHpf4CZcF_KoLm64kwe7JXB-e3_KR/view?usp=share_link,Afcfta_ECI.png,complexity_intra-african_exports_vs_outside_markets.png,complexity_intra-african_exports_vs_outside_markets,10,Ethiopia,Complexity of Intra-African Exports vs. Outside Markets,"The Growth Lab has consistently found that lower complexity economies export their highest complexity products to other lower complexity countries. Due to transportation costs, these markets are often neighbors or otherwise geographically nearby. This graph shows that this pattern holds within Africa by comparing the complexity of the export basket of each African country to the rest of Africa (y-axis) versus the complexity of the export basket to markets beyond Africa (x-axis). Exports that remain within Africa are more complex than those that leave Africa for every nation except for Djibouti and Eswatini. This has important implications for the Africa Continental Free Trade Area (AfCFTA) and export strategies of countries.",Atlas of Economic Complexity,https://growthlab.cid.harvard.edu/policy-research/ethiopia,Ethiopia project web page (loosely),complexity_intra-african_exports_vs_outside_markets.png +FB,Done,X SG,RH: scales need to be synchronized; remove left map (employment to population ratio); add a scatterplot showing spatial correlation of % households doing agriculture and % households experiencing food shortages,,https://drive.google.com/file/d/15O6B0EPvfN6Q-0vahZV79qFV1jXLT4QK/view?usp=share_link,nam_agri_income_food.png,spatial_dimensions_employment_agricultural_activity_namibia.png,spatial_dimensions_employment_agricultural_activity_namibia,11,Namibia,Spatial Dimensions of Agricultural Activity in Namibia,"The north of Namibia is the most densely populated area in the country. These regions represent the biggest inclusion challenge for Namibia as they comprise a large share of the unemployed working-age population. Most subsistence household agriculture happens in the north, but food production is not enough to cover the needs of the population, resulting in significant food shortages. In parallel, employment levels are exceptionally low, so households do not have sources of income that could help the north afford food imports. Additionally, the adverse natural conditions of the area have been worsened by climate change, resulting in significant losses of crop and animal production in recent years.","Namibia Labor Force Survey (2018), Namibia Household Income and Expenditure Survey (2015-2016)",https://growthlab.cid.harvard.edu/policy-research/namibia,,spatial_dimensions_employment_agricultural_activity_namibia.png +FB,Done,X SG,"RH: instead of treemap for right side, use scatterplot showing share of employment in one buffer zone (0-5km) vs. share of employment in another (5-15km), to show what are industries that tend to locate in one and not the other",x,https://drive.google.com/file/d/1oT4d-NUv8sQHUQvnDvKnZso9Ycz2f5L-/view?usp=share_link,nam_port_city_composition_antwerp.png,productive_structure_port_cities_antwerp_belgium.png,productive_structure_port_cities_antwerp_belgium,12,Namibia,"Productive Structure of Port Cities: Antwerp, Belgium","Port cities around the world engage in a diversity of industries. As the distance to the port increases, we observe a higher concentration of employment in transportation, warehousing, and certain types of professional services.","Dun & Bradstreet, HDX-WFP Logistics Database",,,productive_structure_port_cities_antwerp_belgium.png +FB,Done,X SG,RH: needs legend; colors should be the regions,,https://drive.google.com/file/d/1UnvCNoh9JcDfITssNkXeV505UuMptV2o/view?usp=share_link,Manufacturing_Country_Space__2019_.png,,manufacturing_country_space,13,South Africa,Manufacturing Country Space (2019),"The Manufacturing Exports Country Space is a network of countries connected by a measure of the relatedness of their manufacturing exports in 2019. This network could be thought of as the inverse of the Product Space, which shows the links between products with respect to their co-location in countries. We constructed the network by considering only manufacturing products. The relatedness was estimated by calculating the cosine similarity of the matrix of countries and their manufacturing exports and selecting the two most similar partners to each country (Hausmann et al., 2021). The size or weight of the edges corresponds to their similarity value. The countries are colored by regions. The network shows that South Africa is in a cluster of countries for which manufacturing is heavily oriented towards metals and products related to the mining and energy industries, which has implications for economic diversification. ",,https://growthlab.cid.harvard.edu/publications/getting-back-curve-south-africa-manufacturing-challenge,,manufacturing_country_space.png +FB,Done,X SG,"RH: needs to be more visually appealing; instead of showing all lines, add confidence interval/range of other states; maybe only keep 2019 line to make graph cleaner",x,https://drive.google.com/file/d/1_A8hT3dCKpt8e_l1a1tunww4fnQkWPwv/view?usp=share_link,leavers_percent_age.jpg,wyoming_outmigration_by_age_bracket.png,wyoming_outmigration_by_age_bracket,14,Wyoming,Wyoming’s Outmigration by Age Bracket in Context,"This figure summarizes patterns of outmigration by age bracket for the U.S. on average in 2000 and 2019, compared to outmigration for Wyoming in both years. Wyoming is an outlier in outmigration in comparison to other states, and we can see that most people leave by the time they reach the age of 40. Since 2000, there has been a noteworthy difference for Wyoming as there is a decline in the outmigration rate of 18–30-year-olds. Individuals in that age range still leave the state at high rates, but Wyoming is no longer an extreme outlier.",IPUMS ACS,https://growthlab.cid.harvard.edu/files/growthlab/files/wyoming-growth-perspective_full-draft_11-9-2022.pdf,,wyoming_outmigration_by_age_bracket.png +Alexia,Done,X SG,Nil to: Combine in one image file and the legel lables need to be redrawn,,https://drive.google.com/file/d/1zhKvcF1aYfM32TSQMNzOCaKA0IukJLSa/view?usp=share_link,FX_sources.png,official_vs_black_market_exchange_rate_ethiopian_importers.png,official_vs_black_market_exchange_rate_ethiopian_importers,15,Ethiopia,Official vs. Black-Market Exchange Rate Usage by Ethiopian Importers,"The Growth Lab partnered with the Ethiopian Economics Association to conduct a survey of importers to understand business practices in the context of a binding foreign exchange constraint and to quantify macroeconomic variables important for policymaking. The survey revealed that firms tend to exclusively utilize either the official market for foreign exchange or the black market, and only a minority of importers use a mix of both. Large firms are more likely to access foreign exchange through the official market (at a more desirable exchange rate), while smaller firms are more likely to turn to the black market (and a less favorable exchange rate) because they cannot access foreign exchange through official channels.",Growth Lab / Ethiopian Economics Association Importer Survey,https://growthlab.cid.harvard.edu/policy-research/ethiopia,Ethiopia Importer Survey (may be online soon),official_vs_black_market_exchange_rate_ethiopian_importers.png +Alexia,Done,X AL,,,https://drive.google.com/file/d/1c2cdIEaVJ4Wp8_jI5EYLr8FJrlHnn74Y/view?usp=share_link,P2PE_322_vizhub2022.png,countries_diversify_industries_with_similar_occupational_inputs.png,countries_diversify_industries_with_similar_occupational_inputs,16,Academic team,Countries Are More Likely to Enter Industries That Require Fewer New Occupations,"Export diversification is key for development. Because industries differ significantly in their occupational inputs and because, in many countries, the current workforce performs only a subset of occupations, export diversification typically requires training people in new occupations. Such training is costly, and hence it is easier for a country to enter industries that rely more on occupations in which the domestic population already expresses capabilites. New Growth Lab research shows that a country’s export specialization can have long-lasting consequences for its ability to diversify its economy and provides potentially large scope for industrial policy to support entry into new industries.",Atlas trade data; BLS OES,https://growthlab.cid.harvard.edu/publications/simple-theory-economic-development-extensive-industry-margin,,countries_diversify_industries_with_similar_occupational_inputs.png +Nil,ready ,,,,https://drive.google.com/file/d/1WEHjJLVn9wfakesasxTm51uRXMDob8R2/view?usp=share_link,telework.png,,jobs_done_remotely_earn_higher_wages,17,,Jobs That Can Be Done Remotely Tend to Earn Higher Wages,"The pandemic made salient that jobs differ in many ways, including the ability to perform the job from home. This figure shows the proportion of jobs in an industry that can be performed remotely and the median wage of jobs in that industry (where the size of bubbles reflects the U.S. industry size). Lower-wage industries, such as restaurants and retail, have a low proportion of jobs that can be done from home. Conversely, many high-income industries, such as legal services and software development, are more readily performed from home.",Growth Lab analysis using BLS Occupational Employment and Wage Statistics (OES) and O*NET from the United States,https://growthlab.cid.harvard.edu/publications/policy-area/telework,,jobs_done_remotely_earn_higher_wages.png +Steven,Done,X SG,,,https://drive.google.com/file/d/1sOq2-IAJfhsqBJizEw4ypsg7MupFNa_f/view?usp=share_link,forest_and_deforestration_under_different_property_regimes.png,deforestation_in_colombia_by_property_regime.png,deforestation_in_colombia_by_property_regime,18,Colombia Amazonia,"Deforestation in Caquetá, Guaviare, and Putumayo, Colombia by Property Regime","Deforestation in the Colombian Amazon differs significantly across space based on the legal status of land, concentrating in areas with unclear legal status. The majority of forest land in Caquetá, Guaviare, and Putumayo lies within a national park or indigenous reserve, which contributes little to deforestation. Most of the deforestation (83%) occurs in other land regimes, which only control 39% of the total Amazon rainforest. This suggests that deforestation can be tackled by addressing patterns of property regime control in the Amazon rainforest.","Author's elaboration based on IDEAM, WDPA and SIAC",,,deforestation_in_colombia_by_property_regime.png \ No newline at end of file diff --git a/src/pages/stories/bestOf/2022/2022-12-14_data2022.json b/src/pages/stories/bestOf/2022/2022-12-14_data2022.json new file mode 100644 index 0000000..fbddaa5 --- /dev/null +++ b/src/pages/stories/bestOf/2022/2022-12-14_data2022.json @@ -0,0 +1,344 @@ +[ + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "Remove black border from around the continent", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1HWUoZveBIOG7daEnhc6fS9ols6a1vGD3/view?usp=share_link", + "Original Filename in G Drive": "nam_choropleth.png", + "Final file for visualization submission after all revisions": "port_cities_southern_africa_travel_time_distance.png", + "hash_id": "port_cities_southern_africa_travel_time_distance", + "order": 1, + "team": "Namibia", + "title": "Port Cities in Southern Africa: Travel Times and Distance from Major Agglomerations", + "description": "From 2012 onwards, the Walvis Bay port in Namibia suffered a collapse in containerized cargo, driven by plummeting transshipment volumes and a massive contraction in Angola’s imports. This figure shows Africa’s population at 20-kilometer aggregation and the area covered by 16-hour travel times to Walvis Bay and peer ports in south-, mid-western, and eastern Africa. The area covered by 16 hours of travel to the port of Walvis Bay reaches a limited market, even though it is relatively more extensive than most of its peer ports. In comparison, most of the population in Botswana, Zimbabwe, and Zambia have shorter routse to travel to the ports of Beira or Durban. This suggests that Namibia might need strategies to improve the inland reach and competitiveness of the port (railway connectivity, lower border delays, and improved turnaround times at the port).", + "data_source": "AfriLearn R package", + "research_link_url": "https://growthlab.cid.harvard.edu/policy-research/namibia", + "research_link_text": "", + "image": "port_cities_southern_africa_travel_time_distance.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "RH: not straightforward to understand, countries can also differ in what they report so it's not obvious if it's a feature of the data or an actual pattern\nwas the visualization portion stretched? The nodes need to be circles\nWhite border to circles to indicate readibility", + "Additional comments, e.g., image quality": "x", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1xJKCLhCEGJDbCZaTAa_DWcjA2P6G74xP/view?usp=share_link", + "Original Filename in G Drive": "nam_port_city_space.png", + "Final file for visualization submission after all revisions": "port_city_space.png", + "hash_id": "port_city_space", + "order": 2, + "team": "Namibia", + "title": "Port City Space", + "description": "While certain activities are prevalent across global port cities, there are also large sources of variation between them. This port space maps the similarities in the industrial composition between port cities within a 5km buffer zone. In general, the ports most similar to each other tend to be within the same country or region.", + "data_source": "Dun & Bradstreet", + "research_link_url": "", + "research_link_text": "", + "image": "port_city_space.png" + }, + { + "person responsible": "Steven", + "Status": "Done", + "signoff": "X SG", + "contingencies": "", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1EY2iNo7KeF07rI1PuOkG-R8Ms406GZVh/view?usp=share_link", + "Original Filename in G Drive": "PieSanctions_np.jpg", + "Final file for visualization submission after all revisions": "", + "hash_id": "better_sanctions_on_russia_needed", + "order": 3, + "team": "Academic team", + "title": "Better Sanctions on Russia are Needed", + "description": "In response to the Russian invasion of Ukraine, the EU, the U.S., and their partners have imposed wide-ranging economic sanctions. An important part of these sanctions are restrictions on exports to Russia. Growth Lab research shows that, in general, export restrictions are an effective policy instrument that achieves the objective of cutting Russia off from critical supplies for its economy. But current sanctions do not leverage their full potential and suffer from serious coordination problems among the anti-Putin coalition, enabling Russia to substitute between coalition suppliers. We show how the efficacy of these sanctions can be raised by ~60% through better coordination and concentrating sanctions on products with the highest impact on Russia.", + "data_source": "https://www.globaltradealert.org/", + "research_link_url": "https://growthlab.cid.harvard.edu/publications/design-effective-sanctions-case-bans-exports-russia", + "research_link_text": "", + "image": "better_sanctions_on_russia_needed.png" + }, + { + "person responsible": "Alexia", + "Status": "Done", + "signoff": "X SG", + "contingencies": "Add state boundaries to all states (Wyoming & neighbouring)", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/113UppRgaFQi0-oP4rxl6VM1j5m6aumqC/view?usp=share_link", + "Original Filename in G Drive": "remote1921.png", + "Final file for visualization submission after all revisions": "remote_work_across_commuting_zones_wyoming.png", + "hash_id": "remote_work_across_commuting_zones_wyoming", + "order": 4, + "team": "Wyoming", + "title": "Remote Work Across Commuting Zones (% of Total Employed) in 2019 and 2021", + "description": "These maps show the share of self-reported remote workers at the commuting zone level for 2019 and 2021 in Wyoming and surrounding states. Before the pandemic, very few people were working remotely across the region. Remote work grew enormously in many areas by 2021, creating significant variation across commuting zones. The commuting zones of Wyoming range between a minimum estimate of 7.1% in Rawlins and a maximum of 10.9% in Laramie. The commuting zones with the highest share of remote workers are Denver (28%) and Fort Collins (21%) in Colorado and Provo (21%), and Salt Lake City (21%) in Utah. All these commuting zones include larger urban agglomerations, which have tended to support more remote work globally.", + "data_source": "American Community Survey", + "research_link_url": "https://growthlab.cid.harvard.edu/files/growthlab/files/wyoming-growth-perspective_full-draft_11-9-2022.pdf", + "research_link_text": "", + "image": "remote_work_across_commuting_zones_wyoming.png" + }, + { + "person responsible": "Alexia", + "Status": "Done", + "signoff": "X SG", + "contingencies": "Take out text for axis in middle and take out the node labels => send to Nil to redo manually", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1jGNICxrhzLMfewMBHbukQIDF9ugJC9xN/view?usp=share_link", + "Original Filename in G Drive": "lhf_v_distancedecay.png", + "Final file for visualization submission after all revisions": "ethiopia_diversification_opportunities_vs_sensitivity_remoteness.png", + "hash_id": "ethiopia_diversification_opportunities_vs_sensitivity_remoteness", + "order": 5, + "team": "Ethiopia", + "title": "Ethiopia’s Diversification Opportunities vs. Sensitivity to Remoteness", + "description": "Ethiopia is a remote, landlocked country with large internal distances, limited transportation infrastructure, and neighboring countries with very low purchasing power. This graph plots potential diversification opportunities by their score on a complexity analysis that prioritizes products with similar capabilities required to those that Ethiopia currently has (y-axis) against how sensitive these products are to remoteness (x-axis). The colors indicate product sectors, excluding agriculture and minerals. Many nearby diversification opportunities are very sensitive to remoteness (top right quadrant), indicating that producers may struggle to overcome transport costs to access inputs and reach markets. Only a narrower set of opportunities are more resilient to remote circumstances (top left quadrant).", + "data_source": "UN Comtrade", + "research_link_url": "https://growthlab.cid.harvard.edu/policy-research/ethiopia", + "research_link_text": "Ethiopia Research Compendium (may be online soon)", + "image": "ethiopia_diversification_opportunities_vs_sensitivity_remoteness.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "SG", + "contingencies": "RH: needs clarification if these are roads/tertiary roads; only display data every 10 years, not every year; axes need to be cleaned up", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/15vOEB3kTZlkgeKl3jAtjOGU23hpUKiui/view?usp=share_link", + "Original Filename in G Drive": "Deforestation_moving_into_the_forest_from_roads.png", + "Final file for visualization submission after all revisions": "deforestation_moving_inwards_into_forest_from_roads.png", + "hash_id": "deforestation_moving_inwards_into_forest_from_roads", + "order": 6, + "team": "Colombia Amazonia", + "title": "Deforestation Moving Inwards into the Forest from Roads", + "description": "Deforestation in the Colombian Amazon has been increasingly concentrated along tertiary roads, and this chart highlights this association by utilizing a cumulative distribution function. This chart measures how the distance between tree cover loss incidents and the road network has changed over time. The research finds that 80% of deforestation in the Colombian Amazon occurred within 7.2 km of roads.", + "data_source": "Global Forest Watch (Year of forest loss), OpenStreetMaps / INVIAS (Road network)", + "research_link_url": "", + "research_link_text": "", + "image": "deforestation_moving_inwards_into_forest_from_roads.png" + }, + { + "person responsible": "Alexia", + "Status": "Done", + "signoff": "X SG", + "contingencies": "RH: colors need to indicate the share of professionals in the total employment; put color background for quadrant behind the circles, not mixed", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1Z4zORaNz1qqmGq65PZ0PFPIi3fD8ymwY/view?usp=share_link", + "Original Filename in G Drive": "kaz_sector_growth_prof.png", + "Final file for visualization submission after all revisions": "sector_growth_sector_share_specialist_professionals_kazakhstan.png", + "hash_id": "sector_growth_sector_share_specialist_professionals_kazakhstan", + "order": 7, + "team": "Kazakhstan", + "title": "Sector Growth vs. Growth in the Sector Share of Specialist-Professionals 2016-2019, Percent", + "description": "This graph represents the GDP growth of Kazakhstan's economic sectors as well as the growth in the share of professional occupations in the workforce of these sectors. It shows that sectors that grew the most also tend to have experienced a large increase in the share of professionals in their workforce. The graph suggests that the country experienced a skills-biased growth. The size of bubbles is proportional to the sector’s 2019 GDP.", + "data_source": "Bureau of National Statistics of Kazakhstan", + "research_link_url": "https://growthlab.cid.harvard.edu/policy-research/kazakhstan", + "research_link_text": "", + "image": "sector_growth_sector_share_specialist_professionals_kazakhstan.png" + }, + { + "person responsible": "Alexia", + "Status": "Done", + "signoff": "", + "contingencies": "", + "Additional comments, e.g., image quality": "Dotted red line is the dollar poverty level", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1r8Z5KI7S1gr4vc8okrmHrJBtiLfNXWz3/view?usp=share_link", + "Original Filename in G Drive": "povcal_val.jpg", + "Final file for visualization submission after all revisions": "south_africa_income_consumption_deciles.png", + "hash_id": "south_africa_income_consumption_deciles", + "order": 8, + "team": "South Africa", + "title": "Rich as the Richest, Poor as the Poorest: Inequality in South Africa", + "description": "This graph shows the distribution of average monthly per capita consumption by decile for all countries, highlighting South Africa, Greece, and Cameroon. The graph shows how unequal South Africa is in a striking way. The poorest in South Africa (1st decile) compare to the poorest in Cameroon, a country much poorer than South Africa in terms of overall GDP per capita. But the richest in South Africa (10th decile) are as rich as the richest in Greece, a country with a much higher GDP per capita.", + "data_source": "", + "research_link_url": "https://growthlab.cid.harvard.edu/publications/diagnosing-south-africa-high-unemployment-and-low-informality", + "research_link_text": "", + "image": "south_africa_income_consumption_deciles.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1BtidKiMeb1hiLK1I80Df78cI-Gls0RVb/view?usp=share_link", + "Original Filename in G Drive": "kaz_nonmin_prod_intro_pc_copy.png", + "Final file for visualization submission after all revisions": "competitive_non-mineral_exports_per_capita_kazakhstan.png", + "hash_id": "competitive_non-mineral_exports_per_capita_kazakhstan", + "order": 9, + "team": "Kazakhstan", + "title": "Competitive Non-Mineral Exports Per Capita by Product Year of Introduction, 2019", + "description": "Kazakhstan’s export basket remains concentrated in many of the same products that were prominent two decades earlier. The country had a comparative advantage in very few non-mineral products that were introduced intensively after 2000. In 2019, non-mineral exports per capita were $875, and approximately $610 is comprised of products for which Kazakhstan has a global comparative advantage. This contrasts with other major oil exporters such as the UAE, Oman, and Kuwait, who not only export much higher values of non-mineral products per capita, but who have also more rapidly diversified and expanded their non-mineral exports in the last two decades to have a comparative advantage in many chemicals, processed metals, transportation equipment, and other products.", + "data_source": "Atlas of Economic Complexity, World Bank WDI, and author's calculations", + "research_link_url": "https://growthlab.cid.harvard.edu/policy-research/kazakhstan", + "research_link_text": "", + "image": "competitive_non-mineral_exports_per_capita_kazakhstan.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "RH: clean up 45 degree line", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1uUHPHpf4CZcF_KoLm64kwe7JXB-e3_KR/view?usp=share_link", + "Original Filename in G Drive": "Afcfta_ECI.png", + "Final file for visualization submission after all revisions": "complexity_intra-african_exports_vs_outside_markets.png", + "hash_id": "complexity_intra-african_exports_vs_outside_markets", + "order": 10, + "team": "Ethiopia", + "title": "Complexity of Intra-African Exports vs. Outside Markets", + "description": "The Growth Lab has consistently found that lower complexity economies export their highest complexity products to other lower complexity countries. Due to transportation costs, these markets are often neighbors or otherwise geographically nearby. This graph shows that this pattern holds within Africa by comparing the complexity of the export basket of each African country to the rest of Africa (y-axis) versus the complexity of the export basket to markets beyond Africa (x-axis). Exports that remain within Africa are more complex than those that leave Africa for every nation except for Djibouti and Eswatini. This has important implications for the Africa Continental Free Trade Area (AfCFTA) and export strategies of countries.", + "data_source": "Atlas of Economic Complexity", + "research_link_url": "https://growthlab.cid.harvard.edu/policy-research/ethiopia", + "research_link_text": "Ethiopia project web page (loosely)", + "image": "complexity_intra-african_exports_vs_outside_markets.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "RH: scales need to be synchronized; remove left map (employment to population ratio); add a scatterplot showing spatial correlation of % households doing agriculture and % households experiencing food shortages", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/15O6B0EPvfN6Q-0vahZV79qFV1jXLT4QK/view?usp=share_link", + "Original Filename in G Drive": "nam_agri_income_food.png", + "Final file for visualization submission after all revisions": "spatial_dimensions_employment_agricultural_activity_namibia.png", + "hash_id": "spatial_dimensions_employment_agricultural_activity_namibia", + "order": 11, + "team": "Namibia", + "title": "Spatial Dimensions of Agricultural Activity in Namibia", + "description": "The north of Namibia is the most densely populated area in the country. These regions represent the biggest inclusion challenge for Namibia as they comprise a large share of the unemployed working-age population. Most subsistence household agriculture happens in the north, but food production is not enough to cover the needs of the population, resulting in significant food shortages. In parallel, employment levels are exceptionally low, so households do not have sources of income that could help the north afford food imports. Additionally, the adverse natural conditions of the area have been worsened by climate change, resulting in significant losses of crop and animal production in recent years.", + "data_source": "Namibia Labor Force Survey (2018), Namibia Household Income and Expenditure Survey (2015-2016)", + "research_link_url": "https://growthlab.cid.harvard.edu/policy-research/namibia", + "research_link_text": "", + "image": "spatial_dimensions_employment_agricultural_activity_namibia.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "RH: instead of treemap for right side, use scatterplot showing share of employment in one buffer zone (0-5km) vs. share of employment in another (5-15km), to show what are industries that tend to locate in one and not the other", + "Additional comments, e.g., image quality": "x", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1oT4d-NUv8sQHUQvnDvKnZso9Ycz2f5L-/view?usp=share_link", + "Original Filename in G Drive": "nam_port_city_composition_antwerp.png", + "Final file for visualization submission after all revisions": "productive_structure_port_cities_antwerp_belgium.png", + "hash_id": "productive_structure_port_cities_antwerp_belgium", + "order": 12, + "team": "Namibia", + "title": "Productive Structure of Port Cities: Antwerp, Belgium", + "description": "Port cities around the world engage in a diversity of industries. As the distance to the port increases, we observe a higher concentration of employment in transportation, warehousing, and certain types of professional services.", + "data_source": "Dun & Bradstreet, HDX-WFP Logistics Database", + "research_link_url": "", + "research_link_text": "", + "image": "productive_structure_port_cities_antwerp_belgium.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "RH: needs legend; colors should be the regions", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1UnvCNoh9JcDfITssNkXeV505UuMptV2o/view?usp=share_link", + "Original Filename in G Drive": "Manufacturing_Country_Space__2019_.png", + "Final file for visualization submission after all revisions": "", + "hash_id": "manufacturing_country_space", + "order": 13, + "team": "South Africa", + "title": "Manufacturing Country Space (2019)", + "description": "The Manufacturing Exports Country Space is a network of countries connected by a measure of the relatedness of their manufacturing exports in 2019. This network could be thought of as the inverse of the Product Space, which shows the links between products with respect to their co-location in countries. We constructed the network by considering only manufacturing products. The relatedness was estimated by calculating the cosine similarity of the matrix of countries and their manufacturing exports and selecting the two most similar partners to each country (Hausmann et al., 2021). The size or weight of the edges corresponds to their similarity value. The countries are colored by regions. The network shows that South Africa is in a cluster of countries for which manufacturing is heavily oriented towards metals and products related to the mining and energy industries, which has implications for economic diversification.", + "data_source": "", + "research_link_url": "https://growthlab.cid.harvard.edu/publications/getting-back-curve-south-africa-manufacturing-challenge", + "research_link_text": "", + "image": "manufacturing_country_space.png" + }, + { + "person responsible": "FB", + "Status": "Done", + "signoff": "X SG", + "contingencies": "RH: needs to be more visually appealing; instead of showing all lines, add confidence interval/range of other states; maybe only keep 2019 line to make graph cleaner", + "Additional comments, e.g., image quality": "x", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1_A8hT3dCKpt8e_l1a1tunww4fnQkWPwv/view?usp=share_link", + "Original Filename in G Drive": "leavers_percent_age.jpg", + "Final file for visualization submission after all revisions": "wyoming_outmigration_by_age_bracket.png", + "hash_id": "wyoming_outmigration_by_age_bracket", + "order": 14, + "team": "Wyoming", + "title": "Wyoming’s Outmigration by Age Bracket in Context", + "description": "This figure summarizes patterns of outmigration by age bracket for the U.S. on average in 2000 and 2019, compared to outmigration for Wyoming in both years. Wyoming is an outlier in outmigration in comparison to other states, and we can see that most people leave by the time they reach the age of 40. Since 2000, there has been a noteworthy difference for Wyoming as there is a decline in the outmigration rate of 18–30-year-olds. Individuals in that age range still leave the state at high rates, but Wyoming is no longer an extreme outlier.", + "data_source": "IPUMS ACS", + "research_link_url": "https://growthlab.cid.harvard.edu/files/growthlab/files/wyoming-growth-perspective_full-draft_11-9-2022.pdf", + "research_link_text": "", + "image": "wyoming_outmigration_by_age_bracket.png" + }, + { + "person responsible": "Alexia", + "Status": "Done", + "signoff": "X SG", + "contingencies": "Nil to: Combine in one image file and the legel lables need to be redrawn", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1zhKvcF1aYfM32TSQMNzOCaKA0IukJLSa/view?usp=share_link", + "Original Filename in G Drive": "FX_sources.png", + "Final file for visualization submission after all revisions": "official_vs_black_market_exchange_rate_ethiopian_importers.png", + "hash_id": "official_vs_black_market_exchange_rate_ethiopian_importers", + "order": 15, + "team": "Ethiopia", + "title": "Official vs. Black-Market Exchange Rate Usage by Ethiopian Importers", + "description": "The Growth Lab partnered with the Ethiopian Economics Association to conduct a survey of importers to understand business practices in the context of a binding foreign exchange constraint and to quantify macroeconomic variables important for policymaking. The survey revealed that firms tend to exclusively utilize either the official market for foreign exchange or the black market, and only a minority of importers use a mix of both. Large firms are more likely to access foreign exchange through the official market (at a more desirable exchange rate), while smaller firms are more likely to turn to the black market (and a less favorable exchange rate) because they cannot access foreign exchange through official channels.", + "data_source": "Growth Lab / Ethiopian Economics Association Importer Survey", + "research_link_url": "https://growthlab.cid.harvard.edu/policy-research/ethiopia", + "research_link_text": "Ethiopia Importer Survey (may be online soon)", + "image": "official_vs_black_market_exchange_rate_ethiopian_importers.png" + }, + { + "person responsible": "Alexia", + "Status": "Done", + "signoff": "X AL", + "contingencies": "", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1c2cdIEaVJ4Wp8_jI5EYLr8FJrlHnn74Y/view?usp=share_link", + "Original Filename in G Drive": "P2PE_322_vizhub2022.png", + "Final file for visualization submission after all revisions": "countries_diversify_industries_with_similar_occupational_inputs.png", + "hash_id": "countries_diversify_industries_with_similar_occupational_inputs", + "order": 16, + "team": "Academic team", + "title": "Countries Are More Likely to Enter Industries That Require Fewer New Occupations", + "description": "Export diversification is key for development. Because industries differ significantly in their occupational inputs and because, in many countries, the current workforce performs only a subset of occupations, export diversification typically requires training people in new occupations. Such training is costly, and hence it is easier for a country to enter industries that rely more on occupations in which the domestic population already expresses capabilites. New Growth Lab research shows that a country’s export specialization can have long-lasting consequences for its ability to diversify its economy and provides potentially large scope for industrial policy to support entry into new industries.", + "data_source": "Atlas trade data; BLS OES", + "research_link_url": "https://growthlab.cid.harvard.edu/publications/simple-theory-economic-development-extensive-industry-margin", + "research_link_text": "", + "image": "countries_diversify_industries_with_similar_occupational_inputs.png" + }, + { + "person responsible": "Nil", + "Status": "ready", + "signoff": "", + "contingencies": "", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1WEHjJLVn9wfakesasxTm51uRXMDob8R2/view?usp=share_link", + "Original Filename in G Drive": "telework.png", + "Final file for visualization submission after all revisions": "", + "hash_id": "jobs_done_remotely_earn_higher_wages", + "order": 17, + "team": "", + "title": "Jobs That Can Be Done Remotely Tend to Earn Higher Wages", + "description": "The pandemic made salient that jobs differ in many ways, including the ability to perform the job from home. This figure shows the proportion of jobs in an industry that can be performed remotely and the median wage of jobs in that industry (where the size of bubbles reflects the U.S. industry size). Lower-wage industries, such as restaurants and retail, have a low proportion of jobs that can be done from home. Conversely, many high-income industries, such as legal services and software development, are more readily performed from home.", + "data_source": "Growth Lab analysis using BLS Occupational Employment and Wage Statistics (OES) and O*NET from the United States", + "research_link_url": "https://growthlab.cid.harvard.edu/publications/policy-area/telework", + "research_link_text": "", + "image": "jobs_done_remotely_earn_higher_wages.png" + }, + { + "person responsible": "Steven", + "Status": "Done", + "signoff": "X SG", + "contingencies": "", + "Additional comments, e.g., image quality": "", + "Original visualization image in G Drive": "https://drive.google.com/file/d/1sOq2-IAJfhsqBJizEw4ypsg7MupFNa_f/view?usp=share_link", + "Original Filename in G Drive": "forest_and_deforestration_under_different_property_regimes.png", + "Final file for visualization submission after all revisions": "deforestation_in_colombia_by_property_regime.png", + "hash_id": "deforestation_in_colombia_by_property_regime", + "order": 18, + "team": "Colombia Amazonia", + "title": "Deforestation in Caquetá, Guaviare, and Putumayo, Colombia by Property Regime", + "description": "Deforestation in the Colombian Amazon differs significantly across space based on the legal status of land, concentrating in areas with unclear legal status. The majority of forest land in Caquetá, Guaviare, and Putumayo lies within a national park or indigenous reserve, which contributes little to deforestation. Most of the deforestation (83%) occurs in other land regimes, which only control 39% of the total Amazon rainforest. This suggests that deforestation can be tackled by addressing patterns of property regime control in the Amazon rainforest.", + "data_source": "Author's elaboration based on IDEAM, WDPA and SIAC", + "research_link_url": "", + "research_link_text": "", + "image": "deforestation_in_colombia_by_property_regime.png" + } + ] \ No newline at end of file diff --git a/src/pages/stories/bestOf/2022/Template.tsx b/src/pages/stories/bestOf/2022/Template.tsx new file mode 100644 index 0000000..42127e6 --- /dev/null +++ b/src/pages/stories/bestOf/2022/Template.tsx @@ -0,0 +1,294 @@ +import React, { + MutableRefObject, +} from 'react'; +import { + StoriesGrid, +} from '../../../../styling/Grid'; +import { + FullWidth, + StoryTitle, + StickyCenteredContainer, + Authors, + ButtonLink as ButtonLinkBase, + baseColor, +} from '../../../../styling/styleUtils'; +import Share from '../../../../components/share'; + +import TextBlock from '../../../../components/text/TextBlock'; +import styled from 'styled-components/macro'; +import useScrollingSections from '../../../../hooks/useScrollingSections'; +import StandardFooter from '../../../../components/text/StandardFooter'; +import Helmet from 'react-helmet'; +import SmartCoverPhoto from '../../../../components/general/SmartCoverPhoto'; +import DefaultHubHeader from '../../../../components/navigation/DefaultHubHeader'; + +import { + RootAlternative, + HeadingAlternative, + MainNarrativeRoot, + VizContainer, + MobileTextAlternate, + FirstParagraphAlternative, + FadeInContainer, +} from '../../sharedStyling'; +import HashLinkTitle from '../HashLinkTitle'; +import FullScreenImage from '../FullScreenImage'; +import {storyMobileWidth} from '../../../../styling/Grid'; + + + +const StickyContainer = styled.div` + position: sticky; + top: 0; + min-height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + + @media (max-width: ${storyMobileWidth}px) { + position: relative; + z-index: 10; + } +`; + +const DivContainer = styled.div` + a { + border: none; + } +`; + +const FadeInImageContainer = styled(FadeInContainer)` + a { + border: none; + } +`; + +const ButtonLink = styled(ButtonLinkBase)` + margin-top: 1rem; + && { /* needed to override template styling */ + display: inline-block; + border-color: ${baseColor}; + color: ${baseColor}; + + &: hover { + color: #fff; + } + + @media (max-width: ${storyMobileWidth}px) { + background-color: #fff; + box-shadow: 0px 0px 1px 1px #fff; + } + } +`; + +const StickyText = styled(StickyContainer)` + background-color: rgba(0,0,0,0.1); + padding: 1.5rem; + + @media (max-width: ${storyMobileWidth}px) { + background-color: unset; + } +`; + +export const StorySectionContainer = styled.div` + min-height: 50vh; + position: relative; +`; + +const InlineExploreButtonDiv = styled.div` + display: inline-block; + float: left; + +`; + +const InlineShareButtonDiv = styled.div` + display: inline-block; + float: right; + margin-top: 1rem; + padding: 0.4rem 0.6rem; + + @media (max-width: ${storyMobileWidth}px) { + + * { + background-color: #fff; + box-shadow: 0px 0px 1px 1px #fff; + + } + } +`; + + +const LineDivider = styled.div` + width: 100%; + height: 1px; + border-bottom: 1px solid #000000; + margin: 10px 0px; +`; + +export interface SectionDatum { + id: string; + title: string; + text: string | React.ReactNode; + image: string; + linkText: string | undefined; + url: string | undefined; + ref: MutableRefObject; +} + +interface Props { + metaTitle: string; + metaDescription: string; + coverPhotoSrc: {low: string, high: string}; + pageTitle: string; + dateLine: string; + byLine: string | React.ReactNode; + introText: string | React.ReactNode; + sectionsData: SectionDatum[]; + hasBeenRendered: MutableRefObject; +} + + +const BestOfTemplate = (props: Props) => { + const { + metaTitle, metaDescription, coverPhotoSrc, sectionsData, + pageTitle, dateLine, byLine, introText, hasBeenRendered + } = props; + + /* + For some submissions, the link button to explore more + should say "Explore the research", rather than "Explore the project". + + The following hash IDs are submissions where the explore more + button should say "Explore the research". + + */ + const linkToResearch = [ + "better_sanctions_on_russia_needed", + "countries_diversify_industries_with_similar_occupational_inputs", + "manufacturing_country_space", + "south_africa_income_consumption_deciles", + "remote_work_across_commuting_zones_wyoming", + "wyoming_outmigration_by_age_bracket" + ]; + + const {section} = useScrollingSections({refs: sectionsData.map(({ref}) => ref)}); + + let imageElm: React.ReactElement | null = null; + const sectionsElms = sectionsData.map(({title, text, image, ref, id, url}, i) => { + const Wrapper = i === 0 ? FirstParagraphAlternative : MobileTextAlternate; + const refObject = i === 0 ? undefined : ref as React.RefObject; + if (section === i || (section === null && i === 0)) { + const ImageContainer = i === 0 ? DivContainer : FadeInImageContainer; + imageElm = ( + + + + ); + + } + + if(hasBeenRendered.current === true) { + if(section === i) { + window.history.pushState("", document.title, window.location.pathname + "#" + id); + } else if(section === null && i === 0) { + window.history.pushState("", document.title, window.location.pathname); + } + } + let linkButton: React.ReactElement | null; + if (url) { + linkButton = ( + + + {linkToResearch.includes(id) ? 'Explore the research' : 'Explore the project'} + + + ); + } else { + linkButton = null; + } + + let shareButton: React.ReactElement | null; + + shareButton = ( + + + + ); + + + return ( + +
+ + + + + {title} + +
{text}
+ + {linkButton} + {shareButton} +
+
+
+ + ); + + }); + + if(hasBeenRendered.current === false) { + hasBeenRendered.current = true; + } + + return ( + <> + + {metaTitle} + + + + + + + + + + + + {pageTitle} + {dateLine} + {byLine} +
{introText}
+
+
+
+ + + + {imageElm} + + + + : undefined + }> + {sectionsElms} + + +
+ + + ); +}; + +export default BestOfTemplate; diff --git a/src/pages/stories/bestOf/2022/cover-photo-low-res.jpg b/src/pages/stories/bestOf/2022/cover-photo-low-res.jpg new file mode 100644 index 0000000..17718f7 Binary files /dev/null and b/src/pages/stories/bestOf/2022/cover-photo-low-res.jpg differ diff --git a/src/pages/stories/bestOf/2022/cover-photo.jpg b/src/pages/stories/bestOf/2022/cover-photo.jpg new file mode 100644 index 0000000..a345d52 Binary files /dev/null and b/src/pages/stories/bestOf/2022/cover-photo.jpg differ diff --git a/src/pages/stories/bestOf/2022/header_image.png b/src/pages/stories/bestOf/2022/header_image.png new file mode 100644 index 0000000..5c1ab44 Binary files /dev/null and b/src/pages/stories/bestOf/2022/header_image.png differ diff --git a/src/pages/stories/bestOf/2022/images/better_sanctions_on_russia_needed.png b/src/pages/stories/bestOf/2022/images/better_sanctions_on_russia_needed.png new file mode 100644 index 0000000..1ba927b Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/better_sanctions_on_russia_needed.png differ diff --git a/src/pages/stories/bestOf/2022/images/competitive_non-mineral_exports_per_capita_kazakhstan.png b/src/pages/stories/bestOf/2022/images/competitive_non-mineral_exports_per_capita_kazakhstan.png new file mode 100644 index 0000000..7c1767f Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/competitive_non-mineral_exports_per_capita_kazakhstan.png differ diff --git a/src/pages/stories/bestOf/2022/images/complexity_intra-african_exports_vs_outside_markets.png b/src/pages/stories/bestOf/2022/images/complexity_intra-african_exports_vs_outside_markets.png new file mode 100644 index 0000000..f849a7a Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/complexity_intra-african_exports_vs_outside_markets.png differ diff --git a/src/pages/stories/bestOf/2022/images/countries_diversify_industries_with_similar_occupational_inputs.png b/src/pages/stories/bestOf/2022/images/countries_diversify_industries_with_similar_occupational_inputs.png new file mode 100644 index 0000000..137a2d7 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/countries_diversify_industries_with_similar_occupational_inputs.png differ diff --git a/src/pages/stories/bestOf/2022/images/deforestation_in_colombia_by_property_regime.png b/src/pages/stories/bestOf/2022/images/deforestation_in_colombia_by_property_regime.png new file mode 100644 index 0000000..eaf85f6 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/deforestation_in_colombia_by_property_regime.png differ diff --git a/src/pages/stories/bestOf/2022/images/deforestation_moving_inwards_into_forest_from_roads.png b/src/pages/stories/bestOf/2022/images/deforestation_moving_inwards_into_forest_from_roads.png new file mode 100644 index 0000000..9ac8795 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/deforestation_moving_inwards_into_forest_from_roads.png differ diff --git a/src/pages/stories/bestOf/2022/images/ethiopia_diversification_opportunities_vs_sensitivity_remoteness.png b/src/pages/stories/bestOf/2022/images/ethiopia_diversification_opportunities_vs_sensitivity_remoteness.png new file mode 100644 index 0000000..c203a88 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/ethiopia_diversification_opportunities_vs_sensitivity_remoteness.png differ diff --git a/src/pages/stories/bestOf/2022/images/jobs_done_remotely_earn_higher_wages.png b/src/pages/stories/bestOf/2022/images/jobs_done_remotely_earn_higher_wages.png new file mode 100644 index 0000000..8eeea6e Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/jobs_done_remotely_earn_higher_wages.png differ diff --git a/src/pages/stories/bestOf/2022/images/manufacturing_country_space.png b/src/pages/stories/bestOf/2022/images/manufacturing_country_space.png new file mode 100644 index 0000000..97e972f Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/manufacturing_country_space.png differ diff --git a/src/pages/stories/bestOf/2022/images/official_vs_black_market_exchange_rate_ethiopian_importers.png b/src/pages/stories/bestOf/2022/images/official_vs_black_market_exchange_rate_ethiopian_importers.png new file mode 100644 index 0000000..0a5d954 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/official_vs_black_market_exchange_rate_ethiopian_importers.png differ diff --git a/src/pages/stories/bestOf/2022/images/port_cities_southern_africa_travel_time_distance.png b/src/pages/stories/bestOf/2022/images/port_cities_southern_africa_travel_time_distance.png new file mode 100644 index 0000000..846dfe1 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/port_cities_southern_africa_travel_time_distance.png differ diff --git a/src/pages/stories/bestOf/2022/images/port_city_space.png b/src/pages/stories/bestOf/2022/images/port_city_space.png new file mode 100644 index 0000000..78970ed Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/port_city_space.png differ diff --git a/src/pages/stories/bestOf/2022/images/productive_structure_port_cities_antwerp_belgium.png b/src/pages/stories/bestOf/2022/images/productive_structure_port_cities_antwerp_belgium.png new file mode 100644 index 0000000..f6d9f92 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/productive_structure_port_cities_antwerp_belgium.png differ diff --git a/src/pages/stories/bestOf/2022/images/remote_work_across_commuting_zones_wyoming.png b/src/pages/stories/bestOf/2022/images/remote_work_across_commuting_zones_wyoming.png new file mode 100644 index 0000000..a433f0d Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/remote_work_across_commuting_zones_wyoming.png differ diff --git a/src/pages/stories/bestOf/2022/images/sector_growth_sector_share_specialist_professionals_kazakhstan.png b/src/pages/stories/bestOf/2022/images/sector_growth_sector_share_specialist_professionals_kazakhstan.png new file mode 100644 index 0000000..ad8bd65 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/sector_growth_sector_share_specialist_professionals_kazakhstan.png differ diff --git a/src/pages/stories/bestOf/2022/images/south_africa_income_consumption_deciles.png b/src/pages/stories/bestOf/2022/images/south_africa_income_consumption_deciles.png new file mode 100644 index 0000000..f66bb40 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/south_africa_income_consumption_deciles.png differ diff --git a/src/pages/stories/bestOf/2022/images/spatial_dimensions_employment_agricultural_activity_namibia.png b/src/pages/stories/bestOf/2022/images/spatial_dimensions_employment_agricultural_activity_namibia.png new file mode 100644 index 0000000..dbedc01 Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/spatial_dimensions_employment_agricultural_activity_namibia.png differ diff --git a/src/pages/stories/bestOf/2022/images/wyoming_outmigration_by_age_bracket.png b/src/pages/stories/bestOf/2022/images/wyoming_outmigration_by_age_bracket.png new file mode 100644 index 0000000..7c4a29b Binary files /dev/null and b/src/pages/stories/bestOf/2022/images/wyoming_outmigration_by_age_bracket.png differ diff --git a/src/pages/stories/bestOf/2022/index.tsx b/src/pages/stories/bestOf/2022/index.tsx new file mode 100644 index 0000000..2eca57f --- /dev/null +++ b/src/pages/stories/bestOf/2022/index.tsx @@ -0,0 +1,101 @@ +import React, {useRef, useEffect} from 'react'; +import BestOfTemplate, {SectionDatum} from './Template'; +import CoverPhotoImage from './header_image.png'; +// TO DO: Need to create low-res version of header image +import CoverPhotoImageLowRes from './header_image.png'; +import {get, Routes} from '../../../../metadata'; +import data from './2022-12-14_data2022.json'; +import {scrollToAnchor} from '../../../../hooks/useScrollBehavior'; +import { useLocation } from 'react-router'; +import {storyMobileWidth} from '../../../../styling/Grid'; +import orderBy from 'lodash/orderBy'; + + +const orderedData = orderBy(data, ['order'], ['asc']); + +const BestOf2022 = () =>{ + const section_0 = useRef(null); + const section_1 = useRef(null); + const section_2 = useRef(null); + const section_3 = useRef(null); + const section_4 = useRef(null); + const section_5 = useRef(null); + const section_6 = useRef(null); + const section_7 = useRef(null); + const section_8 = useRef(null); + const section_9 = useRef(null); + const section_10 = useRef(null); + const section_11 = useRef(null); + const section_12 = useRef(null); + const section_13 = useRef(null); + const section_14 = useRef(null); + const section_15 = useRef(null); + const section_16 = useRef(null); + const section_17 = useRef(null); + const sections = [ + section_0, + section_1, + section_2, + section_3, + section_4, + section_5, + section_6, + section_7, + section_8, + section_9, + section_10, + section_11, + section_12, + section_13, + section_14, + section_15, + section_16, + section_17, + ]; + + const hasBeenRendered = useRef(false); + + const location = useLocation(); + + useEffect(() => { + const anchor = location && location.hash ? location.hash : null; + const bufferTop = window.innerWidth > storyMobileWidth ? -window.innerHeight * 0.95 : -window.innerHeight * 1.6; + scrollToAnchor({anchor, bufferTop}); + }, [location.pathname]); + + const metadata = get(Routes.BestOf2022); + + const sectionsData: SectionDatum[] = orderedData.map((d, i) => { + const source = d.data_source && d.data_source.length + ? <>

Source: {d.data_source} : null; + const url = d.research_link_url && d.research_link_url.toLowerCase() !== 'n/a' + ? d.research_link_url : undefined; + const linkText = d.research_link_text ? d.research_link_text : undefined; + return ({ + id: d.hash_id, + title: d.title, + text: (

{d.description}{source}

), + image: d.image && d.image.length ? require(`./images/${d.image}`) : CoverPhotoImageLowRes, + linkText, + url, + ref: sections[i], + }); + }); + + return ( + + In 2022, the Growth Lab’s research agenda spanned five continents. Our researchers tackled development challenges with a diverse group of countries and regions while also working on pressing issues such as Russia’s invasion of Ukraine, green growth, and the future of work in a post-pandemic world. The work of our multi-disciplinary team takes on many forms, including pioneering academic research on the determinants of growth, enabling more sustainable and inclusive growth through place-specific policy engagements, and translating research insights into open-access digital tools. In no particular order, here are our top visual insights of 2022.

} + sectionsData={sectionsData} + hasBeenRendered={hasBeenRendered} + /> + ); +}; + +export default BestOf2022; diff --git a/src/pages/stories/bestOf/FullScreenImage.tsx b/src/pages/stories/bestOf/FullScreenImage.tsx index 7c7096c..2a170f3 100644 --- a/src/pages/stories/bestOf/FullScreenImage.tsx +++ b/src/pages/stories/bestOf/FullScreenImage.tsx @@ -22,7 +22,7 @@ const scaleIn = keyframes`{ const Image = styled.img` max-width: 100%; max-height: 80vh; - cursor: pointer; + cursor: zoom-in; &.scale-in { animation: ${scaleIn} 150ms; @@ -38,7 +38,7 @@ const FullScreenImage = ({src}: {src: string}) => { width: '100vw', height: '100vh', backgroundColor: '#fff', - padding: '4rem', + padding: '4rem' } : {}; const closeButton = fullscreen ? : null; @@ -53,6 +53,7 @@ const FullScreenImage = ({src}: {src: string}) => { alt='' title='' className={fullscreen ? 'scale-in' : undefined} + style={{cursor: fullscreen ? 'zoom-out' : 'zoom-in'}} /> {closeButton} diff --git a/src/pages/stories/sharedStyling.ts b/src/pages/stories/sharedStyling.ts index da35f1a..72eb8e1 100644 --- a/src/pages/stories/sharedStyling.ts +++ b/src/pages/stories/sharedStyling.ts @@ -104,6 +104,8 @@ export const HeadingAlternative = styled.div` `; export const MainNarrativeRoot = styled.div` +position: relative; + @media(max-width: ${storyMobileWidth}px) { position: relative; z-index: 150 !important; @@ -146,6 +148,7 @@ export const StickyText = styled(StickyContainer)` top: 10vh; `; + export const MobileText = styled.div` @media (max-width: ${storyMobileWidth}px) { position: relative; @@ -171,6 +174,7 @@ export const MobileTextAlternate = styled.div` } `; + export const FirstParagraph = styled(MobileText)` @media (max-width: ${storyMobileWidth}px) { padding-top: 20vh;