diff --git a/website/src/components/Home/Community/PartnersShowcase.tsx b/website/src/components/Home/Community/PartnersShowcase.tsx new file mode 100644 index 00000000000..9357613c7de --- /dev/null +++ b/website/src/components/Home/Community/PartnersShowcase.tsx @@ -0,0 +1,68 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {useEffect, useState} from 'react'; + +import CallstackWordmark from '@site/static/img/showcase/callstack_wordmark.svg'; +import ExpoWordmark from '@site/static/img/showcase/expo-wordmark.svg'; +import InfiniteRedWordmark from '@site/static/img/showcase/infinite-red-wordmark.svg'; +import MicrosoftWordmark from '@site/static/img/showcase/microsoft-wordmark.svg'; +import SWMWordmark from '@site/static/img/showcase/swm-wordmark.svg'; +import {PartnerLink} from '@site/src/types'; + +import styles from './styles.module.css'; + +const PARTNERS = [ + { + href: 'https://callstack.com/', + logo: , + }, + { + href: 'https://expo.dev/', + className: styles.expo, + logo: , + }, + { + href: 'https://infinite.red/', + logo: , + }, + { + href: 'https://www.microsoft.com/', + logo: , + }, + { + href: 'https://swmansion.com/', + logo: , + }, +]; + +export default function PartnersShowcase() { + const [partners, setPartners] = useState(PARTNERS); + + useEffect(() => { + setPartners(currentCompanies => shuffleItems(currentCompanies)); + }, []); + + return ( +
+ {partners.map(({href, className, logo}) => ( + + {logo} + + ))} +
+ ); +} + +function shuffleItems(apps: PartnerLink[]) { + return [...apps].sort(() => 0.5 - Math.random()); +} diff --git a/website/src/components/Home/Community/index.tsx b/website/src/components/Home/Community/index.tsx index ce0079a3e4c..15ffa705197 100644 --- a/website/src/components/Home/Community/index.tsx +++ b/website/src/components/Home/Community/index.tsx @@ -7,7 +7,9 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import {ShowcaseData} from '@site/src/types'; +import PartnersShowcase from './PartnersShowcase'; import Section from '../Section'; import SectionTitle from '../SectionTitle'; @@ -15,9 +17,9 @@ import styles from './styles.module.css'; function Community() { const {siteConfig} = useDocusaurusContext(); - const apps = Object.values(siteConfig.customFields.users) + const apps = Object.values(siteConfig.customFields?.users as ShowcaseData) .flat() - .filter(app => app.pinned); + .filter(app => Boolean(app.pinned)); return (
@@ -60,58 +62,15 @@ function Community() {

Meta released React Native in 2015 and has been maintaining it ever - since. Today, React Native is supported by contributions from - individuals and companies around the world including{' '} - - - Callstack - - - ,{' '} - - - Expo - - - ,{' '} - - Infinite Red - - ,{' '} - - Microsoft - {' '} - and{' '} - - Software Mansion - - . If you're interested in learning more, check out{' '} - - how we have structured the ecosystem - - . + since. +
+ Today, React Native is supported by contributions from individuals and + companies around the world including:

+

- Our community is always shipping exciting new projects and expanding - beyond Android and iOS with initiatives like{' '} + Additionally, our community is always shipping exciting new projects + and expanding beyond Android and iOS with initiatives like{' '} React Native Web - .

+ + Learn more about the Ecosystem +
); } diff --git a/website/src/components/Home/Community/styles.module.css b/website/src/components/Home/Community/styles.module.css index 4935464b005..5c9f6d52b81 100644 --- a/website/src/components/Home/Community/styles.module.css +++ b/website/src/components/Home/Community/styles.module.css @@ -53,11 +53,62 @@ } } +.partnersContainer { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr; + align-items: center; + justify-content: center; + gap: 16px; + padding: 20px 0 40px; + + a { + display: flex; + justify-content: center; + color: var(--ifm-heading-color); + + &, + &:hover { + border-bottom: 0 !important; + } + + &.expo svg { + max-width: 130px; + } + } + + svg { + max-width: 142px; + max-height: 56px; + } +} + +html[data-theme="dark"] { + .partnersContainer a { + color: var(--ifm-heading-color) !important; + } +} + +@media only screen and (max-width: 800px) { + .partnersContainer { + grid-template-columns: 1fr 1fr 1fr; + gap: 20px 24px; + } +} + +@media only screen and (max-width: 450px) { + .partnersContainer { + grid-template-columns: 1fr 1fr; + column-gap: 32px; + } +} + .communityNote { - margin-top: 48px; + margin-top: 52px; + margin-bottom: 8px; text-align: center; color: var(--home-secondary-text); padding: 0 12px; + font-size: 0.9rem; } .secondaryButton { diff --git a/website/src/pages/showcase.tsx b/website/src/pages/showcase.tsx index b3584cf43f3..2eb7ba5863a 100644 --- a/website/src/pages/showcase.tsx +++ b/website/src/pages/showcase.tsx @@ -5,28 +5,24 @@ * LICENSE file in the root directory of this source tree. */ -import React, {useEffect, useState} from 'react'; +import {type PropsWithChildren, useEffect, useState} from 'react'; + import useBaseUrl from '@docusaurus/useBaseUrl'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; -import type users from '../../showcase.json'; -import IconExternalLink from '../theme/Icon/ExternalLink'; +import {ShowcaseApp, ShowcaseData} from '@site/src/types'; import ThemedImage from '@theme/ThemedImage'; +import Layout from '@theme/Layout'; -type UserAppType = (typeof users)[keyof typeof users][number]; - -const renderApp = (app: UserAppType, i: number) => ( - -); +import IconExternalLink from '../theme/Icon/ExternalLink'; function Section({ children, background = 'light', -}: React.PropsWithChildren<{background?: 'light' | 'dark'}>) { +}: PropsWithChildren<{background?: 'light' | 'dark'}>) { return
{children}
; } -const AppBox = ({app}: {app: UserAppType}) => { +const AppBox = ({app}: {app: ShowcaseApp}) => { const imgSource = useBaseUrl( app.icon.startsWith('http') ? app.icon : 'img/showcase/' + app.icon ); @@ -57,7 +53,7 @@ const AppBox = ({app}: {app: UserAppType}) => { ); }; -const renderLinks = (app: UserAppType) => { +const renderLinks = (app: ShowcaseApp) => { const links = [ app.linkAppStore ? ( @@ -92,15 +88,17 @@ const renderLinks = (app: UserAppType) => { return

{links}

; }; -const randomizeApps = apps => +const randomizeApps = (apps: ShowcaseApp[]) => [...apps].filter(app => !app.group).sort(() => 0.5 - Math.random()); const Showcase = () => { const {siteConfig} = useDocusaurusContext(); const {meta, microsoft, shopify, wix, amazon, others} = siteConfig - .customFields.users as typeof users; - const [pinnedRandomizedApps, setPinnedRandomizedApps] = useState([]); - const [randomizedApps, setRandomizedApps] = useState([]); + .customFields.users as ShowcaseData; + const [pinnedRandomizedApps, setPinnedRandomizedApps] = useState< + ShowcaseApp[] + >([]); + const [randomizedApps, setRandomizedApps] = useState([]); useEffect(() => { setRandomizedApps(randomizeApps(others.filter(app => !app.pinned))); @@ -140,7 +138,11 @@ const Showcase = () => { Meta’s product ecosystem, from Facebook Marketplace, Messenger Desktop, Ads Manager to the Meta Quest app and many more.

-
{meta.map(renderApp)}
+
+ {meta.map((app, i) => ( + + ))} +

@@ -166,7 +168,11 @@ const Showcase = () => { {' '} for React Native Windows and macOS.

-
{microsoft.map(renderApp)}
+
+ {microsoft.map((app, i) => ( + + ))} +

@@ -185,7 +191,11 @@ const Showcase = () => { 2016. Amazon also uses React Native to support customer-favorite devices such as the Kindle E-readers.

-
{amazon.map(renderApp)}
+
+ {amazon.map((app, i) => ( + + ))} +

@@ -206,7 +216,11 @@ const Showcase = () => { .

-
{shopify.map(renderApp)}
+
+ {shopify.map((app, i) => ( + + ))} +

@@ -225,13 +239,21 @@ const Showcase = () => { variety of open source projects. Wix is an early adopter of React Native and uses it for its entire suite of applications.

-
{wix.map(renderApp)}
+
+ {wix.map((app, i) => ( + + ))} +

Users Showcase

- {pinnedRandomizedApps.map(renderApp)} - {randomizedApps.map(renderApp)} + {pinnedRandomizedApps.map((app, i) => ( + + ))} + {randomizedApps.map((app, i) => ( + + ))}
diff --git a/website/src/theme/Icon/ExternalLink/index.tsx b/website/src/theme/Icon/ExternalLink/index.tsx index c82abadf2a7..d423dc7eee9 100644 --- a/website/src/theme/Icon/ExternalLink/index.tsx +++ b/website/src/theme/Icon/ExternalLink/index.tsx @@ -26,17 +26,17 @@ export default function IconExternalLink({ y2="64" fill="none" stroke="currentColor" - stroke-linecap="round" - stroke-linejoin="round" - stroke-width="16" + strokeLinecap="round" + strokeLinejoin="round" + strokeWidth="16" /> ); diff --git a/website/src/types/index.d.ts b/website/src/types/index.d.ts new file mode 100644 index 00000000000..bad93b08af5 --- /dev/null +++ b/website/src/types/index.d.ts @@ -0,0 +1,9 @@ +export type ShowcaseApp = (typeof users)[keyof typeof users][number]; + +export type ShowcaseData = Record; + +export type PartnerLink = { + href: string; + className?: string; + logo: ReactNode; +}; diff --git a/website/static/img/showcase/callstack_wordmark.svg b/website/static/img/showcase/callstack_wordmark.svg new file mode 100644 index 00000000000..b94c7f3e6e6 --- /dev/null +++ b/website/static/img/showcase/callstack_wordmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/website/static/img/showcase/expo-wordmark.svg b/website/static/img/showcase/expo-wordmark.svg new file mode 100644 index 00000000000..62fe56891b1 --- /dev/null +++ b/website/static/img/showcase/expo-wordmark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/website/static/img/showcase/infinite-red-wordmark.svg b/website/static/img/showcase/infinite-red-wordmark.svg new file mode 100644 index 00000000000..01b71f28dd0 --- /dev/null +++ b/website/static/img/showcase/infinite-red-wordmark.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/static/img/showcase/microsoft-wordmark.svg b/website/static/img/showcase/microsoft-wordmark.svg new file mode 100644 index 00000000000..e8c71b399e8 --- /dev/null +++ b/website/static/img/showcase/microsoft-wordmark.svg @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/website/static/img/showcase/swm-wordmark.svg b/website/static/img/showcase/swm-wordmark.svg new file mode 100644 index 00000000000..c745750fac1 --- /dev/null +++ b/website/static/img/showcase/swm-wordmark.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file