diff --git a/.gitignore b/.gitignore index d8bec488b..7bf71dbc5 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,6 @@ yarn-error.log* # external fonts public/fonts/**/Optimistic_*.woff2 + +# rss +public/rss.xml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e861af35..4c7e5ec74 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,6 +79,7 @@ Ignore this rule if you're specifically describing an experimental proposal. Mak - Use semicolons. - No space between function names and parens (`method() {}` not `method () {}`). - When in doubt, use the default style favored by [Prettier](https://prettier.io/playground/). +- Always capitalize React concepts such as Hooks, Effects, and Transitions. ### Highlighting diff --git a/colors.js b/colors.js index acf8214ee..872f33cac 100644 --- a/colors.js +++ b/colors.js @@ -11,7 +11,7 @@ module.exports = { tertiary: '#5E687E', // gray-50 'tertiary-dark': '#99A1B3', // gray-30 link: '#087EA4', // blue-50 - 'link-dark': '#149ECA', // blue-40 + 'link-dark': '#58C4DC', // blue-40 syntax: '#EBECF0', // gray-10 wash: '#FFFFFF', 'wash-dark': '#23272F', // gray-90 @@ -23,6 +23,8 @@ module.exports = { 'border-dark': '#343A46', // gray-80 'secondary-button': '#EBECF0', // gray-10 'secondary-button-dark': '#404756', // gray-70 + brand: '#087EA4', // blue-40 + 'brand-dark': '#58C4DC', // blue-40 // Gray 'gray-95': '#16181D', diff --git a/package.json b/package.json index 274c2506e..26bb39657 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,15 @@ "prettier:diff": "yarn nit:source", "lint-heading-ids": "node scripts/headingIdLinter.js", "fix-headings": "node scripts/headingIdLinter.js --fix", - "ci-check": "npm-run-all prettier:diff --parallel lint tsc lint-heading-ids", + "ci-check": "npm-run-all prettier:diff --parallel lint tsc lint-heading-ids rss", "tsc": "tsc --noEmit", "start": "next start", "postinstall": "patch-package && (is-ci || husky install .husky)", - "check-all": "npm-run-all prettier lint:fix tsc" + "check-all": "npm-run-all prettier lint:fix tsc rss", + "rss": "node scripts/generateRss.js" }, "dependencies": { - "@codesandbox/sandpack-react": "2.13.1", + "@codesandbox/sandpack-react": "2.13.5", "@docsearch/css": "3.0.0-alpha.41", "@docsearch/react": "3.0.0-alpha.41", "@headlessui/react": "^1.7.0", @@ -97,7 +98,7 @@ "webpack-bundle-analyzer": "^4.5.0" }, "engines": { - "node": "^16.8.0 || ^18.0.0 || ^19.0.0 || ^20.0.0" + "node": ">=16.8.0" }, "nextBundleAnalysis": { "budget": null, diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 000000000..5de701e13 Binary files /dev/null and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-384x384.png b/public/android-chrome-384x384.png new file mode 100644 index 000000000..f42a6776e Binary files /dev/null and b/public/android-chrome-384x384.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png new file mode 100644 index 000000000..2fdbf6902 Binary files /dev/null and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 000000000..baf1332a3 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/browserconfig.xml b/public/browserconfig.xml new file mode 100644 index 000000000..f9c2e67fe --- /dev/null +++ b/public/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #2b5797 + + + diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 000000000..d24cb4f76 Binary files /dev/null and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 000000000..953ae4cc3 Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico index 38fd8641c..519b939a0 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/favicon_old.ico b/public/favicon_old.ico new file mode 100644 index 000000000..20b59d440 Binary files /dev/null and b/public/favicon_old.ico differ diff --git a/public/images/team/jack-pope.jpg b/public/images/team/jack-pope.jpg new file mode 100644 index 000000000..601e5840e Binary files /dev/null and b/public/images/team/jack-pope.jpg differ diff --git a/public/images/team/lauren.jpg b/public/images/team/lauren.jpg index 1485cf8ff..cb08b9725 100644 Binary files a/public/images/team/lauren.jpg and b/public/images/team/lauren.jpg differ diff --git a/public/images/team/lesiutin.jpg b/public/images/team/lesiutin.jpg new file mode 100644 index 000000000..edfc942e0 Binary files /dev/null and b/public/images/team/lesiutin.jpg differ diff --git a/public/images/uwu.png b/public/images/uwu.png new file mode 100644 index 000000000..a09d245ea Binary files /dev/null and b/public/images/uwu.png differ diff --git a/public/mstile-150x150.png b/public/mstile-150x150.png new file mode 100644 index 000000000..d36e7ee9e Binary files /dev/null and b/public/mstile-150x150.png differ diff --git a/public/safari-pinned-tab.svg b/public/safari-pinned-tab.svg new file mode 100644 index 000000000..7e4874b2f --- /dev/null +++ b/public/safari-pinned-tab.svg @@ -0,0 +1,60 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 000000000..337446d52 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "React", + "short_name": "React", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-384x384.png", + "sizes": "384x384", + "type": "image/png" + } + ], + "theme_color": "#23272f", + "background_color": "#23272f", + "display": "standalone" +} diff --git a/scripts/generateRss.js b/scripts/generateRss.js new file mode 100644 index 000000000..e0f3d5561 --- /dev/null +++ b/scripts/generateRss.js @@ -0,0 +1,6 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + */ +const {generateRssFeed} = require('../src/utils/rss'); + +generateRssFeed(); diff --git a/src/components/ButtonLink.tsx b/src/components/ButtonLink.tsx index 15ab83f2b..23c971756 100644 --- a/src/components/ButtonLink.tsx +++ b/src/components/ButtonLink.tsx @@ -26,7 +26,8 @@ function ButtonLink({ className, 'active:scale-[.98] transition-transform inline-flex font-bold items-center outline-none focus:outline-none focus-visible:outline focus-visible:outline-link focus:outline-offset-2 focus-visible:dark:focus:outline-link-dark leading-snug', { - 'bg-link text-white hover:bg-opacity-80': type === 'primary', + 'bg-link text-white dark:bg-brand-dark dark:text-secondary hover:bg-opacity-80': + type === 'primary', 'text-primary dark:text-primary-dark shadow-secondary-button-stroke dark:shadow-secondary-button-stroke-dark hover:bg-gray-40/5 active:bg-gray-40/10 hover:dark:bg-gray-60/5 active:dark:bg-gray-60/10': type === 'secondary', 'text-lg py-3 rounded-full px-4 sm:px-6': size === 'lg', diff --git a/src/components/Icon/IconCanary.tsx b/src/components/Icon/IconCanary.tsx index a7782b141..7f584fed7 100644 --- a/src/components/Icon/IconCanary.tsx +++ b/src/components/Icon/IconCanary.tsx @@ -4,29 +4,35 @@ import {memo} from 'react'; -export const IconCanary = memo( - function IconCanary({className, title}) { - return ( - - {title && {title}} - - - - - - - ); +export const IconCanary = memo< + JSX.IntrinsicElements['svg'] & {title?: string; size?: 's' | 'md'} +>(function IconCanary( + {className, title, size} = { + className: undefined, + title: undefined, + size: 'md', } -); +) { + return ( + + {title && {title}} + + + + + + + ); +}); diff --git a/src/components/Layout/Footer.tsx b/src/components/Layout/Footer.tsx index 26bdf6711..5bcf9df98 100644 --- a/src/components/Layout/Footer.tsx +++ b/src/components/Layout/Footer.tsx @@ -285,6 +285,30 @@ export function Footer() { dir="ltr"> ©{new Date().getFullYear()} +
{ + // @ts-ignore + window.__setUwu(false); + }}> + no uwu plz +
+
{ + // @ts-ignore + window.__setUwu(true); + }}> + uwu? +
+
+ Logo by + + @sawaratsuki1004 + +
diff --git a/src/components/Layout/HomeContent.js b/src/components/Layout/HomeContent.js index e1fab6d71..72ab36884 100644 --- a/src/components/Layout/HomeContent.js +++ b/src/components/Layout/HomeContent.js @@ -26,6 +26,8 @@ import Link from 'components/MDX/Link'; import CodeBlock from 'components/MDX/CodeBlock'; import {ExternalLink} from 'components/ExternalLink'; import sidebarBlog from '../../sidebarBlog.json'; +import * as React from 'react'; +import Image from 'next/image'; function Section({children, background = null}) { return ( @@ -115,12 +117,22 @@ export function HomeContent() { <>
+
+ logo by @sawaratsuki1004 +
-

+

React

@@ -489,7 +501,15 @@ export function HomeContent() {

- +
+ logo by @sawaratsuki1004 +
+
Welcome to the
React community @@ -1620,7 +1640,7 @@ function Thumbnail({video}) {
- + React Conf
diff --git a/src/components/Layout/Page.tsx b/src/components/Layout/Page.tsx index ee3c899d0..24d379589 100644 --- a/src/components/Layout/Page.tsx +++ b/src/components/Layout/Page.tsx @@ -8,19 +8,19 @@ import {useRouter} from 'next/router'; import {SidebarNav} from './SidebarNav'; import {Footer} from './Footer'; import {Toc} from './Toc'; -import SocialBanner from '../SocialBanner'; +// import SocialBanner from '../SocialBanner'; import {DocsPageFooter} from 'components/DocsFooter'; import {Seo} from 'components/Seo'; -import ButtonLink from 'components/ButtonLink'; -import {IconNavArrow} from 'components/Icon/IconNavArrow'; import PageHeading from 'components/PageHeading'; import {getRouteMeta} from './getRouteMeta'; import {TocContext} from '../MDX/TocContext'; +import {Languages, LanguagesContext} from '../MDX/LanguagesContext'; import type {TocItem} from 'components/MDX/TocContext'; import type {RouteItem} from 'components/Layout/getRouteMeta'; import {HomeContent} from './HomeContent'; import {TopNav} from './TopNav'; import cn from 'classnames'; +import Head from 'next/head'; import(/* webpackPrefetch: true */ '../MDX/CodeBlock/CodeBlock'); @@ -35,9 +35,17 @@ interface PageProps { description?: string; }; section: 'learn' | 'reference' | 'community' | 'blog' | 'home' | 'unknown'; + languages?: Languages | null; } -export function Page({children, toc, routeTree, meta, section}: PageProps) { +export function Page({ + children, + toc, + routeTree, + meta, + section, + languages = null, +}: PageProps) { const {asPath} = useRouter(); const cleanedPath = asPath.split(/[\?\#]/)[0]; const {route, nextRoute, prevRoute, breadcrumbs, order} = getRouteMeta( @@ -74,7 +82,11 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) { 'max-w-7xl mx-auto', section === 'blog' && 'lg:flex lg:flex-col lg:items-center' )}> - {children} + + + {children} + +
{!isBlogIndex && ( - + {(isHomePage || isBlogIndex) && ( + + + + )} + {/**/} {!isHomePage && (
- { -
- } - {showSurvey && ( - <> -
-

- How do you like these docs? -

-
- - Take our survey! - - -
-
-
- - )} +
)}
+ {index !== 0 && (
  • - {sectionHeader} + {sectionHeaderText} ); diff --git a/src/components/Layout/TopNav/TopNav.tsx b/src/components/Layout/TopNav/TopNav.tsx index b6e276ff7..921d2102c 100644 --- a/src/components/Layout/TopNav/TopNav.tsx +++ b/src/components/Layout/TopNav/TopNav.tsx @@ -10,6 +10,7 @@ import { startTransition, Suspense, } from 'react'; +import Image from 'next/image'; import * as React from 'react'; import cn from 'classnames'; import NextLink from 'next/link'; @@ -24,6 +25,7 @@ import {Logo} from '../../Logo'; import {Feedback} from '../Feedback'; import {SidebarRouteTree} from '../Sidebar'; import type {RouteItem} from '../getRouteMeta'; +import {siteConfig} from 'siteConfig'; declare global { interface Window { @@ -77,6 +79,19 @@ const lightIcon = ( ); +const languageIcon = ( + + + +); + const githubIcon = ( (null); const {asPath} = useRouter(); - const [isScrolled, setIsScrolled] = useState(false); // HACK. Fix up the data structures instead. if ((routeTree as any).routes.length === 1) { @@ -154,18 +170,18 @@ export default function TopNav({ // While the overlay is open, disable body scroll. useEffect(() => { - if (isOpen) { + if (isMenuOpen) { const preferredScrollParent = scrollParentRef.current!; disableBodyScroll(preferredScrollParent); return () => enableBodyScroll(preferredScrollParent); } else { return undefined; } - }, [isOpen]); + }, [isMenuOpen]); // Close the overlay on any navigation. useEffect(() => { - setIsOpen(false); + setIsMenuOpen(false); }, [asPath]); // Also close the overlay if the window gets resized past mobile layout. @@ -175,7 +191,7 @@ export default function TopNav({ function closeIfNeeded() { if (!media.matches) { - setIsOpen(false); + setIsMenuOpen(false); } } @@ -204,7 +220,6 @@ export default function TopNav({ return () => observer.disconnect(); }, []); - const [showSearch, setShowSearch] = useState(false); const onOpenSearch = useCallback(() => { startTransition(() => { setShowSearch(true); @@ -224,39 +239,61 @@ export default function TopNav({
    - {isOpen && ( + {isMenuOpen && (