From 014d419e8444655ef4899f57896bd4e49431dee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ra=C4=8D=C3=A1k?= Date: Tue, 26 Nov 2024 11:35:02 +0100 Subject: [PATCH 1/2] Add new about page template --- .../types/src/gdocTypes/Gdoc.ts | 17 +++++ packages/@ourworldindata/types/src/index.ts | 2 + site/gdocs/OwidGdoc.tsx | 7 +- site/gdocs/components/OwidGdocHeader.tsx | 5 +- site/gdocs/pages/AboutPage.scss | 74 +++++++++++++++++++ site/gdocs/pages/AboutPage.tsx | 52 +++++++++++++ site/owid.scss | 1 + 7 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 site/gdocs/pages/AboutPage.scss create mode 100644 site/gdocs/pages/AboutPage.tsx diff --git a/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts b/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts index 0d8a7c64cb0..378f3c33299 100644 --- a/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts +++ b/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts @@ -202,17 +202,32 @@ export interface OwidGdocAuthorInterface extends OwidGdocBaseInterface { latestWorkLinks?: DbEnrichedLatestWork[] } +export interface OwidGdocAboutContent { + type: OwidGdocType.AboutPage + title: string + excerpt: string + "featured-image"?: string + authors: string[] + body: OwidEnrichedGdocBlock[] +} + +export interface OwidGdocAboutInterface extends OwidGdocBaseInterface { + content: OwidGdocAboutContent +} + export type OwidGdocContent = | OwidGdocPostContent | OwidGdocDataInsightContent | OwidGdocHomepageContent | OwidGdocAuthorContent + | OwidGdocAboutContent export type OwidGdoc = | OwidGdocPostInterface | OwidGdocDataInsightInterface | OwidGdocHomepageInterface | OwidGdocAuthorInterface + | OwidGdocAboutInterface export enum OwidGdocErrorMessageType { Error = "error", @@ -226,6 +241,8 @@ export type OwidGdocProperty = | keyof OwidGdocDataInsightContent | keyof OwidGdocAuthorInterface | keyof OwidGdocAuthorContent + | keyof OwidGdocAboutInterface + | keyof OwidGdocAboutContent export type OwidGdocErrorMessageProperty = | OwidGdocProperty diff --git a/packages/@ourworldindata/types/src/index.ts b/packages/@ourworldindata/types/src/index.ts index 562dd93191d..1d5808c615f 100644 --- a/packages/@ourworldindata/types/src/index.ts +++ b/packages/@ourworldindata/types/src/index.ts @@ -284,6 +284,8 @@ export { type OwidGdocErrorMessage, OwidGdocErrorMessageType, type OwidGdocLinkJSON, + type OwidGdocAboutContent, + type OwidGdocAboutInterface, type OwidGdocAuthorContent, type OwidGdocAuthorInterface, type OwidGdocBaseInterface, diff --git a/site/gdocs/OwidGdoc.tsx b/site/gdocs/OwidGdoc.tsx index 122455fef22..e21685689c7 100644 --- a/site/gdocs/OwidGdoc.tsx +++ b/site/gdocs/OwidGdoc.tsx @@ -21,6 +21,7 @@ import { DataInsightPage } from "./pages/DataInsight.js" import { Fragment } from "./pages/Fragment.js" import { Homepage } from "./pages/Homepage.js" import { Author } from "./pages/Author.js" +import AboutPage from "./pages/AboutPage.js" export type Attachments = { linkedAuthors?: LinkedAuthor[] @@ -79,13 +80,15 @@ export function OwidGdoc({ type: P.union( OwidGdocType.Article, OwidGdocType.TopicPage, - OwidGdocType.LinearTopicPage, - OwidGdocType.AboutPage + OwidGdocType.LinearTopicPage ), }, }, (props) => ) + .with({ content: { type: OwidGdocType.AboutPage } }, (props) => ( + + )) .with({ content: { type: OwidGdocType.DataInsight } }, (props) => ( )) diff --git a/site/gdocs/components/OwidGdocHeader.tsx b/site/gdocs/components/OwidGdocHeader.tsx index c97ba5a92ac..413f5eeabd4 100644 --- a/site/gdocs/components/OwidGdocHeader.tsx +++ b/site/gdocs/components/OwidGdocHeader.tsx @@ -174,10 +174,7 @@ export function OwidGdocHeader(props: { return if (props.content.type === OwidGdocType.TopicPage) return - if ( - props.content.type === OwidGdocType.LinearTopicPage || - props.content.type === OwidGdocType.AboutPage - ) + if (props.content.type === OwidGdocType.LinearTopicPage) return // Defaulting to ArticleHeader, but will require the value to be set for all docs going forward return diff --git a/site/gdocs/pages/AboutPage.scss b/site/gdocs/pages/AboutPage.scss new file mode 100644 index 00000000000..4dfb8fe079a --- /dev/null +++ b/site/gdocs/pages/AboutPage.scss @@ -0,0 +1,74 @@ +.about-header { + color: $blue-60; +} + +.about-nav { + border-bottom: 1px solid $blue-20; +} + +.about-nav-list { + display: flex; + gap: 8px; + list-style: none; + padding: 0; + + h2 { + margin: 0; + } +} + +.about-nav-link { + @include body-2-regular; + display: block; + padding: 16px; + color: $blue-60; + text-wrap: nowrap; + + &--is-active { + @include body-2-semibold; + color: $blue-90; + border-bottom: 1px solid $vermillion; + } + + &:hover { + color: $blue-90; + } +} + +.about-body { + margin-bottom: 80px; + + h2 { + @include h1-semibold; + color: $blue-60; + } + + h2:first-of-type { + margin-top: 32px; + } + + hr { + margin: 40px 0; + } + + // Remove some margins since margins don't collapse in display: grid. + .article-block__side-by-side { + margin: 0; + } + + hr + .article-block__side-by-side { + h2 { + margin-top: 0; + } + + *:last-child { + margin-bottom: 0; + } + } + + .article-block__side-by-side:has(+ hr) { + *:last-child { + margin-bottom: 0; + } + } +} diff --git a/site/gdocs/pages/AboutPage.tsx b/site/gdocs/pages/AboutPage.tsx new file mode 100644 index 00000000000..a5f91ed4868 --- /dev/null +++ b/site/gdocs/pages/AboutPage.tsx @@ -0,0 +1,52 @@ +import cx from "classnames" +import * as React from "react" + +import { OwidGdocAboutInterface } from "@ourworldindata/types" +import { ArticleBlocks } from "../components/ArticleBlocks.js" + +const NAV_LINKS = [ + { title: "About Us", href: "/about" }, + { title: "Organization", href: "/organization" }, + { title: "Funding", href: "/funding" }, + { title: "Team", href: "/team" }, + { title: "Jobs", href: "/jobs" }, + { title: "FAQs", href: "/faqs" }, +] + +export default function AboutPage({ content, slug }: OwidGdocAboutInterface) { + return ( +
+

+ About +

+ +
+ +
+
+ ) +} + +function AboutNav({ slug }: { slug: string }) { + return ( + + ) +} diff --git a/site/owid.scss b/site/owid.scss index f80ce84450d..7bd853d8c22 100644 --- a/site/owid.scss +++ b/site/owid.scss @@ -119,6 +119,7 @@ @import "./gdocs/pages/DataInsight.scss"; @import "./gdocs/pages/Homepage.scss"; @import "./gdocs/pages/Author.scss"; +@import "./gdocs/pages/AboutPage.scss"; @import "css/donate.scss"; @import "./ThankYouPage.scss"; From 874da675f928817af0c4c039f82cd8077fd7dde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ra=C4=8D=C3=A1k?= Date: Tue, 26 Nov 2024 11:37:40 +0100 Subject: [PATCH 2/2] Add people ArchieML component --- db/model/Gdoc/GdocBase.ts | 2 + db/model/Gdoc/enrichedToMarkdown.ts | 20 ++++++++ db/model/Gdoc/enrichedToRaw.ts | 21 ++++++++ db/model/Gdoc/exampleEnrichedBlocks.ts | 15 ++++++ db/model/Gdoc/gdocUtils.ts | 4 ++ db/model/Gdoc/rawToArchie.ts | 31 ++++++++++++ db/model/Gdoc/rawToEnriched.ts | 50 +++++++++++++++++++ .../types/src/gdocTypes/ArchieMlComponents.ts | 32 ++++++++++++ .../types/src/gdocTypes/Gdoc.ts | 2 +- packages/@ourworldindata/types/src/index.ts | 4 ++ packages/@ourworldindata/utils/src/Util.ts | 12 +++++ site/gdocs/OwidGdoc.tsx | 3 +- site/gdocs/components/ArticleBlock.tsx | 10 ++++ site/gdocs/components/Image.tsx | 2 + site/gdocs/components/People.scss | 6 +++ site/gdocs/components/People.tsx | 12 +++++ site/gdocs/components/Person.scss | 42 ++++++++++++++++ site/gdocs/components/Person.tsx | 40 +++++++++++++++ site/owid.scss | 2 + 19 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 site/gdocs/components/People.scss create mode 100644 site/gdocs/components/People.tsx create mode 100644 site/gdocs/components/Person.scss create mode 100644 site/gdocs/components/Person.tsx diff --git a/db/model/Gdoc/GdocBase.ts b/db/model/Gdoc/GdocBase.ts index f0c5e036a38..03a5f6445cd 100644 --- a/db/model/Gdoc/GdocBase.ts +++ b/db/model/Gdoc/GdocBase.ts @@ -554,6 +554,8 @@ export class GdocBase implements OwidGdocBaseInterface { "list", "missing-data", "numbered-list", + "people", + "person", "pull-quote", "sdg-grid", "sdg-toc", diff --git a/db/model/Gdoc/enrichedToMarkdown.ts b/db/model/Gdoc/enrichedToMarkdown.ts index 8c8994dea26..7cba71488f8 100644 --- a/db/model/Gdoc/enrichedToMarkdown.ts +++ b/db/model/Gdoc/enrichedToMarkdown.ts @@ -6,6 +6,7 @@ import { getLinkType } from "@ourworldindata/components" import { OwidEnrichedGdocBlock, Span, + compact, excludeNullish, isArray, } from "@ourworldindata/utils" @@ -156,6 +157,25 @@ ${items} .with({ type: "list" }, (b): string | undefined => b.items.map((item) => `* ${spansToMarkdown(item.value)}`).join("\n") ) + .with({ type: "people" }, (b): string | undefined => + b.items + .map((item) => enrichedBlockToMarkdown(item, exportComponents)) + .join("\n") + ) + .with({ type: "person" }, (b): string | undefined => { + const items = [ + b.image && + markdownComponent( + "Image", + { filename: b.image, alt: b.name }, + exportComponents + ), + `### ${b.name}`, + b.title, + enrichedBlocksToMarkdown(b.text, exportComponents), + ] + return compact(items).join("\n") + }) .with( { type: "pull-quote" }, (b): string | undefined => `> ${spansToMarkdown(b.text)}` diff --git a/db/model/Gdoc/enrichedToRaw.ts b/db/model/Gdoc/enrichedToRaw.ts index 7cdb40bf7f7..9a2ada59b0c 100644 --- a/db/model/Gdoc/enrichedToRaw.ts +++ b/db/model/Gdoc/enrichedToRaw.ts @@ -44,6 +44,8 @@ import { RawBlockHomepageIntro, RawBlockLatestDataInsights, RawBlockSocials, + RawBlockPeople, + RawBlockPerson, } from "@ourworldindata/types" import { spanToHtmlString } from "./gdocUtils.js" import { match, P } from "ts-pattern" @@ -182,6 +184,25 @@ export function enrichedBlockToRawBlock( value: b.items.map((item) => spansToHtmlText(item.value)), }) ) + .with( + { type: "people" }, + (b): RawBlockPeople => ({ + type: b.type, + value: b.items.map(enrichedBlockToRawBlock) as RawBlockPerson[], + }) + ) + .with( + { type: "person" }, + (b): RawBlockPerson => ({ + type: "person", + value: { + image: b.image, + name: b.name, + title: b.title, + text: b.text.map(enrichedBlockToRawBlock) as RawBlockText[], + }, + }) + ) .with( { type: "pull-quote" }, (b): RawBlockPullQuote => ({ diff --git a/db/model/Gdoc/exampleEnrichedBlocks.ts b/db/model/Gdoc/exampleEnrichedBlocks.ts index 2c1e6581560..84329f12c45 100644 --- a/db/model/Gdoc/exampleEnrichedBlocks.ts +++ b/db/model/Gdoc/exampleEnrichedBlocks.ts @@ -1,6 +1,7 @@ import { BlockImageSize, EnrichedBlockChart, + EnrichedBlockPerson, EnrichedBlockText, HorizontalAlign, OwidEnrichedGdocBlock, @@ -48,6 +49,14 @@ const enrichedChart: EnrichedBlockChart = { parseErrors: [], } +const enrichedBlockPerson: EnrichedBlockPerson = { + type: "person", + image: "example.png", + name: "Max Roser", + text: [enrichedBlockText], + parseErrors: [], +} + export const enrichedBlockExamples: Record< OwidEnrichedGdocBlock["type"], OwidEnrichedGdocBlock @@ -176,6 +185,12 @@ export const enrichedBlockExamples: Record< items: [enrichedBlockText], parseErrors: [], }, + people: { + type: "people", + items: [enrichedBlockPerson, enrichedBlockPerson], + parseErrors: [], + }, + person: enrichedBlockPerson, "pull-quote": { type: "pull-quote", text: [spanSimpleText], diff --git a/db/model/Gdoc/gdocUtils.ts b/db/model/Gdoc/gdocUtils.ts index 0c9f32abff8..39339fc5563 100644 --- a/db/model/Gdoc/gdocUtils.ts +++ b/db/model/Gdoc/gdocUtils.ts @@ -174,6 +174,9 @@ export function extractFilenamesFromBlock( if (item.filename) filenames.add(item.filename) if (item.smallFilename) filenames.add(item.smallFilename) }) + .with({ type: "person" }, (item) => { + if (item.image) filenames.add(item.image) + }) .with({ type: "prominent-link" }, (item) => { if (item.thumbnail) filenames.add(item.thumbnail) }) @@ -233,6 +236,7 @@ export function extractFilenamesFromBlock( "list", "missing-data", "numbered-list", + "people", "pill-row", "pull-quote", "recirc", diff --git a/db/model/Gdoc/rawToArchie.ts b/db/model/Gdoc/rawToArchie.ts index bc9c8f37373..d8ee8aa4a17 100644 --- a/db/model/Gdoc/rawToArchie.ts +++ b/db/model/Gdoc/rawToArchie.ts @@ -43,6 +43,8 @@ import { RawBlockHomepageSearch, RawBlockLatestDataInsights, RawBlockSocials, + RawBlockPeople, + RawBlockPerson, } from "@ourworldindata/types" import { isArray } from "@ourworldindata/utils" import { match } from "ts-pattern" @@ -213,6 +215,33 @@ function* rawBlockNumberedListToArchieMLString( yield* listToArchieMLString(block.value, "numbered-list") } +function* rawBlockPeopleToArchieMLString( + block: RawBlockPeople +): Generator { + yield "[.+people]" + if (typeof block.value !== "string") { + for (const b of block.value) { + yield* OwidRawGdocBlockToArchieMLStringGenerator(b) + } + } + yield "[]" +} + +function* rawBlockPersonToArchieMLString( + block: RawBlockPerson +): Generator { + yield "{.person}" + yield* propertyToArchieMLString("image", block.value) + yield* propertyToArchieMLString("name", block.value) + yield* propertyToArchieMLString("title", block.value) + yield "[.+text]" + for (const b of block.value.text) { + yield* OwidRawGdocBlockToArchieMLStringGenerator(b) + } + yield "[]" + yield "{}" +} + function* rawBlockPullQuoteToArchieMLString( block: RawBlockPullQuote ): Generator { @@ -773,6 +802,8 @@ export function* OwidRawGdocBlockToArchieMLStringGenerator( .with({ type: "video" }, rawBlockVideoToArchieMLString) .with({ type: "list" }, rawBlockListToArchieMLString) .with({ type: "numbered-list" }, rawBlockNumberedListToArchieMLString) + .with({ type: "people" }, rawBlockPeopleToArchieMLString) + .with({ type: "person" }, rawBlockPersonToArchieMLString) .with({ type: "pull-quote" }, rawBlockPullQuoteToArchieMLString) .with( { type: "horizontal-rule" }, diff --git a/db/model/Gdoc/rawToEnriched.ts b/db/model/Gdoc/rawToEnriched.ts index d951a28ee88..e6e3eb0e3b0 100644 --- a/db/model/Gdoc/rawToEnriched.ts +++ b/db/model/Gdoc/rawToEnriched.ts @@ -120,6 +120,10 @@ import { SocialLinkType, RawBlockLatestWork, EnrichedBlockLatestWork, + RawBlockPeople, + EnrichedBlockPeople, + RawBlockPerson, + EnrichedBlockPerson, } from "@ourworldindata/types" import { traverseEnrichedSpan, @@ -166,6 +170,8 @@ export function parseRawBlocksToEnrichedBlocks( .with({ type: "video" }, parseVideo) .with({ type: "list" }, parseList) .with({ type: "numbered-list" }, parseNumberedList) + .with({ type: "people" }, parsePeople) + .with({ type: "person" }, parsePerson) .with({ type: "pull-quote" }, parsePullQuote) .with( { type: "horizontal-rule" }, @@ -790,6 +796,50 @@ const parseList = (raw: RawBlockList): EnrichedBlockList => { // return { errors, texts } // } +const parsePerson = (raw: RawBlockPerson): EnrichedBlockPerson => { + const createError = (error: ParseError): EnrichedBlockPerson => ({ + type: "person", + name: "", + text: [], + parseErrors: [error], + }) + + if (!raw.value?.name) { + return createError({ message: "Person must have a name" }) + } + + return { + type: "person", + image: raw.value.image, + name: raw.value.name, + title: raw.value.title, + text: raw.value.text.map(parseText), + parseErrors: [], + } +} + +const parsePeople = (raw: RawBlockPeople): EnrichedBlockPeople => { + const createError = ( + error: ParseError, + items: EnrichedBlockPerson[] = [] + ): EnrichedBlockPeople => ({ + type: "people", + items, + parseErrors: [error], + }) + + if (typeof raw.value === "string") + return createError({ + message: "Value is a string, not a list of {.person} blocks", + }) + + return { + type: "people", + items: raw.value.map(parsePerson), + parseErrors: [], + } +} + const parsePullQuote = (raw: RawBlockPullQuote): EnrichedBlockPullQuote => { const createError = ( error: ParseError, diff --git a/packages/@ourworldindata/types/src/gdocTypes/ArchieMlComponents.ts b/packages/@ourworldindata/types/src/gdocTypes/ArchieMlComponents.ts index d2e2fdda4a4..7d839f78099 100644 --- a/packages/@ourworldindata/types/src/gdocTypes/ArchieMlComponents.ts +++ b/packages/@ourworldindata/types/src/gdocTypes/ArchieMlComponents.ts @@ -245,6 +245,34 @@ export type EnrichedBlockNumberedList = { items: EnrichedBlockText[] } & EnrichedBlockWithParseErrors +export type RawBlockPeople = { + type: "people" + value: RawBlockPerson[] | ArchieMLUnexpectedNonObjectValue +} + +export type RawBlockPerson = { + type: "person" + value: { + image?: string + name: string + title?: string + text: RawBlockText[] + } +} + +export type EnrichedBlockPeople = { + type: "people" + items: EnrichedBlockPerson[] +} & EnrichedBlockWithParseErrors + +export type EnrichedBlockPerson = { + type: "person" + image?: string + name: string + title?: string + text: EnrichedBlockText[] +} & EnrichedBlockWithParseErrors + export type RawBlockPullQuote = { type: "pull-quote" value: OwidRawGdocBlock[] | ArchieMLUnexpectedNonObjectValue @@ -887,6 +915,8 @@ export type OwidRawGdocBlock = | RawBlockImage | RawBlockVideo | RawBlockList + | RawBlockPeople + | RawBlockPerson | RawBlockPullQuote | RawBlockRecirc | RawBlockResearchAndWriting @@ -933,6 +963,8 @@ export type OwidEnrichedGdocBlock = | EnrichedBlockImage | EnrichedBlockVideo | EnrichedBlockList + | EnrichedBlockPeople + | EnrichedBlockPerson | EnrichedBlockPullQuote | EnrichedBlockRecirc | EnrichedBlockResearchAndWriting diff --git a/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts b/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts index 378f3c33299..2973bc895ef 100644 --- a/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts +++ b/packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts @@ -205,7 +205,7 @@ export interface OwidGdocAuthorInterface extends OwidGdocBaseInterface { export interface OwidGdocAboutContent { type: OwidGdocType.AboutPage title: string - excerpt: string + excerpt?: string "featured-image"?: string authors: string[] body: OwidEnrichedGdocBlock[] diff --git a/packages/@ourworldindata/types/src/index.ts b/packages/@ourworldindata/types/src/index.ts index 1d5808c615f..39644a16320 100644 --- a/packages/@ourworldindata/types/src/index.ts +++ b/packages/@ourworldindata/types/src/index.ts @@ -184,6 +184,8 @@ export { type RawBlockList, type RawBlockMissingData, type RawBlockNumberedList, + type RawBlockPeople, + type RawBlockPerson, type RawBlockPosition, type RawBlockProminentLink, type RawBlockPullQuote, @@ -237,6 +239,8 @@ export { type EnrichedBlockList, type EnrichedBlockMissingData, type EnrichedBlockNumberedList, + type EnrichedBlockPeople, + type EnrichedBlockPerson, type EnrichedBlockProminentLink, type EnrichedBlockPullQuote, type EnrichedBlockRecirc, diff --git a/packages/@ourworldindata/utils/src/Util.ts b/packages/@ourworldindata/utils/src/Util.ts index 5dc5d615f86..5551975fae3 100644 --- a/packages/@ourworldindata/utils/src/Util.ts +++ b/packages/@ourworldindata/utils/src/Util.ts @@ -1664,6 +1664,18 @@ export function traverseEnrichedBlock( ) } ) + .with({ type: "people" }, (people) => { + callback(people) + for (const item of people.items) { + traverseEnrichedBlock(item, callback, spanCallback) + } + }) + .with({ type: "person" }, (person) => { + callback(person) + for (const node of person.text) { + traverseEnrichedBlock(node, callback, spanCallback) + } + }) .with( { type: P.union( diff --git a/site/gdocs/OwidGdoc.tsx b/site/gdocs/OwidGdoc.tsx index e21685689c7..b37668275a2 100644 --- a/site/gdocs/OwidGdoc.tsx +++ b/site/gdocs/OwidGdoc.tsx @@ -9,6 +9,7 @@ import { RelatedChart, OwidGdocType, OwidGdoc as OwidGdocInterface, + OwidGdocAboutInterface, OwidGdocMinimalPostInterface, OwidGdocHomepageMetadata, DbEnrichedLatestWork, @@ -87,7 +88,7 @@ export function OwidGdoc({ (props) => ) .with({ content: { type: OwidGdocType.AboutPage } }, (props) => ( - + )) .with({ content: { type: OwidGdocType.DataInsight } }, (props) => ( diff --git a/site/gdocs/components/ArticleBlock.tsx b/site/gdocs/components/ArticleBlock.tsx index bd33ba3e209..d6719aeb68a 100644 --- a/site/gdocs/components/ArticleBlock.tsx +++ b/site/gdocs/components/ArticleBlock.tsx @@ -22,6 +22,7 @@ import { BlockErrorBoundary, BlockErrorFallback } from "./BlockErrorBoundary.js" import { match } from "ts-pattern" import { renderSpans } from "../utils.js" import Paragraph from "./Paragraph.js" +import People from "./People.js" import TableOfContents from "./TableOfContents.js" import urlSlug from "url-slug" import { MissingData } from "./MissingData.js" @@ -42,6 +43,7 @@ import { HomepageIntro } from "./HomepageIntro.js" import { HomepageSearch } from "./HomepageSearch.js" import LatestDataInsightsBlock from "./LatestDataInsightsBlock.js" import { Socials } from "./Socials.js" +import Person from "./Person.js" export type Container = | "default" @@ -285,6 +287,14 @@ export default function ArticleBlock({ filename={block.filename} /> )) + .with({ type: "people" }, (block) => ( + + {block.items.map((block, index) => ( + + ))} + + )) + .with({ type: "person" }, (block) => ) .with({ type: "pull-quote" }, (block) => ( = { ["key-insight"]: gridSpan5, ["author-byline"]: "48px", ["author-header"]: gridSpan2, + ["person"]: gridSpan2, ["span-5"]: gridSpan5, ["span-6"]: gridSpan6, ["span-7"]: gridSpan7, diff --git a/site/gdocs/components/People.scss b/site/gdocs/components/People.scss new file mode 100644 index 00000000000..d9df395736b --- /dev/null +++ b/site/gdocs/components/People.scss @@ -0,0 +1,6 @@ +.people { + display: flex; + flex-direction: column; + gap: 24px; + max-width: 845px; +} diff --git a/site/gdocs/components/People.tsx b/site/gdocs/components/People.tsx new file mode 100644 index 00000000000..9000d699ffe --- /dev/null +++ b/site/gdocs/components/People.tsx @@ -0,0 +1,12 @@ +import cx from "classnames" +import * as React from "react" + +export default function People({ + className, + children, +}: { + className?: string + children: React.ReactNode +}) { + return
{children}
+} diff --git a/site/gdocs/components/Person.scss b/site/gdocs/components/Person.scss new file mode 100644 index 00000000000..2d4f8af0771 --- /dev/null +++ b/site/gdocs/components/Person.scss @@ -0,0 +1,42 @@ +.person { + display: flex; + gap: 24px; + + @include sm-only { + flex-direction: column; + gap: 16px; + } +} + +.person-image-container { + display: flex; + flex: 0 0 193px; + gap: 16px; + + @include sm-only { + align-items: center; + flex: initial; + } +} + +.person-image { + img { + border-radius: 50%; + } + + @include sm-only { + flex: 0 0 76px; + } +} + +.person-header { + margin-bottom: 8px; +} + +.person-heading { + margin: 0; +} + +.person-title { + color: $blue-60; +} diff --git a/site/gdocs/components/Person.tsx b/site/gdocs/components/Person.tsx new file mode 100644 index 00000000000..ee879a937dc --- /dev/null +++ b/site/gdocs/components/Person.tsx @@ -0,0 +1,40 @@ +import * as React from "react" + +import { EnrichedBlockPerson } from "@ourworldindata/types" +import { ArticleBlocks } from "./ArticleBlocks.js" +import Image from "./Image.js" +import { useMediaQuery } from "usehooks-ts" +import { SMALL_BREAKPOINT_MEDIA_QUERY } from "../../SiteConstants.js" + +export default function Person({ person }: { person: EnrichedBlockPerson }) { + const isSmallScreen = useMediaQuery(SMALL_BREAKPOINT_MEDIA_QUERY) + + const header = ( +
+

{person.name}

+ {person.title && ( + {person.title} + )} +
+ ) + + return ( +
+ {person.image && ( +
+ + {isSmallScreen && header} +
+ )} +
+ {(!person.image || !isSmallScreen) && header} + +
+
+ ) +} diff --git a/site/owid.scss b/site/owid.scss index 7bd853d8c22..056589b9feb 100644 --- a/site/owid.scss +++ b/site/owid.scss @@ -105,6 +105,8 @@ @import "./gdocs/components/KeyIndicator.scss"; @import "./gdocs/components/KeyIndicatorCollection.scss"; @import "./gdocs/components/PillRow.scss"; +@import "./gdocs/components/People.scss"; +@import "./gdocs/components/Person.scss"; @import "./AboutThisData.scss"; @import "./DataInsightsNewsletterBanner.scss"; @import "./DataPage.scss";