Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync with react.dev @ 9aa2e366 #90

Open
wants to merge 175 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
175 commits
Select commit Hold shift + click to select a range
47c818c
feat (conferences) add react connection Paris (#6609)
Feb 5, 2024
c118938
Fix SandpackWithHTMLOutput to use src dir (#6613)
mattcarrollcode Feb 6, 2024
9a843b6
Add React Conf banner (#6595)
mattcarrollcode Feb 8, 2024
6d43bff
Fix scrollbar of SidebarNav to make it tappable (#6586)
tamonmon0417 Feb 10, 2024
6ae9922
Update index.md (#6622)
drex44 Feb 11, 2024
4ff80a5
Fix broken link (#6619)
lakshmi930 Feb 11, 2024
d46c360
Fix CSS discrepancy in issue #6508 (#6509)
hidaviddong Feb 11, 2024
bb3a0f5
Fix some typos (#6478)
romain-trotard Feb 11, 2024
a21a942
Fix typo (#6628)
0ldh Feb 14, 2024
2c4f382
Blog: What We've Been Working On – February 2024 (#6629)
rickhanlonii Feb 15, 2024
c1039b3
minor fixes from #6629 (#6630)
rickhanlonii Feb 15, 2024
9d3fc07
tweaks (#6631)
rickhanlonii Feb 15, 2024
bce6e55
Add warning page for RTR deprecation (#6632)
jackpope Feb 15, 2024
b66dece
Update react-labs-what-we-have-been-working-on-february-2024.md
sophiebits Feb 15, 2024
c608570
[blog] labs 2024 - minor grammer fix
mattcarrollcode Feb 16, 2024
1c06fcc
Update conferences.md to include Chain React 2024 (#6640)
robinheinze Feb 17, 2024
74c33a1
Fix typos in latest blog post (#6636)
stephan281094 Feb 17, 2024
156765f
Fix localhost link in script documentation (#6642)
devongovett Feb 17, 2024
35530ee
[typo] syntax looks wrong #6633 (#6641)
felipe-b-oliveira Feb 18, 2024
c9369f4
feat(conferences): add React Universe Conf 2024 (#6649)
szymonrybczak Feb 20, 2024
e16634a
Add options to call signature of react-dom/server legacy APIs (#6477)
eps1lon Feb 20, 2024
af289c3
Update team page (#6652)
josephsavona Feb 20, 2024
5398b47
Add React Alicante to conferences.md (#6655)
VictoriaQ Feb 21, 2024
93aec27
Remove redundant suggestion (#6643)
tomaszwysocki Feb 21, 2024
2ad51d9
feat(conferences): add The GeekConf 2024 (#6654)
apherio Feb 23, 2024
a853e69
Remove useMemo from useFormStatus example (#6658)
rickhanlonii Feb 24, 2024
081d100
fix(sandpack): clear up bundler timeout when there's a syntax error (…
danilowoz Feb 24, 2024
9ceb057
Revert "fix(sandpack): clear up bundler timeout when there's a syntax…
harish-sethuraman Feb 26, 2024
41b1bb3
Update Dan's twitter link
gaearon Feb 26, 2024
6d8e094
fix: Update @codesandbox/sandpack-react version to 2.13.4 (#6664)
danilowoz Feb 27, 2024
6e650f9
update: "Configuring TypeScript" link for Next.js App Directory - to …
tomihq Feb 29, 2024
6310c8a
Add /link redirects (#6670)
rickhanlonii Mar 1, 2024
265fa26
Update small typo in useDeferredValue.md (#6673)
ninjaPixel Mar 3, 2024
716e889
Add hydration-mismatch link (#6678)
rickhanlonii Mar 4, 2024
5de8519
fix: Update sandpack-react version to 2.13.5 (#6668)
danilowoz Mar 8, 2024
aa31fe5
Add details about shallow renderer warning (#6689)
jackpope Mar 11, 2024
1a839ff
Remove links to localhost (#6696)
poteto Mar 14, 2024
0dc1b31
Add initial Rules of React docs (#6680)
poteto Mar 15, 2024
f55d948
Reorder rules of react summary in reference index (#6698)
poteto Mar 15, 2024
ef3a7ea
Fix typos in typescript.md (#6439)
pavelsavva Mar 19, 2024
5a45b53
Fix hover styles in strictmode docs (#6705)
rickhanlonii Mar 23, 2024
9c04f9b
Correct pluralization of 'covers' (#6702)
allison-strandberg Mar 23, 2024
7bdbab1
Fix missing id properties in docs example (#6395)
jpayoung Mar 24, 2024
d661678
Update @eps1lon's job title (#6710)
poteto Mar 25, 2024
4df3124
Fix caps for React concepts (#6712)
rickhanlonii Mar 27, 2024
2aa9594
Add warning page for ReactDOMTestUtils deprecation (#6716)
eps1lon Mar 27, 2024
9b4de7c
Add Jack to team page (#6721)
rickhanlonii Mar 28, 2024
6436bd9
Fix typo in components-and-hooks-must-be-pure.md (#6724)
rivea0 Mar 29, 2024
3076795
chore: fix typos (#6723)
ahmoin Mar 29, 2024
9748943
Update Node.js version in engines into package.json file (^21.0.0) (#…
foridpathan Mar 31, 2024
712556c
Fix inconsistent link underline on hover (#6731)
poteto Apr 2, 2024
93177e6
fix(rules-of-react): "everytime" -> "every time" (#6737)
SiarheiBobryk Apr 6, 2024
a7103d8
Add Ruslan to team page (#6738)
rickhanlonii Apr 8, 2024
11a7479
Fixes #6693: fixes search functionality on iOS devices (#6743)
ramizackaryshamir Apr 10, 2024
342fddb
Revert inappropriate capitalization of "Transition" (#6746)
smikitky Apr 10, 2024
db2dc7f
Add docs for onCaughtError and onUncaughtError (#6742)
rickhanlonii Apr 11, 2024
2749eb4
Update link to nearestnabors.com (#6754)
jackpope Apr 15, 2024
56ca8f1
[easy] remove unused ref in ExpandableCallout.tsx (#6755)
kassens Apr 15, 2024
c2180a3
fix issue #6734 (#6735)
wheeler6123 Apr 17, 2024
37a8d64
Update SocialBanner.tsx (#6763)
kassens Apr 19, 2024
07cbd00
API docs for useDeferredValue's initialValue (#6747)
acdlite Apr 22, 2024
f8afd94
Add /link/new-jsx-transform (#6772)
rickhanlonii Apr 24, 2024
cdd2fdd
Add documentation for ref cleanup functions (#6770)
jackpope Apr 24, 2024
9fb2f0d
Move `use` to APIs (#6774)
kassens Apr 24, 2024
4f55010
Rename useFormState to useActionState (#6776)
kassens Apr 25, 2024
191852a
Add blog posts for React 19 Beta (#6778)
rickhanlonii Apr 25, 2024
412b733
Blog post nits (#6779)
rickhanlonii Apr 25, 2024
c8a316a
Blog typo
rickhanlonii Apr 25, 2024
0078b50
React19 blog post typos (#6780)
Zeko369 Apr 25, 2024
317dcf3
Fix code example in React-19 `useOptimistic` section (#6781)
gnoff Apr 25, 2024
9afcbf6
[React19-blog]: Make use(context) example easier to understand (#6783)
Zeko369 Apr 25, 2024
9aa8e82
refines the messaging to clarify that Server Components the feature i…
gnoff Apr 25, 2024
cdd0964
Fix react-helmet link (#6786)
gnoff Apr 25, 2024
526d7b4
Clarify React DOM APIs in React 19 Post (#6785)
rickhanlonii Apr 25, 2024
64beb65
Resources -> resources (#6787)
gnoff Apr 25, 2024
8cbed3e
Fix typos (#6788)
dom-zhu Apr 25, 2024
e09ff1c
Better use(Context) example in 19 blog (#6789)
rickhanlonii Apr 26, 2024
e45ac55
Better use(Promise) example in 19 blog (#6790)
rickhanlonii Apr 26, 2024
057f35c
Replaced all instances of /react to /rsc (#6797)
srikanth-kandi Apr 26, 2024
f664028
Updated react-19.md (#6796)
cbmongithub Apr 26, 2024
cf53cb5
Add rss feed (#6803)
rickhanlonii Apr 26, 2024
bc1020a
Update me
poteto Apr 26, 2024
845a281
Add redirects for moved rsc pages (#6800)
eps1lon Apr 26, 2024
807001c
chore: fix typo (#6791)
ChiaJune Apr 26, 2024
537bd05
to make examples consistent. (#6793)
Shubhdeep12 Apr 26, 2024
8c1c6e3
Add meta task for rss auto-discovery (#6805)
rickhanlonii Apr 26, 2024
01edd5c
Upgrade guide should recommend installing types `@beta` (#6806)
eps1lon Apr 26, 2024
9c53b48
Remove useless async (#6809)
Brooooooklyn Apr 29, 2024
3981ffe
Add versions page and nav version (#6814)
rickhanlonii Apr 30, 2024
86d306f
rm new redirects (#6816)
rickhanlonii Apr 30, 2024
6d0aca1
Fix punctuation. (#6815)
toocomputer Apr 30, 2024
e538800
Update react-19.md (#6813)
harish-sethuraman Apr 30, 2024
1df378f
uwu (#6817)
rickhanlonii Apr 30, 2024
3dd67d1
Fix type issues with `useActionState` docs (#6798)
eps1lon Apr 30, 2024
6f5ee38
uwu - add alt and instructions for turning off
rickhanlonii Apr 30, 2024
74697fb
fix uwu flicker (#6820)
rickhanlonii Apr 30, 2024
7062b8d
Update server-components.md - typo (#6823)
mootookoi May 1, 2024
bdb0d26
add uww toggle (#6824)
rickhanlonii May 1, 2024
0dbd67a
Add React Rally 2024 to conferences (#6819)
mzabriskie May 1, 2024
9e1f5cd
Add "Languages" navigation and article (#6382)
smikitky May 1, 2024
a2f8ff3
fix brand colors (#6826)
rickhanlonii May 1, 2024
a6450b9
Update uwu logo (#6827)
poteto May 2, 2024
e69ec58
rm survey and fix old links (#6828)
rickhanlonii May 2, 2024
d4a9a76
Fix typo in server-components.md (#6829)
seanWLawrence May 3, 2024
0e1ff1a
Fix React 19 upgrade guide typo (#6830)
Ryczko May 3, 2024
556063b
Add a redirect entry for feed.xml => rss.xml (#6836)
flexdinesh May 5, 2024
1fa2057
Update react-19.md (#6838)
HomyeeKing May 6, 2024
46437c2
Add missing period to React v18.0 blog post (#6842)
jackspiva May 7, 2024
0b9ae66
Add docs for useRef no no (#6846)
rickhanlonii May 9, 2024
f1b0f86
Fix typo on tutorial-tic-tac-toe.md (#6843)
skoryky May 10, 2024
f9b9b66
Fix #6852: navigation link fix (#6853)
Rekl0w May 10, 2024
4f1d985
Update synchronizing-with-effects.md (#6856)
segmentationfaulter May 10, 2024
b7bf6c1
Fix Node.js version update at `package.json` (#6855)
Rekl0w May 10, 2024
a81e415
Change React dependency version in <form> page fix (#6858)
includerajat May 13, 2024
f053b53
Update team.md: Jason Bonta (#6862)
jbonta May 14, 2024
e0c667f
Add React Compiler Docs (#6869)
rickhanlonii May 15, 2024
fa19b7f
compiler playground link
jbonta May 15, 2024
8d69e6e
Clearer rule severity for React Compiler eslint plugin (#6870)
spanishpear May 16, 2024
4e3d63a
Fix typos in React Compiler guide (#6875)
denniskigen May 17, 2024
3a46a6e
Update instructions for setting up the React Compiler in Next.js (#6877)
timneutkens May 17, 2024
70a7b64
Update export of next.config.js (#6878)
timneutkens May 17, 2024
ee068ac
Update separating-events-from-effects.md (#6880)
officialkidmax May 19, 2024
8bb3eb3
Fix typo (spreadsheet => stylesheet) (#6750)
smikitky May 19, 2024
e7c52aa
add frontend nation conference (#6866)
danielkellyio May 19, 2024
9967ded
Fix the order of the returns of useActionState (#6864)
yousefelgoharyx May 19, 2024
0dc72f6
Rm dupe blog description (#6885)
rickhanlonii May 20, 2024
05c9d77
typo: spell check (#6892)
TheRakeshPurohit May 21, 2024
bc43b95
End ReactConf banner (#6893)
rickhanlonii May 21, 2024
beefa06
docs: format src/content/blog/2024/04/25/react-19.md (#6883)
kiner-tang May 21, 2024
80d30d7
navitem-css-change (#6888)
ohe1013 May 21, 2024
adb3bed
Update react-compiler docs (#6898)
poteto May 21, 2024
4eb0850
fixed typo in synchronizing-with-effects.md (#6899)
emmanueposu May 22, 2024
59a2739
Add React Conf 2024 Recap post (#6886)
rickhanlonii May 22, 2024
f055f8f
Fix recap blog video links (#6902)
rickhanlonii May 22, 2024
bb96306
Add codemods to upgrade guide (#6897)
rickhanlonii May 23, 2024
68c0f85
s/beta/rc (#6906)
rickhanlonii May 23, 2024
a25bd4b
Clarify precedence is arbitrary valued (#6908)
gnoff May 23, 2024
69b95a6
Add /warnings/version-mismatch (#6909)
rickhanlonii May 24, 2024
ef23197
Clarify useEffect caveats (#6910)
rickhanlonii May 24, 2024
c3bc5af
FIX: Typo in useEffect.md caveats (#6911)
rachitiitr May 25, 2024
12fca4c
Add act documentation (#6901)
jackpope May 28, 2024
ad1a5c2
docs: update links @testing-library/react-native (#6916)
germanolira May 29, 2024
b12743c
Add more codemods (#6921)
rickhanlonii May 29, 2024
438ee7a
Update to CodePen URL (#6452)
chriscoyier Jun 11, 2024
c116c42
Remove mention of Suspensey `<script />` (#6945)
eps1lon Jun 12, 2024
04b5d44
Small typo - Update cache.md (#6935)
kasperaamodt Jun 12, 2024
73a8d9c
Update preinit.md 📜 (#6938)
sanjaiyan-dev Jun 12, 2024
c36bd39
docs(api-act): api act parts word error (#6939)
yaolifeng0629 Jun 12, 2024
f1bdfa2
Recommend installing exact RC (#6944)
eps1lon Jun 12, 2024
56df8af
rearrange conferences (#6952)
harish-sethuraman Jun 14, 2024
3997808
Update react-compiler.md (#6965)
dusanmarsa Jun 18, 2024
169d5c1
Add branding context menu (#6986)
rickhanlonii Jun 20, 2024
dc08860
Add React Brussels 2024 and React Africa 2024 (#6990)
AymenBenAmor Jun 24, 2024
4eacc73
Remove uwuQueryParam console.log (#6993)
mattcarrollcode Jun 24, 2024
e9d2c63
Update compiler docs for Expo apps (#7000)
poteto Jun 28, 2024
53fbed3
Add Chennai React meetup (#7004)
Nikhil-Kumaran Jun 30, 2024
1a3a3ef
fix: Correct reference to sandboxed file App.js in challenge (#7010)
ichistmeinname Jul 4, 2024
2a2e02f
Update compiler docs for Rspack and Rsbuild apps (#7031)
chenjiahan Jul 5, 2024
4c91abc
Update /link/legacy-context to removal blog post (#7047)
kassens Jul 10, 2024
de726d2
Update verb usage in sentence (#7070)
ryanjbonnell Jul 20, 2024
6274d4f
docs: Add RenderCon Kenya 2024 conference (#6914)
orama254 Jul 20, 2024
6671ba7
Document behaviour of setting state inside `useLayoutEffect` (#7096)
OliverJAsh Aug 7, 2024
2bfa7a6
Update compiler docs installation instructions (#7095)
poteto Aug 8, 2024
a220bb3
docs: replace check mark emoji to check mark button emoji (#7121)
k35o Aug 22, 2024
b5f28b4
Redirect lists-and-keys to rendering-lists describing key (#7120)
BartoszKlonowski Aug 23, 2024
7d50c3f
Emphasize the second problem paragraph with chain of effects example …
BartoszKlonowski Aug 25, 2024
50004fa
Adds React Advanced London 2024 (#7127)
PixelsCommander Aug 26, 2024
40d7349
Parallel structure
sophiebits Aug 29, 2024
c2d6131
Fix typo 'bulit' -> 'built' (#7138)
tveastman Sep 1, 2024
391dadb
Fix typos in lazy.md and cache.md (#7141)
kihyeoon Sep 2, 2024
cd923d6
Update conferences.md to move the past conferences lower (#7130)
JiashengWu Sep 6, 2024
2c06272
add React Day Berlin 2024 to conferences.md (#7137)
McFrid Sep 6, 2024
60ef58c
Update conferences.md, add conference (#7135)
OlegKomissarov Sep 6, 2024
9aa2e36
Changed the documentation of the subscribe argument to a more accurat…
Tinttori Sep 8, 2024
763a38d
merging all conflicts
react-translations-bot Sep 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -36,3 +36,6 @@ yarn-error.log*

# external fonts
public/fonts/**/Optimistic_*.woff2

# rss
public/rss.xml
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -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

4 changes: 3 additions & 1 deletion colors.js
Original file line number Diff line number Diff line change
@@ -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',
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -15,17 +15,19 @@
"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.6.0",
"@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",
"@radix-ui/react-context-menu": "^2.1.5",
"body-scroll-lock": "^3.1.3",
"classnames": "^2.2.6",
"date-fns": "^2.16.1",
@@ -97,7 +99,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,
Binary file added public/android-chrome-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/android-chrome-384x384.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/android-chrome-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions public/browserconfig.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#2b5797</TileColor>
</tile>
</msapplication>
</browserconfig>
Binary file added public/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/favicon.ico
Binary file not shown.
Binary file added public/favicon_old.ico
Binary file not shown.
12 changes: 12 additions & 0 deletions public/images/brand/logo_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions public/images/brand/logo_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions public/images/brand/wordmark_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions public/images/brand/wordmark_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/team/jack-pope.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/team/lauren.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/team/lesiutin.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/uwu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/mstile-150x150.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions public/safari-pinned-tab.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions public/site.webmanifest
Original file line number Diff line number Diff line change
@@ -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"
}
6 changes: 6 additions & 0 deletions scripts/generateRss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/
const {generateRssFeed} = require('../src/utils/rss');

generateRssFeed();
3 changes: 2 additions & 1 deletion src/components/ButtonLink.tsx
Original file line number Diff line number Diff line change
@@ -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',
56 changes: 31 additions & 25 deletions src/components/Icon/IconCanary.tsx
Original file line number Diff line number Diff line change
@@ -4,29 +4,35 @@

import {memo} from 'react';

export const IconCanary = memo<JSX.IntrinsicElements['svg'] & {title?: string}>(
function IconCanary({className, title}) {
return (
<svg
className={className}
width="20px"
height="20px"
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg">
{title && <title>{title}</title>}
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<g
id="noun-labs-1201738-(2)"
transform="translate(2, 0)"
fill="currentColor"
fillRule="nonzero">
<path
d="M10.2865804,5.55665262 L10.2865804,2.22331605 L10.8591544,2.22331605 C11.0103911,2.22244799 11.1551447,2.16342155 11.2617505,2.05914367 C11.3684534,1.95486857 11.4282767,1.81370176 11.4282767,1.66667106 L11.4282767,0.556642208 C11.4282767,0.40907262 11.3678934,0.26747526 11.2605218,0.16308627 C11.1531503,0.0587028348 11.0074938,0 10.8556998,0 L5.14338868,0 C4.9915947,0 4.84594391,0.0587028348 4.73856664,0.16308627 C4.63119507,0.267469704 4.57081178,0.40907262 4.57081178,0.556642208 L4.57081178,1.66667106 C4.57081178,1.81434899 4.63119507,1.95594912 4.73856664,2.06033811 C4.8459382,2.16472155 4.9915947,2.22331605 5.14338868,2.22331605 L5.71596273,2.22331605 L5.71596273,5.55665262 C5.71596273,8.38665538 2.97295619,9.88999017 0.651686904,15.5566623 C-0.0957823782,17.360053 -2.00560068,20 7.99951567,20 C18.004632,20 16.0948137,17.3600252 15.3507732,15.5566623 C13.0124432,9.88999017 10.2865804,8.38665538 10.2865804,5.55665262 Z M9.89570197,10.709991 C10.0921412,10.709991 10.2805515,10.7858383 10.4193876,10.9209301 C10.5583466,11.0559135 10.6363652,11.2390693 10.6363652,11.4300417 C10.6363652,11.6210141 10.5583466,11.8040698 10.4193876,11.9391533 C10.2805401,12.0741367 10.0921412,12.1499813 9.89570197,12.1499813 C9.6992627,12.1499813 9.51096673,12.074134 9.37201631,11.9391533 C9.23316875,11.8040615 9.15515307,11.6210141 9.15515307,11.4300417 C9.15515307,11.2390693 9.2331716,11.0559024 9.37201631,10.9209301 C9.57264221,10.7258996 9.61239426,10.709991 9.89570197,10.709991 Z M8.98919546,9.04212824 C9.09790709,9.14792278 9.15884755,9.29158681 9.1585213,9.44110085 C9.15829001,9.59073155 9.09678989,9.73407335 8.98763252,9.83954568 C8.87847514,9.945018 8.73069852,10.0039347 8.57678157,10.0033977 C8.42286747,10.0027392 8.27565088,9.94273467 8.16727355,9.83639845 C8.05900765,9.73006224 7.99873866,9.58628988 7.99963013,9.43664806 C8.00052304,9.28788403 8.0620221,9.14542556 8.17051087,9.04048101 C8.27911107,8.93555591 8.42599335,8.87663641 8.57913312,8.87663641 C8.73291864,8.87665585 8.88047525,8.93622535 8.98919546,9.04212824 Z M7.99965585,17.9999981 C4.91377349,17.9999981 3.29882839,17.7332867 2.51364277,17.4999976 C2.37780966,17.4476975 2.26954376,17.3439641 2.21396931,17.2125528 C2.15838628,17.0811499 2.16006066,16.9334692 2.21876871,16.8033858 C2.6144474,15.5921346 3.14916224,14.4280501 3.81316983,13.3333824 C5.980145,9.82337899 8.22941036,13.8867718 10.0980836,13.8867718 C11.9666996,13.8867718 11.4695868,12.1534924 12.1827971,13.3333824 C12.8511505,14.4269112 13.3916656,15.5896902 13.794259,16.8000524 C13.8533022,16.9322137 13.8537479,17.0822749 13.7952635,17.2147751 C13.7368889,17.3472613 13.6248314,17.4504531 13.4856467,17.5000531 C12.6833967,17.7332867 11.0855382,17.9999981 7.99965585,17.9999981 Z"
id="Shape"></path>
</g>
</g>
</svg>
);
export const IconCanary = memo<
JSX.IntrinsicElements['svg'] & {title?: string; size?: 's' | 'md'}
>(function IconCanary(
{className, title, size} = {
className: undefined,
title: undefined,
size: 'md',
}
);
) {
return (
<svg
className={className}
width={size === 's' ? '12px' : '20px'}
height={size === 's' ? '12px' : '20px'}
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg">
{title && <title>{title}</title>}
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<g
id="noun-labs-1201738-(2)"
transform="translate(2, 0)"
fill="currentColor"
fillRule="nonzero">
<path
d="M10.2865804,5.55665262 L10.2865804,2.22331605 L10.8591544,2.22331605 C11.0103911,2.22244799 11.1551447,2.16342155 11.2617505,2.05914367 C11.3684534,1.95486857 11.4282767,1.81370176 11.4282767,1.66667106 L11.4282767,0.556642208 C11.4282767,0.40907262 11.3678934,0.26747526 11.2605218,0.16308627 C11.1531503,0.0587028348 11.0074938,0 10.8556998,0 L5.14338868,0 C4.9915947,0 4.84594391,0.0587028348 4.73856664,0.16308627 C4.63119507,0.267469704 4.57081178,0.40907262 4.57081178,0.556642208 L4.57081178,1.66667106 C4.57081178,1.81434899 4.63119507,1.95594912 4.73856664,2.06033811 C4.8459382,2.16472155 4.9915947,2.22331605 5.14338868,2.22331605 L5.71596273,2.22331605 L5.71596273,5.55665262 C5.71596273,8.38665538 2.97295619,9.88999017 0.651686904,15.5566623 C-0.0957823782,17.360053 -2.00560068,20 7.99951567,20 C18.004632,20 16.0948137,17.3600252 15.3507732,15.5566623 C13.0124432,9.88999017 10.2865804,8.38665538 10.2865804,5.55665262 Z M9.89570197,10.709991 C10.0921412,10.709991 10.2805515,10.7858383 10.4193876,10.9209301 C10.5583466,11.0559135 10.6363652,11.2390693 10.6363652,11.4300417 C10.6363652,11.6210141 10.5583466,11.8040698 10.4193876,11.9391533 C10.2805401,12.0741367 10.0921412,12.1499813 9.89570197,12.1499813 C9.6992627,12.1499813 9.51096673,12.074134 9.37201631,11.9391533 C9.23316875,11.8040615 9.15515307,11.6210141 9.15515307,11.4300417 C9.15515307,11.2390693 9.2331716,11.0559024 9.37201631,10.9209301 C9.57264221,10.7258996 9.61239426,10.709991 9.89570197,10.709991 Z M8.98919546,9.04212824 C9.09790709,9.14792278 9.15884755,9.29158681 9.1585213,9.44110085 C9.15829001,9.59073155 9.09678989,9.73407335 8.98763252,9.83954568 C8.87847514,9.945018 8.73069852,10.0039347 8.57678157,10.0033977 C8.42286747,10.0027392 8.27565088,9.94273467 8.16727355,9.83639845 C8.05900765,9.73006224 7.99873866,9.58628988 7.99963013,9.43664806 C8.00052304,9.28788403 8.0620221,9.14542556 8.17051087,9.04048101 C8.27911107,8.93555591 8.42599335,8.87663641 8.57913312,8.87663641 C8.73291864,8.87665585 8.88047525,8.93622535 8.98919546,9.04212824 Z M7.99965585,17.9999981 C4.91377349,17.9999981 3.29882839,17.7332867 2.51364277,17.4999976 C2.37780966,17.4476975 2.26954376,17.3439641 2.21396931,17.2125528 C2.15838628,17.0811499 2.16006066,16.9334692 2.21876871,16.8033858 C2.6144474,15.5921346 3.14916224,14.4280501 3.81316983,13.3333824 C5.980145,9.82337899 8.22941036,13.8867718 10.0980836,13.8867718 C11.9666996,13.8867718 11.4695868,12.1534924 12.1827971,13.3333824 C12.8511505,14.4269112 13.3916656,15.5896902 13.794259,16.8000524 C13.8533022,16.9322137 13.8537479,17.0822749 13.7952635,17.2147751 C13.7368889,17.3472613 13.6248314,17.4504531 13.4856467,17.5000531 C12.6833967,17.7332867 11.0855382,17.9999981 7.99965585,17.9999981 Z"
id="Shape"></path>
</g>
</g>
</svg>
);
});
24 changes: 24 additions & 0 deletions src/components/Layout/Footer.tsx
Original file line number Diff line number Diff line change
@@ -285,6 +285,30 @@ export function Footer() {
dir="ltr">
&copy;{new Date().getFullYear()}
</div>
<div
className="uwu-visible text-xs cursor-pointer hover:text-link hover:dark:text-link-dark hover:underline"
onClick={() => {
// @ts-ignore
window.__setUwu(false);
}}>
no uwu plz
</div>
<div
className="uwu-hidden text-xs cursor-pointer hover:text-link hover:dark:text-link-dark hover:underline"
onClick={() => {
// @ts-ignore
window.__setUwu(true);
}}>
uwu?
</div>
<div className="uwu-visible text-xs">
Logo by
<ExternalLink
className="ms-1"
href="https://twitter.com/sawaratsuki1004">
@sawaratsuki1004
</ExternalLink>
</div>
</div>
<div className="flex flex-col">
<FooterLink href="/learn" isHeader={true}>
28 changes: 24 additions & 4 deletions src/components/Layout/HomeContent.js
Original file line number Diff line number Diff line change
@@ -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() {
<>
<div className="ps-0">
<div className="mx-5 mt-12 lg:mt-24 mb-20 lg:mb-32 flex flex-col justify-center">
<div className="uwu-visible flex justify-center">
<Image
alt="logo by @sawaratsuki1004"
title="logo by @sawaratsuki1004"
loading="eager"
width={313}
height={160}
src="/images/uwu.png"
/>
</div>
<Logo
className={cn(
'mt-4 mb-3 text-link dark:text-link-dark w-24 lg:w-28 self-center text-sm me-0 flex origin-center transition-all ease-in-out'
'uwu-hidden mt-4 mb-3 text-brand dark:text-brand-dark w-24 lg:w-28 self-center text-sm me-0 flex origin-center transition-all ease-in-out'
)}
/>
<h1 className="text-5xl font-display lg:text-6xl self-center flex font-semibold leading-snug text-primary dark:text-primary-dark">
<h1 className="uwu-hidden text-5xl font-display lg:text-6xl self-center flex font-semibold leading-snug text-primary dark:text-primary-dark">
React
</h1>
<p className="text-4xl font-display max-w-lg md:max-w-full py-1 text-center text-secondary dark:text-primary-dark leading-snug self-center">
@@ -489,7 +501,15 @@ export function HomeContent() {
</div>

<div className="mt-20 px-5 lg:px-0 mb-6 max-w-4xl text-center text-opacity-80">
<Logo className="text-link dark:text-link-dark w-24 lg:w-28 mb-10 lg:mb-8 mt-12 h-auto mx-auto self-start" />
<div className="uwu-visible flex justify-center">
<img
alt="logo by @sawaratsuki1004"
title="logo by @sawaratsuki1004"
className="uwu-visible mb-10 lg:mb-8 h-24 lg:h-32"
src="/images/uwu.png"
/>
</div>
<Logo className="uwu-hidden text-brand dark:text-brand-dark w-24 lg:w-28 mb-10 lg:mb-8 mt-12 h-auto mx-auto self-start" />
<Header>
Welcome to the <br className="hidden lg:inline" />
React community
@@ -1620,7 +1640,7 @@ function Thumbnail({video}) {
</div>
<div className="mt-1">
<span className="inline-flex text-xs font-normal items-center text-primary-dark py-1 whitespace-nowrap outline-link px-1.5 rounded-lg">
<Logo className="text-xs me-1 w-4 h-4 text-link-dark" />
<Logo className="text-xs me-1 w-4 h-4 text-brand text-brand-dark" />
React Conf
</span>
</div>
66 changes: 30 additions & 36 deletions src/components/Layout/Page.tsx
Original file line number Diff line number Diff line change
@@ -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'
)}>
<TocContext.Provider value={toc}>{children}</TocContext.Provider>
<TocContext.Provider value={toc}>
<LanguagesContext.Provider value={languages}>
{children}
</LanguagesContext.Provider>
</TocContext.Provider>
</div>
{!isBlogIndex && (
<DocsPageFooter
@@ -91,12 +103,10 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
let hasColumns = true;
let showSidebar = true;
let showToc = true;
let showSurvey = true;
if (isHomePage || isBlogIndex) {
hasColumns = false;
showSidebar = false;
showToc = false;
showSurvey = false;
} else if (section === 'blog') {
showToc = false;
hasColumns = false;
@@ -117,7 +127,17 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
image={`/images/og-` + section + '.png'}
searchOrder={searchOrder}
/>
<SocialBanner />
{(isHomePage || isBlogIndex) && (
<Head>
<link
rel="alternate"
type="application/rss+xml"
title="React Blog RSS Feed"
href="/rss.xml"
/>
</Head>
)}
{/*<SocialBanner />*/}
<TopNav
section={section}
routeTree={routeTree}
@@ -129,7 +149,7 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
'grid grid-cols-only-content lg:grid-cols-sidebar-content 2xl:grid-cols-sidebar-content-toc'
)}>
{showSidebar && (
<div className="lg:-mt-16">
<div className="lg:-mt-16 z-10">
<div className="fixed top-0 py-0 shadow lg:pt-16 lg:sticky start-0 end-0 lg:shadow-none">
<SidebarNav
key={section}
@@ -154,33 +174,7 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
)}>
{!isHomePage && (
<div className="w-full px-5 pt-10 mx-auto sm:px-12 md:px-12 md:pt-12 lg:pt-10">
{
<hr className="mx-auto max-w-7xl border-border dark:border-border-dark" />
}
{showSurvey && (
<>
<div className="flex flex-col items-center p-4 m-4">
<p className="mb-4 text-lg font-bold text-primary dark:text-primary-dark">
How do you like these docs?
</p>
<div>
<ButtonLink
href="https://www.surveymonkey.co.uk/r/PYRPF3X"
className="mt-1"
type="primary"
size="md"
target="_blank">
Take our survey!
<IconNavArrow
displayDirection="end"
className="inline ms-1"
/>
</ButtonLink>
</div>
</div>
<hr className="mx-auto max-w-7xl border-border dark:border-border-dark" />
</>
)}
<hr className="mx-auto max-w-7xl border-border dark:border-border-dark" />
</div>
)}
<div
9 changes: 7 additions & 2 deletions src/components/Layout/Sidebar/SidebarRouteTree.tsx
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import {SidebarLink} from './SidebarLink';
import {useCollapse} from 'react-collapsed';
import usePendingRoute from 'hooks/usePendingRoute';
import type {RouteItem} from 'components/Layout/getRouteMeta';
import {siteConfig} from 'siteConfig';

interface SidebarRouteTreeProps {
isForceExpanded: boolean;
@@ -150,8 +151,12 @@ export function SidebarRouteTree({
);
}
if (hasSectionHeader) {
let sectionHeaderText =
sectionHeader != null
? sectionHeader.replace('{{version}}', siteConfig.version)
: '';
return (
<Fragment key={`${sectionHeader}-${level}-separator`}>
<Fragment key={`${sectionHeaderText}-${level}-separator`}>
{index !== 0 && (
<li
role="separator"
@@ -163,7 +168,7 @@ export function SidebarRouteTree({
'mb-1 text-sm font-bold ms-5 text-tertiary dark:text-tertiary-dark',
index !== 0 && 'mt-2'
)}>
{sectionHeader}
{sectionHeaderText}
</h3>
</Fragment>
);
145 changes: 145 additions & 0 deletions src/components/Layout/TopNav/BrandMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import * as ContextMenu from '@radix-ui/react-context-menu';
import {IconCopy} from 'components/Icon/IconCopy';
import {IconDownload} from 'components/Icon/IconDownload';
import {IconNewPage} from 'components/Icon/IconNewPage';
import {ExternalLink} from 'components/ExternalLink';
import {IconClose} from '../../Icon/IconClose';

function MenuItem({
children,
onSelect,
}: {
children: React.ReactNode;
onSelect?: () => void;
}) {
return (
<ContextMenu.Item
className="flex items-center hover:bg-border dark:hover:bg-border-dark ps-6 pe-4 py-2 w-full text-base cursor-pointer"
onSelect={onSelect}>
{children}
</ContextMenu.Item>
);
}

function DownloadMenuItem({
fileName,
href,
children,
}: {
fileName: string;
href: string;
children: React.ReactNode;
}) {
return (
<a download={fileName} href={href} className="flex items-center w-full">
<MenuItem>{children}</MenuItem>
</a>
);
}

export default function BrandMenu({children}: {children: React.ReactNode}) {
return (
<ContextMenu.Root>
<ContextMenu.Trigger className="flex items-center">
{children}
</ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content
className="hidden lg:block z-50 mt-6 bg-wash border border-border dark:border-border-dark dark:bg-wash-dark rounded min-w-56 overflow-hidden shadow"
// @ts-ignore
sideOffset={0}
align="end">
<ContextMenu.Label className="ps-4 pt-2 text-base text-tertiary dark:text-tertiary-dark">
Dark Mode
</ContextMenu.Label>
<DownloadMenuItem
fileName="react_logo_dark.svg"
href="/images/brand/logo_dark.svg">
<span className="w-8">
<IconDownload />
</span>
<span>Logo SVG</span>
</DownloadMenuItem>
<DownloadMenuItem
fileName="react_wordmark_dark.svg"
href="/images/brand/wordmark_dark.svg">
<span className="w-8">
<IconDownload />
</span>
<span>Wordmark SVG</span>
</DownloadMenuItem>
<MenuItem
onSelect={async () => {
await navigator.clipboard.writeText('#58C4DC');
}}>
<span className="w-8">
<IconCopy />
</span>
<span>Copy dark mode color</span>
</MenuItem>
<ContextMenu.Label className="ps-4 text-base text-tertiary dark:text-tertiary-dark">
Light Mode
</ContextMenu.Label>
<DownloadMenuItem
fileName="react_logo_light.svg"
href="/images/brand/logo_light.svg">
<span className="w-8">
<IconDownload />
</span>
<span>Logo SVG</span>
</DownloadMenuItem>
<DownloadMenuItem
fileName="react_wordmark_light.svg"
href="/images/brand/wordmark_light.svg">
<span className="w-8">
<IconDownload />
</span>
<span>Wordmark SVG</span>
</DownloadMenuItem>
<MenuItem
onSelect={async () => {
await navigator.clipboard.writeText('#087EA4');
}}>
<span className="w-8">
<IconCopy />
</span>
<span>Copy light mode color</span>
</MenuItem>
<div className="uwu-visible flex flex-col">
<ContextMenu.Separator className="" />
<ContextMenu.Label className="ps-4 text-base text-tertiary dark:text-tertiary-dark">
uwu
</ContextMenu.Label>
<MenuItem
onSelect={() => {
// @ts-ignore
window.__setUwu(false);
}}>
<span className="w-8">
<IconClose />
</span>
<span>Turn off</span>
</MenuItem>
<DownloadMenuItem fileName="react_uwu_png" href="/images/uwu.png">
<span className="w-8">
<IconDownload />
</span>
<span>Logo PNG</span>
</DownloadMenuItem>

<ExternalLink
className="flex items-center"
href="https://github.com/SAWARATSUKI/KawaiiLogos">
<MenuItem>
<span className="w-8">
<IconNewPage />
</span>
<span>Logo by @sawaratsuki1004</span>
</MenuItem>
</ExternalLink>
</div>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
}
108 changes: 78 additions & 30 deletions src/components/Layout/TopNav/TopNav.tsx
Original file line number Diff line number Diff line change
@@ -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,8 @@ import {Logo} from '../../Logo';
import {Feedback} from '../Feedback';
import {SidebarRouteTree} from '../Sidebar';
import type {RouteItem} from '../getRouteMeta';
import {siteConfig} from 'siteConfig';
import BrandMenu from './BrandMenu';

declare global {
interface Window {
@@ -77,6 +80,19 @@ const lightIcon = (
</svg>
);

const languageIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24">
<path
fill="currentColor"
d=" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z "
/>
</svg>
);

const githubIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -110,7 +126,7 @@ function NavItem({url, isActive, children}: any) {
<Link
href={url}
className={cn(
'active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize',
'active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize whitespace-nowrap',
!isActive && 'hover:bg-primary/5 hover:dark:bg-primary-dark/5',
isActive &&
'bg-highlight dark:bg-highlight-dark text-link dark:text-link-dark'
@@ -142,10 +158,11 @@ export default function TopNav({
breadcrumbs: RouteItem[];
section: 'learn' | 'reference' | 'community' | 'blog' | 'home' | 'unknown';
}) {
const [isOpen, setIsOpen] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [showSearch, setShowSearch] = useState(false);
const [isScrolled, setIsScrolled] = useState(false);
const scrollParentRef = useRef<HTMLDivElement>(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 +171,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 +192,7 @@ export default function TopNav({

function closeIfNeeded() {
if (!media.matches) {
setIsOpen(false);
setIsMenuOpen(false);
}
}

@@ -204,7 +221,6 @@ export default function TopNav({
return () => observer.disconnect();
}, []);

const [showSearch, setShowSearch] = useState(false);
const onOpenSearch = useCallback(() => {
startTransition(() => {
setShowSearch(true);
@@ -224,39 +240,63 @@ export default function TopNav({
<div ref={scrollDetectorRef} />
<div
className={cn(
isOpen
isMenuOpen
? 'h-screen sticky top-0 lg:bottom-0 lg:h-screen flex flex-col shadow-nav dark:shadow-nav-dark z-20'
: 'z-50 sticky top-0'
: 'z-40 sticky top-0'
)}>
<nav
className={cn(
'duration-300 backdrop-filter backdrop-blur-lg backdrop-saturate-200 transition-shadow bg-opacity-90 items-center w-full flex justify-between bg-wash dark:bg-wash-dark dark:bg-opacity-95 px-1.5 lg:pe-5 lg:ps-4 z-50',
{'dark:shadow-nav-dark shadow-nav': isScrolled || isOpen}
'duration-300 backdrop-filter backdrop-blur-lg backdrop-saturate-200 transition-shadow bg-opacity-90 items-center w-full flex justify-between bg-wash dark:bg-wash-dark dark:bg-opacity-95 px-1.5 lg:pe-5 lg:ps-4 z-40',
{'dark:shadow-nav-dark shadow-nav': isScrolled || isMenuOpen}
)}>
<div className="flex items-center justify-between w-full h-16 gap-0 sm:gap-3">
<div className="flex flex-row 3xl:flex-1 ">
<div className="flex flex-row 3xl:flex-1 items-centers">
<button
type="button"
aria-label="Menu"
onClick={() => setIsOpen(!isOpen)}
onClick={() => setIsMenuOpen(!isMenuOpen)}
className={cn(
'active:scale-95 transition-transform flex lg:hidden w-12 h-12 rounded-full items-center justify-center hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link',
{
'text-link dark:text-link-dark': isOpen,
'text-link dark:text-link-dark': isMenuOpen,
}
)}>
{isOpen ? <IconClose /> : <IconHamburger />}
{isMenuOpen ? <IconClose /> : <IconHamburger />}
</button>
<div className="flex 3xl:flex-1 align-center">
<BrandMenu>
<div className="flex items-center">
<div className="uwu-visible flex items-center justify-center h-full">
<NextLink href="/">
<Image
alt="logo by @sawaratsuki1004"
title="logo by @sawaratsuki1004"
className="h-8"
priority
width={63}
height={32}
src="/images/uwu.png"
/>
</NextLink>
</div>
<div className="uwu-hidden">
<NextLink
href="/"
className={`active:scale-95 overflow-hidden transition-transform relative items-center text-primary dark:text-primary-dark p-1 whitespace-nowrap outline-link rounded-full 3xl:rounded-xl inline-flex text-lg font-normal gap-2`}>
<Logo
className={cn(
'text-sm me-0 w-10 h-10 text-brand dark:text-brand-dark flex origin-center transition-all ease-in-out'
)}
/>
<span className="sr-only 3xl:not-sr-only">React</span>
</NextLink>
</div>
</div>
</BrandMenu>
<div className="flex flex-column justify-center items-center">
<NextLink
href="/"
className={`active:scale-95 overflow-hidden transition-transform relative items-center text-primary dark:text-primary-dark p-1 whitespace-nowrap outline-link rounded-full 3xl:rounded-xl inline-flex text-lg font-normal gap-2`}>
<Logo
className={cn(
'text-sm me-0 w-10 h-10 text-link dark:text-link-dark flex origin-center transition-all ease-in-out'
)}
/>
<span className="sr-only 3xl:not-sr-only">React</span>
href="/versions"
className=" flex py-2 flex-column justify-center items-center text-gray-50 dark:text-gray-30 hover:text-link hover:dark:text-link-dark hover:underline text-sm ms-1 cursor-pointer">
v{siteConfig.version}
</NextLink>
</div>
</div>
@@ -328,6 +368,14 @@ export default function TopNav({
{lightIcon}
</button>
</div>
<div className="flex">
<Link
href="/community/translations"
aria-label="Translations"
className="active:scale-95 transition-transform flex w-12 h-12 rounded-full items-center justify-center hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link">
{languageIcon}
</Link>
</div>
<div className="flex">
<Link
href="https://github.com/facebook/react/releases"
@@ -343,14 +391,14 @@ export default function TopNav({
</div>
</nav>

{isOpen && (
{isMenuOpen && (
<div
ref={scrollParentRef}
className="overflow-y-scroll isolate no-bg-scrollbar lg:w-[342px] grow bg-wash dark:bg-wash-dark">
<aside
className={cn(
`lg:grow lg:flex flex-col w-full pb-8 lg:pb-0 lg:max-w-custom-xs z-50`,
isOpen ? 'block z-40' : 'hidden lg:block'
`lg:grow lg:flex flex-col w-full pb-8 lg:pb-0 lg:max-w-custom-xs z-40`,
isMenuOpen ? 'block z-30' : 'hidden lg:block'
)}>
<nav
role="navigation"
@@ -383,10 +431,10 @@ export default function TopNav({
<SidebarRouteTree
// Don't share state between the desktop and mobile versions.
// This avoids unnecessary animations and visual flicker.
key={isOpen ? 'mobile-overlay' : 'desktop-or-hidden'}
key={isMenuOpen ? 'mobile-overlay' : 'desktop-or-hidden'}
routeTree={routeTree}
breadcrumbs={breadcrumbs}
isForceExpanded={isOpen}
isForceExpanded={isMenuOpen}
/>
</Suspense>
<div className="h-16" />
81 changes: 78 additions & 3 deletions src/components/MDX/ConsoleBlock.tsx
Original file line number Diff line number Diff line change
@@ -15,6 +15,10 @@ interface ConsoleBlockProps {
children: React.ReactNode;
}

interface ConsoleBlockMultiProps {
children: React.ReactNode;
}

const Box = ({
width = '60px',
height = '17px',
@@ -29,7 +33,7 @@ const Box = ({
<div className={className} style={{width, height, ...customStyles}}></div>
);

function ConsoleBlock({level = 'error', children}: ConsoleBlockProps) {
export function ConsoleBlock({level = 'error', children}: ConsoleBlockProps) {
let message: React.ReactNode | null;
if (typeof children === 'string') {
message = children;
@@ -38,7 +42,10 @@ function ConsoleBlock({level = 'error', children}: ConsoleBlockProps) {
}

return (
<div className="mb-4 text-secondary" translate="no" dir="ltr">
<div
className="console-block mb-4 text-secondary bg-wash dark:bg-wash-dark rounded-lg"
translate="no"
dir="ltr">
<div className="flex w-full rounded-t-lg bg-gray-200 dark:bg-gray-80">
<div className="px-4 py-2 border-gray-300 dark:border-gray-90 border-r">
<Box className="bg-gray-300 dark:bg-gray-70" width="15px" />
@@ -73,4 +80,72 @@ function ConsoleBlock({level = 'error', children}: ConsoleBlockProps) {
);
}

export default ConsoleBlock;
export function ConsoleBlockMulti({children}: ConsoleBlockMultiProps) {
return (
<div
className="console-block mb-4 text-secondary bg-wash dark:bg-wash-dark rounded-lg"
translate="no"
dir="ltr">
<div className="flex w-full rounded-t-lg bg-gray-200 dark:bg-gray-80">
<div className="px-4 py-2 border-gray-300 dark:border-gray-90 border-r">
<Box className="bg-gray-300 dark:bg-gray-70" width="15px" />
</div>
<div className="flex text-sm px-4">
<div className="border-b-2 border-gray-300 dark:border-gray-90 text-tertiary dark:text-tertiary-dark">
Console
</div>
<div className="px-4 py-2 flex">
<Box className="me-2 bg-gray-300 dark:bg-gray-70" />
<Box className="me-2 hidden md:block bg-gray-300 dark:bg-gray-70" />
<Box className="hidden md:block bg-gray-300 dark:bg-gray-70" />
</div>
</div>
</div>
<div className="grid grid-cols-1 divide-y divide-gray-300 dark:divide-gray-70 text-base">
{children}
</div>
</div>
);
}

export function ConsoleLogLine({children, level}: ConsoleBlockProps) {
let message: React.ReactNode | null;
if (typeof children === 'string') {
message = children;
} else if (isValidElement(children)) {
message = children.props.children;
} else if (Array.isArray(children)) {
message = children.reduce((result, child) => {
if (typeof child === 'string') {
result += child;
} else if (isValidElement(child)) {
// @ts-ignore
result += child.props.children;
}
return result;
}, '');
}

return (
<div
className={cn(
'ps-4 pe-2 pt-1 pb-2 grid grid-cols-[18px_auto] font-mono rounded-b-md',
{
'bg-red-30 text-red-50 dark:text-red-30 bg-opacity-5':
level === 'error',
'bg-yellow-5 text-yellow-50': level === 'warning',
'bg-gray-5 text-secondary dark:text-secondary-dark': level === 'info',
}
)}>
{level === 'error' && (
<IconError className="self-start mt-1.5 text-[.7rem] w-6" />
)}
{level === 'warning' && (
<IconWarning className="self-start mt-1 text-[.65rem] w-6" />
)}
<div className="px-2 pt-1 whitespace-break-spaces text-code leading-tight">
{message}
</div>
</div>
);
}
6 changes: 1 addition & 5 deletions src/components/MDX/ExpandableCallout.tsx
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@
* Copyright (c) Facebook, Inc. and its affiliates.
*/

import {useRef} from 'react';
import * as React from 'react';
import cn from 'classnames';
import {IconNote} from '../Icon/IconNote';
@@ -63,7 +62,6 @@ const variantMap = {
};

function ExpandableCallout({children, type = 'note'}: ExpandableCalloutProps) {
const contentRef = useRef<HTMLDivElement>(null);
const variant = variantMap[type];

return (
@@ -80,9 +78,7 @@ function ExpandableCallout({children, type = 'note'}: ExpandableCalloutProps) {
{variant.title}
</h3>
<div className="relative">
<div ref={contentRef} className="py-2">
{children}
</div>
<div className="py-2">{children}</div>
</div>
</div>
);
14 changes: 14 additions & 0 deletions src/components/MDX/LanguagesContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/

import {createContext} from 'react';

export type LanguageItem = {
code: string;
name: string;
enName: string;
};
export type Languages = Array<LanguageItem>;

export const LanguagesContext = createContext<Languages | null>(null);
57 changes: 55 additions & 2 deletions src/components/MDX/MDXComponents.tsx
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import cn from 'classnames';

import CodeBlock from './CodeBlock';
import {CodeDiagram} from './CodeDiagram';
import ConsoleBlock from './ConsoleBlock';
import {ConsoleBlock, ConsoleLogLine, ConsoleBlockMulti} from './ConsoleBlock';
import ExpandableCallout from './ExpandableCallout';
import ExpandableExample from './ExpandableExample';
import {H1, H2, H3, H4, H5} from './Heading';
@@ -31,8 +31,11 @@ import ButtonLink from 'components/ButtonLink';
import {TocContext} from './TocContext';
import type {Toc, TocItem} from './TocContext';
import {TeamMember} from './TeamMember';
import {LanguagesContext} from './LanguagesContext';
import {finishedTranslations} from 'utils/finishedTranslations';

import ErrorDecoder from './ErrorDecoder';
import {IconCanary} from '../Icon/IconCanary';

function CodeStep({children, step}: {children: any; step: number}) {
return (
@@ -94,6 +97,20 @@ const Canary = ({children}: {children: React.ReactNode}) => (
<ExpandableCallout type="canary">{children}</ExpandableCallout>
);

const CanaryBadge = ({title}: {title: string}) => (
<span
title={title}
className={
'text-base font-display px-1 py-0.5 font-bold bg-gray-10 dark:bg-gray-60 text-gray-60 dark:text-gray-10 rounded'
}>
<IconCanary
size="s"
className={'inline me-1 mb-0.5 text-sm text-gray-60 dark:text-gray-10'}
/>
Canary only
</span>
);

const Blockquote = ({
children,
...props
@@ -191,7 +208,7 @@ function Recipes(props: any) {

function AuthorCredit({
author = 'Rachel Lee Nabors',
authorLink = 'http://rachelnabors.com/',
authorLink = 'https://nearestnabors.com/',
}: {
author: string;
authorLink: string;
@@ -365,6 +382,38 @@ function InlineTocItem({items}: {items: Array<NestedTocNode>}) {
);
}

type TranslationProgress = 'complete' | 'in-progress';

function LanguageList({progress}: {progress: TranslationProgress}) {
const allLanguages = React.useContext(LanguagesContext) ?? [];
const languages = allLanguages
.filter(
({code}) =>
code !== 'en' &&
(progress === 'complete'
? finishedTranslations.includes(code)
: !finishedTranslations.includes(code))
)
.sort((a, b) => a.enName.localeCompare(b.enName));
return (
<UL>
{languages.map(({code, name, enName}) => {
return (
<LI key={code}>
<Link href={`https://${code}.react.dev/`}>
{enName} ({name})
</Link>{' '}
&mdash;{' '}
<Link href={`https://github.com/reactjs/${code}.react.dev`}>
Contribute
</Link>
</LI>
);
})}
</UL>
);
}

function YouTubeIframe(props: any) {
return (
<div className="relative h-0 overflow-hidden pt-[56.25%]">
@@ -405,6 +454,8 @@ export const MDXComponents = {
pre: CodeBlock,
CodeDiagram,
ConsoleBlock,
ConsoleBlockMulti,
ConsoleLogLine,
DeepDive: (props: {
children: React.ReactNode;
title: string;
@@ -425,11 +476,13 @@ export const MDXComponents = {
IllustrationBlock,
Intro,
InlineToc,
LanguageList,
LearnMore,
Math,
MathI,
Note,
Canary,
CanaryBadge,
PackageImport,
ReadBlogPost,
Recap,
2 changes: 1 addition & 1 deletion src/components/MDX/Sandpack/SandpackRoot.tsx
Original file line number Diff line number Diff line change
@@ -88,7 +88,7 @@ function SandpackRoot(props: SandpackProps) {
autorun,
initMode: 'user-visible',
initModeObserverOptions: {rootMargin: '1400px 0px'},
bundlerURL: 'https://1e4ad8f7.sandpack-bundler-4bw.pages.dev',
bundlerURL: 'https://786946de.sandpack-bundler-4bw.pages.dev',
logLevel: SandpackLogLevel.None,
}}>
<CustomPreset providedFiles={Object.keys(files)} />
6 changes: 3 additions & 3 deletions src/components/MDX/SandpackWithHTMLOutput.tsx
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ export default function ShowRenderedHTML({children}) {
{formatHTML(markup)}
</pre>
</>
);
);
}`;

const formatHTML = `
@@ -77,8 +77,8 @@ export default memo(function SandpackWithHTMLOutput(
) {
const children = [
...Children.toArray(props.children),
createFile('ShowRenderedHTML.js', ShowRenderedHTML),
createFile('formatHTML.js hidden', formatHTML),
createFile('src/ShowRenderedHTML.js', ShowRenderedHTML),
createFile('src/formatHTML.js hidden', formatHTML),
createFile('package.json hidden', packageJSON),
];
return <Sandpack {...props}>{children}</Sandpack>;
6 changes: 3 additions & 3 deletions src/components/MDX/TeamMember.tsx
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ export function TeamMember({
<ExternalLink
aria-label="React on Twitter"
href={`https://twitter.com/${twitter}`}
className="hover:text-primary dark:text-primary-dark flex flex-row items-center">
className="hover:text-primary hover:underline dark:text-primary-dark flex flex-row items-center">
<IconTwitter className="pe-1" />
{twitter}
</ExternalLink>
@@ -90,7 +90,7 @@ export function TeamMember({
<ExternalLink
aria-label="GitHub Profile"
href={`https://github.com/${github}`}
className="hover:text-primary dark:text-primary-dark flex flex-row items-center">
className="hover:text-primary hover:underline dark:text-primary-dark flex flex-row items-center">
<IconGitHub className="pe-1" /> {github}
</ExternalLink>
</div>
@@ -99,7 +99,7 @@ export function TeamMember({
<ExternalLink
aria-label="Personal Site"
href={`https://${personal}`}
className="hover:text-primary dark:text-primary-dark flex flex-row items-center">
className="hover:text-primary hover:underline dark:text-primary-dark flex flex-row items-center">
<IconLink className="pe-1" /> {personal}
</ExternalLink>
)}
6 changes: 0 additions & 6 deletions src/components/PageHeading.tsx
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ function PageHeading({
title,
status,
canary,
description,
tags = [],
breadcrumbs,
}: PageHeadingProps) {
@@ -40,11 +39,6 @@ function PageHeading({
)}
{status ? <em>{status}</em> : ''}
</H1>
{description && (
<p className="mt-4 mb-6 dark:text-primary-dark text-xl text-primary leading-large">
{description}
</p>
)}
{tags?.length > 0 && (
<div className="mt-4">
{tags.map((tag) => (
1 change: 0 additions & 1 deletion src/components/Search.tsx
Original file line number Diff line number Diff line change
@@ -110,7 +110,6 @@ export function Search({
createPortal(
<DocSearchModal
{...options}
initialScrollY={window.scrollY}
searchParameters={searchParameters}
onClose={onClose}
navigator={{
16 changes: 4 additions & 12 deletions src/components/Seo.tsx
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import * as React from 'react';
import Head from 'next/head';
import {withRouter, Router} from 'next/router';
import {siteConfig} from '../siteConfig';
import {finishedTranslations} from 'utils/finishedTranslations';

export interface SeoProps {
title: string;
@@ -18,17 +19,8 @@ export interface SeoProps {
searchOrder?: number;
}

const deployedTranslations = [
'en',
'zh-hans',
'es',
'fr',
'ja',
'tr',
// We'll add more languages when they have enough content.
// Please DO NOT edit this list without a discussion in the reactjs/react.dev repo.
// It must be the same between all translations.
];
// If you are a maintainer of a language fork,
// deployedTranslations has been moved to src/utils/finishedTranslations.ts.

function getDomain(languageCode: string): string {
const subdomain = languageCode === 'en' ? '' : languageCode + '.';
@@ -71,7 +63,7 @@ export const Seo = withRouter(
href={canonicalUrl.replace(siteDomain, getDomain('en'))}
hrefLang="x-default"
/>
{deployedTranslations.map((languageCode) => (
{finishedTranslations.map((languageCode) => (
<link
key={'alt-' + languageCode}
rel="alternate"
8 changes: 3 additions & 5 deletions src/components/SocialBanner.tsx
Original file line number Diff line number Diff line change
@@ -7,9 +7,9 @@ import {useRef, useEffect} from 'react';
import cn from 'classnames';
import {ExternalLink} from './ExternalLink';

const bannerText = 'Support Ukraine 🇺🇦';
const bannerLink = 'https://opensource.fb.com/support-ukraine';
const bannerLinkText = 'Help Provide Humanitarian Aid to Ukraine';
const bannerText = 'Stream React Conf on May 15-16.';
const bannerLink = 'https://conf.react.dev/';
const bannerLinkText = 'Learn more.';

export default function SocialBanner() {
const ref = useRef<HTMLDivElement | null>(null);
@@ -39,9 +39,7 @@ export default function SocialBanner() {
<ExternalLink
className="ms-0 sm:ms-1 text-link dark:text-link-dark hover:underline"
href={bannerLink}>
<div className="inline sm:hidden">🇺🇦 </div>
{bannerLinkText}
<span className="hidden sm:inline">.</span>
</ExternalLink>
</div>
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "Introducing Zero-Bundle-Size React Server Components"
author: Dan Abramov, Lauren Tan, Joseph Savona, and Sebastian Markbage
date: 2020/12/21
description: 2020 has been a long year. As it comes to an end we wanted to share a special Holiday Update on our research into zero-bundle-size React Server Components.
---

December 21, 2020 by [Dan Abramov](https://twitter.com/dan_abramov), [Lauren Tan](https://twitter.com/potetotes), [Joseph Savona](https://twitter.com/en_JS), and [Sebastian Markbåge](https://twitter.com/sebmarkbage)
3 changes: 3 additions & 0 deletions src/content/blog/2021/06/08/the-plan-for-react-18.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "The Plan for React 18"
author: Andrew Clark, Brian Vaughn, Christine Abernathy, Dan Abramov, Rachel Nabors, Rick Hanlon, Sebastian Markbage, and Seth Webster
date: 2021/06/08
description: The React team is excited to share a few updates. We’ve started work on the React 18 release, which will be our next major version. We’ve created a Working Group to prepare the community for gradual adoption of new features in React 18. We’ve published a React 18 Alpha so that library authors can try it and provide feedback...
---

June 8, 2021 by [Andrew Clark](https://twitter.com/acdlite), [Brian Vaughn](https://github.com/bvaughn), [Christine Abernathy](https://twitter.com/abernathyca), [Dan Abramov](https://twitter.com/dan_abramov), [Rachel Nabors](https://twitter.com/rachelnabors), [Rick Hanlon](https://twitter.com/rickhanlonii), [Sebastian Markbåge](https://twitter.com/sebmarkbage), and [Seth Webster](https://twitter.com/sethwebster)
3 changes: 3 additions & 0 deletions src/content/blog/2021/12/17/react-conf-2021-recap.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "React Conf 2021 Recap"
author: Jesslyn Tannady and Rick Hanlon
date: 2021/12/17
description: Last week we hosted our 6th React Conf. In previous years, we've used the React Conf stage to deliver industry changing announcements such as React Native and React Hooks. This year, we shared our multi-platform vision for React, starting with the release of React 18 and gradual adoption of concurrent features.
---

December 17, 2021 by [Jesslyn Tannady](https://twitter.com/jtannady) and [Rick Hanlon](https://twitter.com/rickhanlonii)
3 changes: 3 additions & 0 deletions src/content/blog/2022/03/08/react-18-upgrade-guide.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "How to Upgrade to React 18"
author: Rick Hanlon
date: 2022/03/08
description: As we shared in the release post, React 18 introduces features powered by our new concurrent renderer, with a gradual adoption strategy for existing applications. In this post, we will guide you through the steps for upgrading to React 18.
---

March 08, 2022 by [Rick Hanlon](https://twitter.com/rickhanlonii)
5 changes: 4 additions & 1 deletion src/content/blog/2022/03/29/react-v18.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "React v18.0"
author: The React Team
date: 2022/03/08
description: React 18 is now available on npm! In our last post, we shared step-by-step instructions for upgrading your app to React 18. In this post, we'll give an overview of what's new in React 18, and what it means for the future.
---

March 29, 2022 by [The React Team](/community/team)
@@ -237,7 +240,7 @@ With Strict Mode in React 18, React will simulate unmounting and remounting the
#### useTransition {/*usetransition*/}

`useTransition` and `startTransition` let you mark some state updates as not urgent. Other state updates are considered urgent by default. React will allow urgent state updates (for example, updating a text input) to interrupt non-urgent state updates (for example, rendering a list of search results). [See docs here](/reference/react/useTransition)
`useTransition` and `startTransition` let you mark some state updates as not urgent. Other state updates are considered urgent by default. React will allow urgent state updates (for example, updating a text input) to interrupt non-urgent state updates (for example, rendering a list of search results). [See docs here](/reference/react/useTransition).

#### useDeferredValue {/*usedeferredvalue*/}

Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "React Labs: What We've Been Working On – June 2022"
author: Andrew Clark, Dan Abramov, Jan Kassens, Joseph Savona, Josh Story, Lauren Tan, Luna Ruan, Mengdi Chen, Rick Hanlon, Robert Zhang, Sathya Gunasekaran, Sebastian Markbage, and Xuan Huang
date: 2022/06/15
description: React 18 was years in the making, and with it brought valuable lessons for the React team. Its release was the result of many years of research and exploring many paths. Some of those paths were successful; many more were dead-ends that led to new insights. One lesson we’ve learned is that it’s frustrating for the community to wait for new features without having insight into these paths that we’re exploring.
---

June 15, 2022 by [Andrew Clark](https://twitter.com/acdlite), [Dan Abramov](https://twitter.com/dan_abramov), [Jan Kassens](https://twitter.com/kassens), [Joseph Savona](https://twitter.com/en_JS), [Josh Story](https://twitter.com/joshcstory), [Lauren Tan](https://twitter.com/potetotes), [Luna Ruan](https://twitter.com/lunaruan), [Mengdi Chen](https://twitter.com/mengdi_en), [Rick Hanlon](https://twitter.com/rickhanlonii), [Robert Zhang](https://twitter.com/jiaxuanzhang01), [Sathya Gunasekaran](https://twitter.com/_gsathya), [Sebastian Markbåge](https://twitter.com/sebmarkbage), and [Xuan Huang](https://twitter.com/Huxpro)
@@ -74,6 +77,6 @@ We are working on a new version for the Interaction Tracing API (tentatively cal

Last year, we announced the beta version of the new React documentation website ([later shipped as react.dev](/blog/2023/03/16/introducing-react-dev)) of the new React documentation website. The new learning materials teach Hooks first and has new diagrams, illustrations, as well as many interactive examples and challenges. We took a break from that work to focus on the React 18 release, but now that React 18 is out, we’re actively working to finish and ship the new documentation.

We are currently writing a detailed section about effects, as we’ve heard that is one of the more challenging topics for both new and experienced React users. [Synchronizing with Effects](/learn/synchronizing-with-effects) is the first published page in the series, and there are more to come in the following weeks. When we first started writing a detailed section about effects, we’ve realized that many common effect patterns can be simplified by adding a new primitive to React. We’ve shared some initial thoughts on that in the [useEvent RFC](https://github.com/reactjs/rfcs/pull/220). It is currently in early research, and we are still iterating on the idea. We appreciate the community’s comments on the RFC so far, as well as the [feedback](https://github.com/reactjs/reactjs.org/issues/3308) and contributions to the ongoing documentation rewrite. We’d specifically like to thank [Harish Kumar](https://github.com/harish-sethuraman) for submitting and reviewing many improvements to the new website implementation.
We are currently writing a detailed section about effects, as we’ve heard that is one of the more challenging topics for both new and experienced React users. [Synchronizing with Effects](/learn/synchronizing-with-effects) is the first published page in the series, and there are more to come in the following weeks. When we first started writing a detailed section about effects, we’ve realized that many common effect patterns can be simplified by adding a new primitive to React. We’ve shared some initial thoughts on that in the [useEvent RFC](https://github.com/reactjs/rfcs/pull/220). It is currently in early research, and we are still iterating on the idea. We appreciate the community’s comments on the RFC so far, as well as the [feedback](https://github.com/reactjs/react.dev/issues/3308) and contributions to the ongoing documentation rewrite. We’d specifically like to thank [Harish Kumar](https://github.com/harish-sethuraman) for submitting and reviewing many improvements to the new website implementation.

*Thanks to [Sophie Alpert](https://twitter.com/sophiebits) for reviewing this blog post!*
9 changes: 6 additions & 3 deletions src/content/blog/2023/03/16/introducing-react-dev.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "Introducing react.dev"
author: Dan Abramov and Rachel Nabors
date: 2023/03/16
description: Today we are thrilled to launch react.dev, the new home for React and its documentation. In this post, we would like to give you a tour of the new site.
---

March 16, 2023 by [Dan Abramov](https://twitter.com/dan_abramov) and [Rachel Nabors](https://twitter.com/rachelnabors)
@@ -266,7 +269,7 @@ Use the conditional operator (`cond ? a : b`) to render a ❌ if `isPacked` isn
function Item({ name, isPacked }) {
return (
<li className="item">
{name} {isPacked && ''}
{name} {isPacked && ''}
</li>
);
}
@@ -304,7 +307,7 @@ export default function PackingList() {
function Item({ name, isPacked }) {
return (
<li className="item">
{name} {isPacked ? '' : ''}
{name} {isPacked ? '' : ''}
</li>
);
}
@@ -610,7 +613,7 @@ We hope that this approach will make the API reference useful not only as a way

## What's next? {/*whats-next*/}

That's a wrap for our little tour! Have a look around the new website, see what you like or don't like, and keep the feedback coming in the [anonymous survey](https://www.surveymonkey.co.uk/r/PYRPF3X) or in our [issue tracker](https://github.com/reactjs/reactjs.org/issues).
That's a wrap for our little tour! Have a look around the new website, see what you like or don't like, and keep the feedback coming in our [issue tracker](https://github.com/reactjs/react.dev/issues).

We acknowledge this project has taken a long time to ship. We wanted to maintain a high quality bar that the React community deserves. While writing these docs and creating all of the examples, we found mistakes in some of our own explanations, bugs in React, and even gaps in the React design that we are now working to address. We hope that the new documentation will help us hold React itself to a higher bar in the future.

Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "React Labs: What We've Been Working On – March 2023"
author: Joseph Savona, Josh Story, Lauren Tan, Mengdi Chen, Samuel Susla, Sathya Gunasekaran, Sebastian Markbage, and Andrew Clark
date: 2023/03/22
description: In React Labs posts, we write about projects in active research and development. We've made significant progress on them since our last update, and we'd like to share what we learned.
---

March 22, 2023 by [Joseph Savona](https://twitter.com/en_JS), [Josh Story](https://twitter.com/joshcstory), [Lauren Tan](https://twitter.com/potetotes), [Mengdi Chen](https://twitter.com/mengdi_en), [Samuel Susla](https://twitter.com/SamuelSusla), [Sathya Gunasekaran](https://twitter.com/_gsathya), [Sebastian Markbåge](https://twitter.com/sebmarkbage), and [Andrew Clark](https://twitter.com/acdlite)
3 changes: 3 additions & 0 deletions src/content/blog/2023/05/03/react-canaries.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
---
title: "React Canaries: Enabling Incremental Feature Rollout Outside Meta"
author: Dan Abramov, Sophie Alpert, Rick Hanlon, Sebastian Markbage, and Andrew Clark
date: 2023/05/03
description: We'd like to offer the React community an option to adopt individual new features as soon as their design is close to final, before they're released in a stable version--similar to how Meta has long used bleeding-edge versions of React internally. We are introducing a new officially supported [Canary release channel](/community/versioning-policy#canary-channel). It lets curated setups like frameworks decouple adoption of individual React features from the React release schedule.
---

May 3, 2023 by [Dan Abramov](https://twitter.com/dan_abramov), [Sophie Alpert](https://twitter.com/sophiebits), [Rick Hanlon](https://twitter.com/rickhanlonii), [Sebastian Markbåge](https://twitter.com/sebmarkbage), and [Andrew Clark](https://twitter.com/acdlite)
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
title: "React Labs: What We've Been Working On – February 2024"
author: Joseph Savona, Ricky Hanlon, Andrew Clark, Matt Carroll, and Dan Abramov
date: 2024/02/15
description: In React Labs posts, we write about projects in active research and development. We’ve made significant progress since our last update, and we’d like to share our progress.
---

February 15, 2024 by [Joseph Savona](https://twitter.com/en_JS), [Ricky Hanlon](https://twitter.com/rickhanlonii), [Andrew Clark](https://twitter.com/acdlite), [Matt Carroll](https://twitter.com/mattcarrollcode), and [Dan Abramov](https://twitter.com/dan_abramov).

---

<Intro>

In React Labs posts, we write about projects in active research and development. We’ve made significant progress since our [last update](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023), and we’d like to share our progress.

</Intro>

<Note>

React Conf 2024 is scheduled for May 15–16 in Henderson, Nevada! If you’re interested in attending React Conf in person, you can [sign up for the ticket lottery](https://forms.reform.app/bLaLeE/react-conf-2024-ticket-lottery/1aRQLK) until February 28th.

For more info on tickets, free streaming, sponsoring, and more, see [the React Conf website](https://conf.react.dev).

</Note>

---

## React Compiler {/*react-compiler*/}

React Compiler is no longer a research project: the compiler now powers instagram.com in production, and we are working to ship the compiler across additional surfaces at Meta and to prepare the first open source release.

As discussed in our [previous post](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-optimizing-compiler), React can *sometimes* re-render too much when state changes. Since the early days of React our solution for such cases has been manual memoization. In our current APIs, this means applying the [`useMemo`](/reference/react/useMemo), [`useCallback`](/reference/react/useCallback), and [`memo`](/reference/react/memo) APIs to manually tune how much React re-renders on state changes. But manual memoization is a compromise. It clutters up our code, is easy to get wrong, and requires extra work to keep up to date.

Manual memoization is a reasonable compromise, but we weren’t satisfied. Our vision is for React to *automatically* re-render just the right parts of the UI when state changes, *without compromising on React’s core mental model*. We believe that React’s approach — UI as a simple function of state, with standard JavaScript values and idioms — is a key part of why React has been approachable for so many developers. That’s why we’ve invested in building an optimizing compiler for React.

JavaScript is a notoriously challenging language to optimize, thanks to its loose rules and dynamic nature. React Compiler is able to compile code safely by modeling both the rules of JavaScript *and* the “rules of React”. For example, React components must be idempotent — returning the same value given the same inputs — and can’t mutate props or state values. These rules limit what developers can do and help to carve out a safe space for the compiler to optimize.

Of course, we understand that developers sometimes bend the rules a bit, and our goal is to make React Compiler work out of the box on as much code as possible. The compiler attempts to detect when code doesn’t strictly follow React’s rules and will either compile the code where safe or skip compilation if it isn’t safe. We’re testing against Meta’s large and varied codebase in order to help validate this approach.

For developers who are curious about making sure their code follows React’s rules, we recommend [enabling Strict Mode](/reference/react/StrictMode) and [configuring React’s ESLint plugin](/learn/editor-setup#linting). These tools can help to catch subtle bugs in your React code, improving the quality of your applications today, and future-proofs your applications for upcoming features such as React Compiler. We are also working on consolidated documentation of the rules of React and updates to our ESLint plugin to help teams understand and apply these rules to create more robust apps.

To see the compiler in action, you can check out our [talk from last fall](https://www.youtube.com/watch?v=qOQClO3g8-Y). At the time of the talk, we had early experimental data from trying React Compiler on one page of instagram.com. Since then, we shipped the compiler to production across instagram.com. We’ve also expanded our team to accelerate the rollout to additional surfaces at Meta and to open source. We’re excited about the path ahead and will have more to share in the coming months.

## Actions {/*actions*/}


We [previously shared](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components) that we were exploring solutions for sending data from the client to the server with Server Actions, so that you can execute database mutations and implement forms. During development of Server Actions, we extended these APIs to support data handling in client-only applications as well.

We refer to this broader collection of features as simply "Actions". Actions allow you to pass a function to DOM elements such as [`<form/>`](/reference/react-dom/components/form):

```js
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>
```

The `action` function can operate synchronously or asynchronously. You can define them on the client side using standard JavaScript or on the server with the [`'use server'`](/reference/rsc/use-server) directive. When using an action, React will manage the life cycle of the data submission for you, providing hooks like [`useFormStatus`](/reference/react-dom/hooks/useFormStatus), and [`useActionState`](/reference/react/useActionState) to access the current state and response of the form action.

By default, Actions are submitted within a [transition](/reference/react/useTransition), keeping the current page interactive while the action is processing. Since Actions support async functions, we've also added the ability to use `async/await` in transitions. This allows you to show pending UI with the `isPending` state of a transition when an async request like `fetch` starts, and show the pending UI all the way through the update being applied.

Alongside Actions, we're introducing a feature named [`useOptimistic`](/reference/react/useOptimistic) for managing optimistic state updates. With this hook, you can apply temporary updates that are automatically reverted once the final state commits. For Actions, this allows you to optimistically set the final state of the data on the client, assuming the submission is successful, and revert to the value for data received from the server. It works using regular `async`/`await`, so it works the same whether you're using `fetch` on the client, or a Server Action from the server.

Library authors can implement custom `action={fn}` props in their own components with `useTransition`. Our intent is for libraries to adopt the Actions pattern when designing their component APIs, to provide a consistent experience for React developers. For example, if your library provides a `<Calendar onSelect={eventHandler}>` component, consider also exposing a `<Calendar selectAction={action}>` API, too.

While we initially focused on Server Actions for client-server data transfer, our philosophy for React is to provide the same programming model across all platforms and environments. When possible, if we introduce a feature on the client, we aim to make it also work on the server, and vice versa. This philosophy allows us to create a single set of APIs that work no matter where your app runs, making it easier to upgrade to different environments later.

Actions are now available in the Canary channel and will ship in the next release of React.

## New Features in React Canary {/*new-features-in-react-canary*/}

We introduced [React Canaries](/blog/2023/05/03/react-canaries) as an option to adopt individual new stable features as soon as their design is close to final, before they’re released in a stable semver version.

Canaries are a change to the way we develop React. Previously, features would be researched and built privately inside of Meta, so users would only see the final polished product when released to Stable. With Canaries, we’re building in public with the help of the community to finalize features we share in the React Labs blog series. This means you hear about new features sooner, as they’re being finalized instead of after they’re complete.

React Server Components, Asset Loading, Document Metadata, and Actions have all landed in the React Canary, and we've added docs for these features on react.dev:

- **Directives**: [`"use client"`](/reference/rsc/use-client) and [`"use server"`](/reference/rsc/use-server) are bundler features designed for full-stack React frameworks. They mark the "split points" between the two environments: `"use client"` instructs the bundler to generate a `<script>` tag (like [Astro Islands](https://docs.astro.build/en/concepts/islands/#creating-an-island)), while `"use server"` tells the bundler to generate a POST endpoint (like [tRPC Mutations](https://trpc.io/docs/concepts)). Together, they let you write reusable components that compose client-side interactivity with the related server-side logic.

- **Document Metadata**: we added built-in support for rendering [`<title>`](/reference/react-dom/components/title), [`<meta>`](/reference/react-dom/components/meta), and metadata [`<link>`](/reference/react-dom/components/link) tags anywhere in your component tree. These work the same way in all environments, including fully client-side code, SSR, and RSC. This provides built-in support for features pioneered by libraries like [React Helmet](https://github.com/nfl/react-helmet).

- **Asset Loading**: we integrated Suspense with the loading lifecycle of resources such as stylesheets, fonts, and scripts so that React takes them into account to determine whether the content in elements like [`<style>`](/reference/react-dom/components/style), [`<link>`](/reference/react-dom/components/link), and [`<script>`](/reference/react-dom/components/script) are ready to be displayed. We’ve also added new [Resource Loading APIs](/reference/react-dom#resource-preloading-apis) like `preload` and `preinit` to provide greater control for when a resource should load and initialize.

- **Actions**: As shared above, we've added Actions to manage sending data from the client to the server. You can add `action` to elements like [`<form/>`](/reference/react-dom/components/form), access the status with [`useFormStatus`](/reference/react-dom/hooks/useFormStatus), handle the result with [`useActionState`](/reference/react/useActionState), and optimistically update the UI with [`useOptimistic`](/reference/react/useOptimistic).

Since all of these features work together, it’s difficult to release them in the Stable channel individually. Releasing Actions without the complementary hooks for accessing form states would limit the practical usability of Actions. Introducing React Server Components without integrating Server Actions would complicate modifying data on the server.

Before we can release a set of features to the Stable channel, we need to ensure they work cohesively and developers have everything they need to use them in production. React Canaries allow us to develop these features individually, and release the stable APIs incrementally until the entire feature set is complete.

The current set of features in React Canary are complete and ready to release.

## The Next Major Version of React {/*the-next-major-version-of-react*/}

After a couple of years of iteration, `react@canary` is now ready to ship to `react@latest`. The new features mentioned above are compatible with any environment your app runs in, providing everything needed for production use. Since Asset Loading and Document Metadata may be a breaking change for some apps, the next version of React will be a major version: **React 19**.

There’s still more to be done to prepare for release. In React 19, we’re also adding long-requested improvements which require breaking changes like support for Web Components. Our focus now is to land these changes, prepare for release, finalize docs for new features, and publish announcements for what’s included.

We’ll share more information about everything React 19 includes, how to adopt the new client features, and how to build support for React Server Components in the coming months.

## Offscreen (renamed to Activity). {/*offscreen-renamed-to-activity*/}

Since our last update, we’ve renamed a capability we’re researching from “Offscreen” to “Activity”. The name “Offscreen” implied that it only applied to parts of the app that were not visible, but while researching the feature we realized that it’s possible for parts of the app to be visible and inactive, such as content behind a modal. The new name more closely reflects the behavior of marking certain parts of the app “active” or “inactive”.

Activity is still under research and our remaining work is to finalize the primitives that are exposed to library developers. We’ve deprioritized this area while we focus on shipping features that are more complete.

* * *

In addition to this update, our team has presented at conferences and made appearances on podcasts to speak more on our work and answer questions.

- [Sathya Gunasekaran](/community/team#sathya-gunasekaran) spoke about the React Compiler at the [React India](https://www.youtube.com/watch?v=kjOacmVsLSE) conference

- [Dan Abramov](/community/team#dan-abramov) gave a talk at [RemixConf](https://www.youtube.com/watch?v=zMf_xeGPn6s) titled “React from Another Dimension” which explores an alternative history of how React Server Components and Actions could have been created

- [Dan Abramov](/community/team#dan-abramov) was interviewed on [the Changelog’s JS Party podcast](https://changelog.com/jsparty/311) about React Server Components

- [Matt Carroll](/community/team#matt-carroll) was interviewed on the [Front-End Fire podcast](https://www.buzzsprout.com/2226499/14462424-interview-the-two-reacts-with-rachel-nabors-evan-bacon-and-matt-carroll) where he discussed [The Two Reacts](https://overreacted.io/the-two-reacts/)

Thanks [Lauren Tan](https://twitter.com/potetotes), [Sophie Alpert](https://twitter.com/sophiebits), [Jason Bonta](https://threads.net/someextent), [Eli White](https://twitter.com/Eli_White), and [Sathya Gunasekaran](https://twitter.com/_gsathya) for reviewing this post.

Thanks for reading, and [see you at React Conf](https://conf.react.dev/)!
Loading