Skip to content

Commit 2f7a1a3

Browse files
authored
Home: replace raw links with logo wordmarks in the Community section (#5152)
1 parent e4a8288 commit 2f7a1a3

11 files changed

Lines changed: 300 additions & 83 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import {useEffect, useState} from 'react';
9+
10+
import CallstackWordmark from '@site/static/img/showcase/callstack_wordmark.svg';
11+
import ExpoWordmark from '@site/static/img/showcase/expo-wordmark.svg';
12+
import InfiniteRedWordmark from '@site/static/img/showcase/infinite-red-wordmark.svg';
13+
import MicrosoftWordmark from '@site/static/img/showcase/microsoft-wordmark.svg';
14+
import SWMWordmark from '@site/static/img/showcase/swm-wordmark.svg';
15+
import {PartnerLink} from '@site/src/types';
16+
17+
import styles from './styles.module.css';
18+
19+
const PARTNERS = [
20+
{
21+
href: 'https://callstack.com/',
22+
logo: <CallstackWordmark />,
23+
},
24+
{
25+
href: 'https://expo.dev/',
26+
className: styles.expo,
27+
logo: <ExpoWordmark />,
28+
},
29+
{
30+
href: 'https://infinite.red/',
31+
logo: <InfiniteRedWordmark />,
32+
},
33+
{
34+
href: 'https://www.microsoft.com/',
35+
logo: <MicrosoftWordmark />,
36+
},
37+
{
38+
href: 'https://swmansion.com/',
39+
logo: <SWMWordmark />,
40+
},
41+
];
42+
43+
export default function PartnersShowcase() {
44+
const [partners, setPartners] = useState<PartnerLink[]>(PARTNERS);
45+
46+
useEffect(() => {
47+
setPartners(currentCompanies => shuffleItems(currentCompanies));
48+
}, []);
49+
50+
return (
51+
<div className={styles.partnersContainer}>
52+
{partners.map(({href, className, logo}) => (
53+
<a
54+
key={href}
55+
href={href}
56+
target="_blank"
57+
rel="noopener noreferrer"
58+
className={className}>
59+
{logo}
60+
</a>
61+
))}
62+
</div>
63+
);
64+
}
65+
66+
function shuffleItems(apps: PartnerLink[]) {
67+
return [...apps].sort(() => 0.5 - Math.random());
68+
}

website/src/components/Home/Community/index.tsx

Lines changed: 18 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77

88
import useBaseUrl from '@docusaurus/useBaseUrl';
99
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
10+
import {ShowcaseData} from '@site/src/types';
1011

12+
import PartnersShowcase from './PartnersShowcase';
1113
import Section from '../Section';
1214
import SectionTitle from '../SectionTitle';
1315

1416
import styles from './styles.module.css';
1517

1618
function Community() {
1719
const {siteConfig} = useDocusaurusContext();
18-
const apps = Object.values(siteConfig.customFields.users)
20+
const apps = Object.values(siteConfig.customFields?.users as ShowcaseData)
1921
.flat()
20-
.filter(app => app.pinned);
22+
.filter(app => Boolean(app.pinned));
2123

2224
return (
2325
<Section>
@@ -60,58 +62,15 @@ function Community() {
6062
<div className={styles.communityNote}>
6163
<p>
6264
Meta released React Native in 2015 and has been maintaining it ever
63-
since. Today, React Native is supported by contributions from
64-
individuals and companies around the world including{' '}
65-
<span>
66-
<a
67-
href="https://callstack.com/"
68-
target="_blank"
69-
rel="noopener noreferrer">
70-
Callstack
71-
</a>
72-
</span>
73-
,{' '}
74-
<span>
75-
<a
76-
href="https://expo.dev/"
77-
target="_blank"
78-
rel="noopener noreferrer">
79-
Expo
80-
</a>
81-
</span>
82-
,{' '}
83-
<a
84-
href="https://infinite.red/"
85-
target="_blank"
86-
rel="noopener noreferrer">
87-
Infinite Red
88-
</a>
89-
,{' '}
90-
<a
91-
href="https://www.microsoft.com/"
92-
target="_blank"
93-
rel="noopener noreferrer">
94-
Microsoft
95-
</a>{' '}
96-
and{' '}
97-
<a
98-
href="https://swmansion.com/"
99-
target="_blank"
100-
rel="noopener noreferrer">
101-
Software Mansion
102-
</a>
103-
. If you're interested in learning more, check out{' '}
104-
<a
105-
href="https://github.com/react/react-native/blob/main/ECOSYSTEM.md"
106-
target="_blank"
107-
rel="noopener noreferrer">
108-
how we have structured the ecosystem
109-
</a>
110-
.
65+
since.
66+
<br />
67+
Today, React Native is supported by contributions from individuals and
68+
companies around the world including:
11169
</p>
70+
<PartnersShowcase />
11271
<p>
113-
Our community is always shipping exciting new projects and expanding
114-
beyond Android and iOS with initiatives like{' '}
72+
Additionally, our community is always shipping exciting new projects
73+
and expanding beyond Android and iOS with initiatives like{' '}
11574
<a
11675
href="https://microsoft.github.io/react-native-windows/"
11776
target="_blank"
@@ -132,9 +91,15 @@ function Community() {
13291
rel="noopener noreferrer">
13392
React Native Web
13493
</a>
135-
.
13694
</p>
13795
</div>
96+
<a
97+
href="https://github.com/react/react-native/blob/main/ECOSYSTEM.md"
98+
target="_blank"
99+
rel="noopener noreferrer"
100+
className={styles.secondaryButton}>
101+
Learn more about the Ecosystem
102+
</a>
138103
</Section>
139104
);
140105
}

website/src/components/Home/Community/styles.module.css

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,62 @@
5353
}
5454
}
5555

56+
.partnersContainer {
57+
display: grid;
58+
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
59+
align-items: center;
60+
justify-content: center;
61+
gap: 16px;
62+
padding: 20px 0 40px;
63+
64+
a {
65+
display: flex;
66+
justify-content: center;
67+
color: var(--ifm-heading-color);
68+
69+
&,
70+
&:hover {
71+
border-bottom: 0 !important;
72+
}
73+
74+
&.expo svg {
75+
max-width: 130px;
76+
}
77+
}
78+
79+
svg {
80+
max-width: 142px;
81+
max-height: 56px;
82+
}
83+
}
84+
85+
html[data-theme="dark"] {
86+
.partnersContainer a {
87+
color: var(--ifm-heading-color) !important;
88+
}
89+
}
90+
91+
@media only screen and (max-width: 800px) {
92+
.partnersContainer {
93+
grid-template-columns: 1fr 1fr 1fr;
94+
gap: 20px 24px;
95+
}
96+
}
97+
98+
@media only screen and (max-width: 450px) {
99+
.partnersContainer {
100+
grid-template-columns: 1fr 1fr;
101+
column-gap: 32px;
102+
}
103+
}
104+
56105
.communityNote {
57-
margin-top: 48px;
106+
margin-top: 52px;
107+
margin-bottom: 8px;
58108
text-align: center;
59109
color: var(--home-secondary-text);
60110
padding: 0 12px;
111+
font-size: 0.9rem;
61112
}
62113

63114
.secondaryButton {

website/src/pages/showcase.tsx

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,24 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import React, {useEffect, useState} from 'react';
8+
import {type PropsWithChildren, useEffect, useState} from 'react';
9+
910
import useBaseUrl from '@docusaurus/useBaseUrl';
1011
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
11-
import Layout from '@theme/Layout';
12-
import type users from '../../showcase.json';
13-
import IconExternalLink from '../theme/Icon/ExternalLink';
12+
import {ShowcaseApp, ShowcaseData} from '@site/src/types';
1413
import ThemedImage from '@theme/ThemedImage';
14+
import Layout from '@theme/Layout';
1515

16-
type UserAppType = (typeof users)[keyof typeof users][number];
17-
18-
const renderApp = (app: UserAppType, i: number) => (
19-
<AppBox app={app} key={`app-${app.name}-${i}`} />
20-
);
16+
import IconExternalLink from '../theme/Icon/ExternalLink';
2117

2218
function Section({
2319
children,
2420
background = 'light',
25-
}: React.PropsWithChildren<{background?: 'light' | 'dark'}>) {
21+
}: PropsWithChildren<{background?: 'light' | 'dark'}>) {
2622
return <section className={`Section ${background}`}>{children}</section>;
2723
}
2824

29-
const AppBox = ({app}: {app: UserAppType}) => {
25+
const AppBox = ({app}: {app: ShowcaseApp}) => {
3026
const imgSource = useBaseUrl(
3127
app.icon.startsWith('http') ? app.icon : 'img/showcase/' + app.icon
3228
);
@@ -57,7 +53,7 @@ const AppBox = ({app}: {app: UserAppType}) => {
5753
);
5854
};
5955

60-
const renderLinks = (app: UserAppType) => {
56+
const renderLinks = (app: ShowcaseApp) => {
6157
const links = [
6258
app.linkAppStore ? (
6359
<a key="ios" href={app.linkAppStore} target="_blank">
@@ -92,15 +88,17 @@ const renderLinks = (app: UserAppType) => {
9288
return <p className="showcaseLinks">{links}</p>;
9389
};
9490

95-
const randomizeApps = apps =>
91+
const randomizeApps = (apps: ShowcaseApp[]) =>
9692
[...apps].filter(app => !app.group).sort(() => 0.5 - Math.random());
9793

9894
const Showcase = () => {
9995
const {siteConfig} = useDocusaurusContext();
10096
const {meta, microsoft, shopify, wix, amazon, others} = siteConfig
101-
.customFields.users as typeof users;
102-
const [pinnedRandomizedApps, setPinnedRandomizedApps] = useState([]);
103-
const [randomizedApps, setRandomizedApps] = useState([]);
97+
.customFields.users as ShowcaseData;
98+
const [pinnedRandomizedApps, setPinnedRandomizedApps] = useState<
99+
ShowcaseApp[]
100+
>([]);
101+
const [randomizedApps, setRandomizedApps] = useState<ShowcaseApp[]>([]);
104102

105103
useEffect(() => {
106104
setRandomizedApps(randomizeApps(others.filter(app => !app.pinned)));
@@ -140,7 +138,11 @@ const Showcase = () => {
140138
Meta’s product ecosystem, from Facebook Marketplace, Messenger
141139
Desktop, Ads Manager to the Meta Quest app and many more.
142140
</p>
143-
<div className="logos">{meta.map(renderApp)}</div>
141+
<div className="logos">
142+
{meta.map((app, i) => (
143+
<AppBox app={app} key={`app-${app.name}-${i}`} />
144+
))}
145+
</div>
144146
</div>
145147
<div className="showcaseSection">
146148
<h2 className="withLogo">
@@ -166,7 +168,11 @@ const Showcase = () => {
166168
</a>{' '}
167169
for React Native Windows and macOS.
168170
</p>
169-
<div className="logos">{microsoft.map(renderApp)}</div>
171+
<div className="logos">
172+
{microsoft.map((app, i) => (
173+
<AppBox app={app} key={`app-${app.name}-${i}`} />
174+
))}
175+
</div>
170176
</div>
171177
<div className="showcaseSection">
172178
<h2 className="withLogo">
@@ -185,7 +191,11 @@ const Showcase = () => {
185191
2016. Amazon also uses React Native to support customer-favorite
186192
devices such as the Kindle E-readers.
187193
</p>
188-
<div className="logos">{amazon.map(renderApp)}</div>
194+
<div className="logos">
195+
{amazon.map((app, i) => (
196+
<AppBox app={app} key={`app-${app.name}-${i}`} />
197+
))}
198+
</div>
189199
</div>
190200
<div className="showcaseSection">
191201
<h2 className="withLogo">
@@ -206,7 +216,11 @@ const Showcase = () => {
206216
</a>
207217
.
208218
</p>
209-
<div className="logos">{shopify.map(renderApp)}</div>
219+
<div className="logos">
220+
{shopify.map((app, i) => (
221+
<AppBox app={app} key={`app-${app.name}-${i}`} />
222+
))}
223+
</div>
210224
</div>
211225
<div className="showcaseSection">
212226
<h2 className="withLogo">
@@ -225,13 +239,21 @@ const Showcase = () => {
225239
variety of open source projects. Wix is an early adopter of React
226240
Native and uses it for its entire suite of applications.
227241
</p>
228-
<div className="logos">{wix.map(renderApp)}</div>
242+
<div className="logos">
243+
{wix.map((app, i) => (
244+
<AppBox app={app} key={`app-${app.name}-${i}`} />
245+
))}
246+
</div>
229247
</div>
230248
<div className="showcaseSection showcaseCustomers">
231249
<h2>Users Showcase</h2>
232250
<div className="logos">
233-
{pinnedRandomizedApps.map(renderApp)}
234-
{randomizedApps.map(renderApp)}
251+
{pinnedRandomizedApps.map((app, i) => (
252+
<AppBox app={app} key={`app-${app.name}-${i}`} />
253+
))}
254+
{randomizedApps.map((app, i) => (
255+
<AppBox app={app} key={`app-${app.name}-${i}`} />
256+
))}
235257
</div>
236258
</div>
237259
</Section>

0 commit comments

Comments
 (0)