From 58605ab53355424b1ec2b7679f1bc872fe6747f2 Mon Sep 17 00:00:00 2001
From: devjiwonchoi
Date: Wed, 18 Dec 2024 21:27:49 +0900
Subject: [PATCH 1/4] Create ErrorOverlay component
---
packages/next/.storybook/main.ts | 20 +++++-
.../ErrorOverlay/ErrorOverlay.stories.tsx | 27 ++++++++
.../components/ErrorOverlay/ErrorOverlay.tsx | 58 ++++++++++++++++
.../internal/container/BuildError.tsx | 62 +++++------------
.../root-layout-missing-tags-error.tsx | 66 +++++++------------
.../internal/storybook/with-shadow-portal.tsx | 13 ++++
6 files changed, 156 insertions(+), 90 deletions(-)
create mode 100644 packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.stories.tsx
create mode 100644 packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.tsx
create mode 100644 packages/next/src/client/components/react-dev-overlay/_experimental/internal/storybook/with-shadow-portal.tsx
diff --git a/packages/next/.storybook/main.ts b/packages/next/.storybook/main.ts
index 366f443b0d239..0d7b170179eb0 100644
--- a/packages/next/.storybook/main.ts
+++ b/packages/next/.storybook/main.ts
@@ -11,8 +11,9 @@ function getAbsolutePath(value: string): any {
}
const config: StorybookConfig = {
stories: [
- '../stories/**/*.mdx',
- '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)',
+ // Could to '../src/**/*.stories.@(ts|tsx)', but not sure how much it'll affect perf.
+ // Scoped to experimental dev overlay for now.
+ '../src/client/components/react-dev-overlay/_experimental/**/*.stories.@(ts|tsx)',
],
addons: [
getAbsolutePath('@storybook/addon-webpack5-compiler-swc'),
@@ -23,7 +24,20 @@ const config: StorybookConfig = {
],
framework: {
name: getAbsolutePath('@storybook/react-webpack5'),
- options: {},
+ options: {
+ builder: {
+ useSWC: true,
+ },
+ },
},
+ swc: () => ({
+ jsc: {
+ transform: {
+ react: {
+ runtime: 'automatic',
+ },
+ },
+ },
+ }),
}
export default config
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.stories.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.stories.tsx
new file mode 100644
index 0000000000000..3875cd20f1559
--- /dev/null
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.stories.tsx
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/react'
+import { ErrorOverlay } from './ErrorOverlay'
+import { withShadowPortal } from '../../storybook/with-shadow-portal'
+
+const meta: Meta = {
+ title: 'Overlays/ErrorOverlay',
+ component: ErrorOverlay,
+ parameters: {
+ layout: 'fullscreen',
+ },
+ decorators: [withShadowPortal],
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ errorType: 'Build Error',
+ errorMessage: 'Failed to compile',
+ versionInfo: {
+ installed: '15.0.0',
+ staleness: 'fresh',
+ },
+ children: "Module not found: Cannot find module './missing-module'",
+ },
+}
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.tsx
new file mode 100644
index 0000000000000..3c704eb04ee02
--- /dev/null
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.tsx
@@ -0,0 +1,58 @@
+import type { VersionInfo } from '../../../../../../../server/dev/parse-version-info'
+import { Dialog, DialogHeader, DialogBody, DialogContent } from '../Dialog'
+import { Overlay } from '../Overlay'
+import { VersionStalenessInfo } from '../VersionStalenessInfo'
+
+type ErrorOverlayProps = {
+ errorType:
+ | 'Build Error'
+ | 'Runtime Error'
+ | 'Console Error'
+ | 'Unhandled Runtime Error'
+ | 'Missing Required HTML Tag'
+ errorMessage: string | React.ReactNode
+ onClose: () => void
+ versionInfo?: VersionInfo
+ children?: React.ReactNode
+}
+
+export function ErrorOverlay({
+ errorType,
+ errorMessage,
+ onClose,
+ children,
+ versionInfo,
+}: ErrorOverlayProps) {
+ const isBuildError = errorType === 'Build Error'
+ return (
+
+
+
+ )
+}
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx
index 806769d1cd8a6..bbb70c99150ad 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx
@@ -1,15 +1,8 @@
import * as React from 'react'
import type { VersionInfo } from '../../../../../../server/dev/parse-version-info'
-import {
- Dialog,
- DialogBody,
- DialogContent,
- DialogHeader,
-} from '../components/Dialog'
-import { Overlay } from '../components/Overlay'
import { Terminal } from '../components/Terminal'
-import { VersionStalenessInfo } from '../components/VersionStalenessInfo'
import { noop as css } from '../helpers/noop-template'
+import { ErrorOverlay } from '../components/ErrorOverlay/ErrorOverlay'
export type BuildErrorProps = { message: string; versionInfo?: VersionInfo }
@@ -19,43 +12,22 @@ export const BuildError: React.FC = function BuildError({
}) {
const noop = React.useCallback(() => {}, [])
return (
-
-
-
+
+
+
+
)
}
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx
index 407b09a5fd9a9..7c6f92b14fa3b 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx
@@ -1,50 +1,32 @@
-import * as React from 'react'
import type { VersionInfo } from '../../../../../../server/dev/parse-version-info'
-import { Dialog, DialogContent, DialogHeader } from '../components/Dialog'
-import { Overlay } from '../components/Overlay'
-import { VersionStalenessInfo } from '../components/VersionStalenessInfo'
+import { useCallback } from 'react'
import { HotlinkedText } from '../components/hot-linked-text'
+import { ErrorOverlay } from '../components/ErrorOverlay/ErrorOverlay'
type RootLayoutMissingTagsErrorProps = {
missingTags: string[]
versionInfo?: VersionInfo
}
-export const RootLayoutMissingTagsError: React.FC =
- function RootLayoutMissingTagsError({ missingTags, versionInfo }) {
- const noop = React.useCallback(() => {}, [])
- return (
-
-
-
- )
- }
+export function RootLayoutMissingTagsError({
+ missingTags,
+ versionInfo,
+}: RootLayoutMissingTagsErrorProps) {
+ const noop = useCallback(() => {}, [])
+ return (
+ `<${tagName}>`)
+ .join(
+ ', '
+ )}.\nRead more at https://nextjs.org/docs/messages/missing-root-layout-tags`}
+ />
+ }
+ onClose={noop}
+ versionInfo={versionInfo}
+ />
+ )
+}
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/storybook/with-shadow-portal.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/storybook/with-shadow-portal.tsx
new file mode 100644
index 0000000000000..422a3ee1dd46f
--- /dev/null
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/storybook/with-shadow-portal.tsx
@@ -0,0 +1,13 @@
+import { Base } from '../styles/Base'
+import { CssReset } from '../styles/CssReset'
+import { ComponentStyles } from '../styles/ComponentStyles'
+import { ShadowPortal } from '../components/ShadowPortal'
+
+export const withShadowPortal = (Story: any) => (
+
+
+
+
+
+
+)
From 9a29812df5b3390924e77e80add6e7e38468321b Mon Sep 17 00:00:00 2001
From: devjiwonchoi
Date: Thu, 19 Dec 2024 01:26:58 +0900
Subject: [PATCH 2/4] change name to layout
Co-authored-by: Jude Gao
---
.../ErrorOverlayLayout.stories.tsx} | 10 +++++-----
.../ErrorOverlayLayout.tsx} | 6 +++---
.../_experimental/internal/container/BuildError.tsx | 6 +++---
.../container/root-layout-missing-tags-error.tsx | 4 ++--
4 files changed, 13 insertions(+), 13 deletions(-)
rename packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/{ErrorOverlay/ErrorOverlay.stories.tsx => ErrorOverlayLayout/ErrorOverlayLayout.stories.tsx} (69%)
rename packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/{ErrorOverlay/ErrorOverlay.tsx => ErrorOverlayLayout/ErrorOverlayLayout.tsx} (94%)
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.stories.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.stories.tsx
similarity index 69%
rename from packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.stories.tsx
rename to packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.stories.tsx
index 3875cd20f1559..0996dde10a860 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.stories.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.stories.tsx
@@ -1,10 +1,10 @@
import type { Meta, StoryObj } from '@storybook/react'
-import { ErrorOverlay } from './ErrorOverlay'
+import { ErrorOverlayLayout } from './ErrorOverlayLayout'
import { withShadowPortal } from '../../storybook/with-shadow-portal'
-const meta: Meta = {
- title: 'Overlays/ErrorOverlay',
- component: ErrorOverlay,
+const meta: Meta = {
+ title: 'ErrorOverlayLayout',
+ component: ErrorOverlayLayout,
parameters: {
layout: 'fullscreen',
},
@@ -12,7 +12,7 @@ const meta: Meta = {
}
export default meta
-type Story = StoryObj
+type Story = StoryObj
export const Default: Story = {
args: {
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.tsx
similarity index 94%
rename from packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.tsx
rename to packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.tsx
index 3c704eb04ee02..715a4898cf6d8 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlay/ErrorOverlay.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.tsx
@@ -3,7 +3,7 @@ import { Dialog, DialogHeader, DialogBody, DialogContent } from '../Dialog'
import { Overlay } from '../Overlay'
import { VersionStalenessInfo } from '../VersionStalenessInfo'
-type ErrorOverlayProps = {
+type ErrorOverlayLayoutProps = {
errorType:
| 'Build Error'
| 'Runtime Error'
@@ -16,13 +16,13 @@ type ErrorOverlayProps = {
children?: React.ReactNode
}
-export function ErrorOverlay({
+export function ErrorOverlayLayout({
errorType,
errorMessage,
onClose,
children,
versionInfo,
-}: ErrorOverlayProps) {
+}: ErrorOverlayLayoutProps) {
const isBuildError = errorType === 'Build Error'
return (
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx
index bbb70c99150ad..9112354875d37 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/BuildError.tsx
@@ -2,7 +2,7 @@ import * as React from 'react'
import type { VersionInfo } from '../../../../../../server/dev/parse-version-info'
import { Terminal } from '../components/Terminal'
import { noop as css } from '../helpers/noop-template'
-import { ErrorOverlay } from '../components/ErrorOverlay/ErrorOverlay'
+import { ErrorOverlayLayout } from '../components/ErrorOverlayLayout/ErrorOverlayLayout'
export type BuildErrorProps = { message: string; versionInfo?: VersionInfo }
@@ -12,7 +12,7 @@ export const BuildError: React.FC = function BuildError({
}) {
const noop = React.useCallback(() => {}, [])
return (
- = function BuildError({
-
+
)
}
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx
index 7c6f92b14fa3b..85b9ebae09226 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/root-layout-missing-tags-error.tsx
@@ -1,7 +1,7 @@
import type { VersionInfo } from '../../../../../../server/dev/parse-version-info'
import { useCallback } from 'react'
import { HotlinkedText } from '../components/hot-linked-text'
-import { ErrorOverlay } from '../components/ErrorOverlay/ErrorOverlay'
+import { ErrorOverlayLayout } from '../components/ErrorOverlayLayout/ErrorOverlayLayout'
type RootLayoutMissingTagsErrorProps = {
missingTags: string[]
@@ -14,7 +14,7 @@ export function RootLayoutMissingTagsError({
}: RootLayoutMissingTagsErrorProps) {
const noop = useCallback(() => {}, [])
return (
-
Date: Thu, 19 Dec 2024 01:31:48 +0900
Subject: [PATCH 3/4] fix leaky abstraction on isBuildError
Co-authored-by: Jude Gao
---
.../components/ErrorOverlayLayout/ErrorOverlayLayout.tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.tsx
index 715a4898cf6d8..3764634019c3f 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/ErrorOverlayLayout/ErrorOverlayLayout.tsx
@@ -12,6 +12,7 @@ type ErrorOverlayLayoutProps = {
| 'Missing Required HTML Tag'
errorMessage: string | React.ReactNode
onClose: () => void
+ isBuildError?: boolean
versionInfo?: VersionInfo
children?: React.ReactNode
}
@@ -22,8 +23,8 @@ export function ErrorOverlayLayout({
onClose,
children,
versionInfo,
+ isBuildError,
}: ErrorOverlayLayoutProps) {
- const isBuildError = errorType === 'Build Error'
return (