refactor(website): extract homepage data from UI; feature text updates (#6672)

* refactor(website): extract homepage data from UI; feature text updates

* minor edit
This commit is contained in:
Joshua Chen 2022-02-14 14:13:23 +08:00 committed by GitHub
parent d8caf3f896
commit 56b81d1a55
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 396 additions and 292 deletions

View file

@ -28,7 +28,7 @@
"yarn.lock",
"project-words.txt",
"website/src/data/users.tsx",
"website/src/data/tweets/index.tsx",
"website/src/data/tweets.tsx",
"*.xyz",
"*.docx",
"versioned_docs",

View file

@ -32,7 +32,14 @@ export default function Tweet({
<div className={clsx('card', styles.tweet)}>
<div className="card__header">
<div className="avatar">
<img alt={name} className="avatar__photo" src={avatar} />
<img
alt={name}
className="avatar__photo"
src={avatar}
width="48"
height="48"
loading="lazy"
/>
<div className="avatar__intro">
<div className={styles.tweet}>
<div>

View file

@ -0,0 +1,112 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import Translate, {translate} from '@docusaurus/Translate';
export type FeatureItem = {
title: string;
image: {
src: string;
width: number;
height: number;
};
text: JSX.Element;
};
const FEATURES: FeatureItem[] = [
{
title: translate({
message: 'Powered by MDX',
id: 'homepage.features.powered-by-mdx.title',
}),
image: {
src: '/img/undraw_typewriter.svg',
width: 1009.54,
height: 717.96,
},
text: (
<Translate id="homepage.features.powered-by-mdx.text">
Save time and focus on text documents. Simply write docs and blog posts
with MDX, and Docusaurus builds them into static HTML files ready to be
served. You can even embed React components in your Markdown thanks to
MDX.
</Translate>
),
},
{
title: translate({
message: 'Built Using React',
id: 'homepage.features.built-using-react.title',
}),
image: {
src: '/img/undraw_react.svg',
width: 1108,
height: 731.18,
},
text: (
<Translate id="homepage.features.built-using-react.text">
Extend and customize your project&apos;s layout by writing React
components. Leverage the pluggable architecture, and design your own
site while reusing the same data created by Docusaurus plugins.
</Translate>
),
},
{
title: translate({
message: 'Ready for Translations',
id: 'homepage.features.ready-for-translations.title',
}),
image: {
src: '/img/undraw_around_the_world.svg',
width: 1137,
height: 776.59,
},
text: (
<Translate id="homepage.features.ready-for-translations.text">
Localization comes out-of-the-box. Use git, Crowdin, or any other
translation manager to translate your docs and deploy them individually.
</Translate>
),
},
{
title: translate({
message: 'Document Versioning',
id: 'homepage.features.document-versioning.title',
}),
image: {
src: '/img/undraw_version_control.svg',
width: 1038.23,
height: 693.31,
},
text: (
<Translate id="homepage.features.document-versioning.text">
Support users on all versions of your project. Document versioning helps
you keep documentation in sync with project releases.
</Translate>
),
},
{
title: translate({
message: 'Content Search',
id: 'homepage.features.content-search.title',
}),
image: {
src: '/img/undraw_algolia.svg',
width: 1137.97,
height: 736.21,
},
text: (
<Translate id="homepage.features.content-search.text">
Make it easy for your community to find what they need in your
documentation. We proudly support Algolia documentation search.
</Translate>
),
},
];
export default FEATURES;

View file

@ -0,0 +1,73 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable global-require */
import React from 'react';
import Translate, {translate} from '@docusaurus/Translate';
const QUOTES = [
{
thumbnail: require('./quotes/christopher-chedeau.jpg'),
name: 'Christopher "vjeux" Chedeau',
title: translate({
id: 'homepage.quotes.christopher-chedeau.title',
message: 'Lead Prettier Developer',
description: 'Title of quote of Christopher Chedeau on the home page',
}),
text: (
<Translate
id="homepage.quotes.christopher-chedeau"
description="Quote of Christopher Chedeau on the home page">
I&apos;ve helped open source many projects at Facebook and every one
needed a website. They all had very similar constraints: the
documentation should be written in markdown and be deployed via GitHub
pages. Im so glad that Docusaurus now exists so that I dont have to
spend a week each time spinning up a new one.
</Translate>
),
},
{
thumbnail: require('./quotes/hector-ramos.jpg'),
name: 'Hector Ramos',
title: translate({
id: 'homepage.quotes.hector-ramos.title',
message: 'Lead React Native Advocate',
description: 'Title of quote of Hector Ramos on the home page',
}),
text: (
<Translate
id="homepage.quotes.hector-ramos"
description="Quote of Hector Ramos on the home page">
Open source contributions to the React Native docs have skyrocketed
after our move to Docusaurus. The docs are now hosted on a small repo in
plain markdown, with none of the clutter that a typical static site
generator would require. Thanks Slash!
</Translate>
),
},
{
thumbnail: require('./quotes/ricky-vetter.jpg'),
name: 'Ricky Vetter',
title: translate({
id: 'homepage.quotes.risky-vetter.title',
message: 'ReasonReact Developer',
description: 'Title of quote of Ricky Vetter on the home page',
}),
text: (
<Translate
id="homepage.quotes.risky-vetter"
description="Quote of Ricky Vetter on the home page">
Docusaurus has been a great choice for the ReasonML family of projects.
It makes our documentation consistent, i18n-friendly, easy to maintain,
and friendly for new contributors.
</Translate>
),
},
];
export default QUOTES;

View file

@ -7,7 +7,7 @@
import React from 'react';
import type {Props as Tweet} from '../../components/Tweet';
import type {Props as Tweet} from '../components/Tweet';
export interface TweetItem extends Tweet {
showOnHomepage: boolean;
@ -74,7 +74,7 @@ const TWEETS: TweetItem[] = [
less time building documentation and more time building 🛳
<br />
<br />
Thanks @docusaurus team 🦖
Thanks <b>@docusaurus</b> team 🦖
</>
),
showOnHomepage: true,
@ -102,7 +102,11 @@ const TWEETS: TweetItem[] = [
date: 'Nov 17, 2020',
avatar:
'https://pbs.twimg.com/profile_images/1481221429991718913/aNZZgZME_400x400.jpg',
content: <>.@docusaurus </>,
content: (
<>
.<b>@docusaurus</b>
</>
),
showOnHomepage: false,
},
{
@ -114,10 +118,10 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/1252900852156772352/JLIVJ-TC_400x400.jpg',
content: (
<>
Been doing a lot of work with @docusaurus lately and I have to say it is
really fun to work with. A lot of really cool features. I love that you
can easily reuse content by creating a markdown file and importing it as
a component. 🔥
Been doing a lot of work with <b>@docusaurus</b> lately and I have to
say it is really fun to work with. A lot of really cool features. I love
that you can easily reuse content by creating a markdown file and
importing it as a component. 🔥
</>
),
showOnHomepage: true,
@ -131,10 +135,11 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/1280609918022815746/nCWpKbYh_400x400.jpg',
content: (
<>
The #IOTA wiki is now part of the @docusaurus showcase. We even have the
honor of being a favorite. We are really happy that we found this
project. It helped us a lot to improve the documentation. And we still
have a lot of plans with things like tutorials, versioning and i8n.
The #IOTA wiki is now part of the <b>@docusaurus</b> showcase. We even
have the honor of being a favorite. We are really happy that we found
this project. It helped us a lot to improve the documentation. And we
still have a lot of plans with things like tutorials, versioning and
i8n.
</>
),
showOnHomepage: true,
@ -149,8 +154,8 @@ const TWEETS: TweetItem[] = [
content: (
<>
http://testing-library.com just got a nice update! We&apos;re now on the
latest version of @docusaurus thanks to @matanbobi, @TensorNo, and
@nickemccurdy 💙
latest version of <b>@docusaurus</b> thanks to @matanbobi, @TensorNo,
and @nickemccurdy 💙
<br />
<br />
My favorite new feature: dark mode!! 🌑/
@ -177,8 +182,8 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/1456506127961640962/iM2Hf8du_400x400.jpg',
content: (
<>
Happy to share Temporal&apos;s first open source sponsorship of
@docusaurus!
Happy to share Temporal&apos;s first open source sponsorship of{' '}
<b>@docusaurus</b>!
<br />
<br />
@temporalio uses it for http://docs.temporal.io, and it has been a huge
@ -195,7 +200,11 @@ const TWEETS: TweetItem[] = [
date: 'Jan 5, 2022',
avatar:
'https://pbs.twimg.com/profile_images/1316805792893489152/7soY-vhs_400x400.jpg',
content: <>I hear @docusaurus is a good tool for that!</>,
content: (
<>
I hear <b>@docusaurus</b> is a good tool for that!
</>
),
showOnHomepage: false,
},
{
@ -222,8 +231,8 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/552803871567790081/rPdTN64o_400x400.jpeg',
content: (
<>
I @docusaurus - it makes it so easy to spin up docs, blogs and simple
websites. I&apos;ve used it to:
I <b>@docusaurus</b> - it makes it so easy to spin up docs, blogs and
simple websites. I&apos;ve used it to:
<br />
<br /> Replatform my blog with GitHub pages <br />
Build a website for a local business <br /> Build internal facing
@ -260,7 +269,8 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/573206276819140608/gKAusMeX_400x400.jpeg',
content: (
<>
🥳🎊🥳🎊🥳🎊🥳🎊 The @reactnative website just migrated to @docusaurus
🥳🎊🥳🎊🥳🎊🥳🎊 The @reactnative website just migrated to{' '}
<b>@docusaurus</b>
v2
<br />
Some obvious changes: <br />
@ -287,7 +297,7 @@ const TWEETS: TweetItem[] = [
dark mode! 😎
<br />
<br />
Thanks to the @docusaurus team for their help!
Thanks to the <b>@docusaurus</b> team for their help!
<br />
<br />
https://create-react-app.dev
@ -308,7 +318,7 @@ const TWEETS: TweetItem[] = [
<br />
<br />
👏 @cloverich did the awesome job of migrating from ancient gitbook
-&gt; @docusaurus! 👏 <br />
-&gt; <b>@docusaurus</b>! 👏 <br />
<br />
No real content updates yet, but contributing and publishing has become
way easier
@ -325,10 +335,10 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/1423143362232823809/4khdTyVZ_400x400.png',
content: (
<>
The new website has landed 🚀 powered by @docusaurus v2 and made by
@_semoal kudos to him 👏 #verdaccio #nodejs awesome contribution 🔥
(video made with react remotion @JNYBGR ) all Open Source and hosted on
@Netlify https://verdaccio.org
The new website has landed 🚀 powered by <b>@docusaurus</b> v2 and made
by @_semoal kudos to him 👏 #verdaccio #nodejs awesome contribution
🔥 (video made with react remotion @JNYBGR ) all Open Source and
hosted on @Netlify https://verdaccio.org
</>
),
showOnHomepage: false,
@ -343,8 +353,8 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/1247950572096868352/3kuZJz5j_400x400.jpg',
content: (
<>
I made a @docusaurus website for answers to the H5BP Front End Interview
Questions! Hopefully it makes the browsing experience easier -
I made a <b>@docusaurus</b> website for answers to the H5BP Front End
Interview Questions! Hopefully it makes the browsing experience easier -
https://frontendinterviewhandbook.com
</>
),
@ -360,7 +370,7 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/1302550637197000705/pg5XF8rA_400x400.jpg',
content: (
<>
Just upgraded our website to @docusaurus latest with
Just upgraded our website to <b>@docusaurus</b> latest with
internationalization support 🥳
<br />
<br />
@ -382,8 +392,8 @@ const TWEETS: TweetItem[] = [
'https://pbs.twimg.com/profile_images/1371525161829208064/UCzm0Zye_400x400.jpg',
content: (
<>
Today I tried @docusaurus in a project, I really like the ease and speed
of developing with it \o/
Today I tried <b>@docusaurus</b> in a project, I really like the ease
and speed of developing with it \o/
</>
),
showOnHomepage: false,

View file

@ -5,83 +5,98 @@
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable global-require */
import React from 'react';
import Link from '@docusaurus/Link';
import Translate, {translate} from '@docusaurus/Translate';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useBaseUrl, {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
import Image from '@theme/IdealImage';
import Layout from '@theme/Layout';
import Tweet from '@site/src/components/Tweet';
import Tweets, {type TweetItem} from '@site/src/data/tweets';
import Quotes from '@site/src/data/quotes';
import Features, {type FeatureItem} from '@site/src/data/features';
import clsx from 'clsx';
import styles from './styles.module.css';
const QUOTES = [
{
thumbnail: require('../data/quotes/christopher-chedeau.jpg'),
name: 'Christopher "vjeux" Chedeau',
title: translate({
id: 'homepage.quotes.christopher-chedeau.title',
message: 'Lead Prettier Developer',
description: 'Title of quote of Christopher Chedeau on the home page',
}),
text: (
<Translate
id="homepage.quotes.christopher-chedeau"
description="Quote of Christopher Chedeau on the home page">
I&apos;ve helped open source many projects at Facebook and every one
needed a website. They all had very similar constraints: the
documentation should be written in markdown and be deployed via GitHub
pages. Im so glad that Docusaurus now exists so that I dont have to
spend a week each time spinning up a new one.
</Translate>
),
},
{
thumbnail: require('../data/quotes/hector-ramos.jpg'),
name: 'Hector Ramos',
title: translate({
id: 'homepage.quotes.hector-ramos.title',
message: 'Lead React Native Advocate',
description: 'Title of quote of Hector Ramos on the home page',
}),
text: (
<Translate
id="homepage.quotes.hector-ramos"
description="Quote of Hector Ramos on the home page">
Open source contributions to the React Native docs have skyrocketed
after our move to Docusaurus. The docs are now hosted on a small repo in
plain markdown, with none of the clutter that a typical static site
generator would require. Thanks Slash!
</Translate>
),
},
{
thumbnail: require('../data/quotes/ricky-vetter.jpg'),
name: 'Ricky Vetter',
title: translate({
id: 'homepage.quotes.risky-vetter.title',
message: 'ReasonReact Developer',
description: 'Title of quote of Ricky Vetter on the home page',
}),
text: (
<Translate
id="homepage.quotes.risky-vetter"
description="Quote of Ricky Vetter on the home page">
Docusaurus has been a great choice for the ReasonML family of projects.
It makes our documentation consistent, i18n-friendly, easy to maintain,
and friendly for new contributors.
</Translate>
),
},
];
function HeroBanner() {
return (
<div className={styles.hero} data-theme="dark">
<div className={styles.heroInner}>
<h1 className={styles.heroProjectTagline}>
<img
alt={translate({message: 'Docusaurus with Keytar'})}
className={styles.heroLogo}
src={useBaseUrl('/img/docusaurus_keytar.svg')}
width="200"
height="200"
/>
<span
className={styles.heroTitleTextHtml}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: translate({
id: 'homepage.hero.title',
message:
'Build <b>optimized</b> websites <b>quickly</b>, focus on your <b>content</b>',
description:
'Home page hero title, can contain simple html tags',
}),
}}
/>
</h1>
<div className={styles.indexCtas}>
<Link className="button button--primary" to="/docs">
<Translate>Get Started</Translate>
</Link>
<Link className="button button--info" to="https://docusaurus.new">
<Translate>Playground</Translate>
</Link>
<span className={styles.indexCtasGitHubButtonWrapper}>
<iframe
className={styles.indexCtasGitHubButton}
src="https://ghbtns.com/github-btn.html?user=facebook&amp;repo=docusaurus&amp;type=star&amp;count=true&amp;size=large"
width={160}
height={30}
title="GitHub Stars"
/>
</span>
</div>
</div>
</div>
);
}
function MigrationAnnouncement() {
return (
<div
className={clsx(styles.announcement, styles.announcementDark)}
data-theme="dark">
<div className={styles.announcementInner}>
<Translate
values={{
docusaurusV1Link: (
<Link to="https://v1.docusaurus.io/">
<Translate>Docusaurus v1</Translate>
</Link>
),
migrationGuideLink: (
<Link to="/docs/migration">
<Translate>v1 to v2 migration guide</Translate>
</Link>
),
}}>
{`Coming from {docusaurusV1Link}? Check out our {migrationGuideLink}`}
</Translate>
.
</div>
</div>
);
}
function TweetsSection() {
const tweetColumns: Array<Array<TweetItem>> = [[], [], []];
@ -109,6 +124,36 @@ function TweetsSection() {
);
}
function QuotesSection() {
return (
<div className={clsx(styles.section)}>
<div className="container">
<div className="row">
{Quotes.map((quote) => (
<div className="col" key={quote.name}>
<div className="avatar avatar--vertical margin-bottom--sm">
<Image
alt={quote.name}
className="avatar__photo avatar__photo--xl"
img={quote.thumbnail}
style={{overflow: 'hidden'}}
/>
<div className="avatar__intro padding-top--sm">
<div className="avatar__name">{quote.name}</div>
<small className="avatar__subtitle">{quote.title}</small>
</div>
</div>
<p className="text--center text--italic padding-horiz--md">
{quote.text}
</p>
</div>
))}
</div>
</div>
</div>
);
}
function VideoContainer() {
return (
<div className="container text--center margin-bottom--xl">
@ -134,6 +179,57 @@ function VideoContainer() {
);
}
function Feature({
feature,
className,
}: {
feature: FeatureItem;
className?: string;
}) {
const {withBaseUrl} = useBaseUrlUtils();
return (
<div className={clsx('col', className)}>
<img
className={styles.featureImage}
alt={feature.title}
width={feature.image.width}
height={feature.image.height}
src={withBaseUrl(feature.image.src)}
/>
<h3 className={clsx(styles.featureHeading)}>{feature.title}</h3>
<p className="padding-horiz--md">{feature.text}</p>
</div>
);
}
function FeaturesContainer() {
const firstRow = Features.slice(0, 3);
const secondRow = Features.slice(3);
return (
<div className="container text--center">
<h2>
<Translate>Main features</Translate>
</h2>
<div className="row margin-bottom--lg">
{firstRow.map((feature, idx) => (
<Feature feature={feature} key={idx} />
))}
</div>
<div className="row">
{secondRow.map((feature, idx) => (
<Feature
feature={feature}
key={idx}
className={clsx('col--4', idx === 0 && 'col--offset-2')}
/>
))}
</div>
</div>
);
}
function Home(): JSX.Element {
const {
siteConfig: {customFields, tagline},
@ -142,208 +238,14 @@ function Home(): JSX.Element {
return (
<Layout title={tagline} description={description}>
<main>
<div className={styles.hero} data-theme="dark">
<div className={styles.heroInner}>
<h1 className={styles.heroProjectTagline}>
<img
alt={translate({message: 'Docusaurus with Keytar'})}
className={styles.heroLogo}
src={useBaseUrl('/img/docusaurus_keytar.svg')}
width="200"
height="200"
/>
<span
className={styles.heroTitleTextHtml}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: translate({
id: 'homepage.hero.title',
message:
'Build <b>optimized</b> websites <b>quickly</b>, focus on your <b>content</b>',
description:
'Home page hero title, can contain simple html tags',
}),
}}
/>
</h1>
<div className={styles.indexCtas}>
<Link className="button button--primary" to="/docs">
<Translate>Get Started</Translate>
</Link>
<Link className="button button--info" to="https://docusaurus.new">
<Translate>Playground</Translate>
</Link>
<span className={styles.indexCtasGitHubButtonWrapper}>
<iframe
className={styles.indexCtasGitHubButton}
src="https://ghbtns.com/github-btn.html?user=facebook&amp;repo=docusaurus&amp;type=star&amp;count=true&amp;size=large"
width={160}
height={30}
title="GitHub Stars"
/>
</span>
</div>
</div>
</div>
<div
className={clsx(styles.announcement, styles.announcementDark)}
data-theme="dark">
<div className={styles.announcementInner}>
<Translate
values={{
docusaurusV1Link: (
<Link to="https://v1.docusaurus.io/">
<Translate>Docusaurus v1</Translate>
</Link>
),
migrationGuideLink: (
<Link to="/docs/migration">
<Translate>v1 to v2 migration guide</Translate>
</Link>
),
}}>
{`Coming from {docusaurusV1Link}? Check out our {migrationGuideLink}`}
</Translate>
.
</div>
</div>
<HeroBanner />
<MigrationAnnouncement />
<div className={styles.section}>
<VideoContainer />
<div className="container text--center margin-bottom--xl">
<h2>
<Translate>Main features</Translate>
</h2>
<div className="row">
<div className="col">
<img
className={styles.featureImage}
alt="Powered by MDX"
src={useBaseUrl('/img/undraw_typewriter.svg')}
width="1009.54"
height="717.96"
/>
<h3 className={clsx(styles.featureHeading)}>
<Translate>Powered by Markdown</Translate>
</h3>
<p className="padding-horiz--md">
<Translate>
Save time and focus on your project&apos;s documentation.
Simply write docs and blog posts with Markdown/MDX and
Docusaurus will publish a set of static HTML files ready to
serve. You can even embed JSX components into your Markdown
thanks to MDX.
</Translate>
</p>
</div>
<div className="col">
<img
alt="Built Using React"
className={styles.featureImage}
src={useBaseUrl('/img/undraw_react.svg')}
width="1108"
height="731.18"
/>
<h3 className={clsx(styles.featureHeading)}>
<Translate>Built Using React</Translate>
</h3>
<p className="padding-horiz--md">
<Translate>
Extend or customize your project&apos;s layout by reusing
React. Docusaurus can be extended while reusing the same
header and footer.
</Translate>
</p>
</div>
<div className="col">
<img
alt="Ready for Translations"
className={styles.featureImage}
src={useBaseUrl('/img/undraw_around_the_world.svg')}
width="1137"
height="776.59"
/>
<h3 className={clsx(styles.featureHeading)}>
<Translate>Ready for Translations</Translate>
</h3>
<p className="padding-horiz--md">
<Translate>
Localization comes pre-configured. Use Crowdin to translate
your docs into over 70 languages.
</Translate>
</p>
</div>
</div>
</div>
<div className="container text--center">
<div className="row">
<div className="col col--4 col--offset-2">
<img
alt="Document Versioning"
className={styles.featureImage}
src={useBaseUrl('/img/undraw_version_control.svg')}
width="1038.23"
height="693.31"
/>
<h3 className={clsx(styles.featureHeading)}>
<Translate>Document Versioning</Translate>
</h3>
<p className="padding-horiz--md">
<Translate>
Support users on all versions of your project. Document
versioning helps you keep documentation in sync with project
releases.
</Translate>
</p>
</div>
<div className="col col--4">
<img
alt="Document Search"
className={styles.featureImage}
src={useBaseUrl('/img/undraw_algolia.svg')}
width="1137.97"
height="736.21"
/>
<h3 className={clsx(styles.featureHeading)}>
<Translate>Content Search</Translate>
</h3>
<p className="padding-horiz--md">
<Translate>
Make it easy for your community to find what they need in
your documentation. We proudly support Algolia documentation
search.
</Translate>
</p>
</div>
</div>
</div>
<FeaturesContainer />
</div>
<TweetsSection />
<div className={clsx(styles.section)}>
<div className="container">
<div className="row">
{QUOTES.map((quote) => (
<div className="col" key={quote.name}>
<div className="avatar avatar--vertical margin-bottom--sm">
<Image
alt={quote.name}
className="avatar__photo avatar__photo--xl"
img={quote.thumbnail}
style={{overflow: 'hidden'}}
/>
<div className="avatar__intro padding-top--sm">
<div className="avatar__name">{quote.name}</div>
<small className="avatar__subtitle">{quote.title}</small>
</div>
</div>
<p className="text--center text--italic padding-horiz--md">
{quote.text}
</p>
</div>
))}
</div>
</div>
</div>
<QuotesSection />
</main>
</Layout>
);