diff --git a/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content-layout.tsx b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content-layout.tsx
new file mode 100644
index 000000000000..29cde6fb285c
--- /dev/null
+++ b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content-layout.tsx
@@ -0,0 +1,70 @@
+import type { DebugInfo } from '../../../../../shared/types'
+import type { ErrorType } from '../../../errors/error-type-label/error-type-label'
+
+import { ErrorMessage } from '../../../errors/error-message/error-message'
+import { ErrorOverlayToolbar } from '../../../errors/error-overlay-toolbar/error-overlay-toolbar'
+import { ErrorTypeLabel } from '../../../errors/error-type-label/error-type-label'
+import { EnvironmentNameLabel } from '../../../errors/environment-name-label/environment-name-label'
+import { IssueFeedbackButton } from '../../../errors/error-overlay-toolbar/issue-feedback-button'
+import { css } from '../../../../utils/css'
+
+// This behaves like the ErrorOverlayLayout.
+export function IssuesTabContentLayout({
+ error,
+ errorType,
+ message,
+ debugInfo,
+ children,
+ errorCode,
+ environmentName,
+}: {
+ error: Error & { environmentName?: string }
+ errorType: ErrorType
+ message: string
+ debugInfo: DebugInfo
+ children: React.ReactNode
+
+ errorCode?: string | null
+ environmentName?: string
+}) {
+ return (
+
+
+
+
+
+ {environmentName && (
+
+ )}
+
+
+ }
+ />
+
+
+
+ {children}
+
+ )
+}
+
+// The components in this file shares the style with the Error Overlay.
+export const DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_LAYOUT_STYLES = css`
+ [data-nextjs-devtools-panel-tab-issues-content-layout] {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ min-height: 0;
+ padding: 14px;
+ }
+`
diff --git a/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content.tsx b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content.tsx
index 283c47e0db78..9c8ab83a41f4 100644
--- a/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content.tsx
+++ b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content.tsx
@@ -1,19 +1,7 @@
import type { OverlayState } from '../../../../shared'
-import type { DebugInfo } from '../../../../../shared/types'
import type { ReadyRuntimeError } from '../../../../utils/get-error-by-type'
-import type { ErrorType } from '../../../errors/error-type-label/error-type-label'
import { Suspense, useMemo, useState } from 'react'
-
-import {
- GenericErrorDescription,
- HydrationErrorDescription,
-} from '../../../../container/errors'
-import { EnvironmentNameLabel } from '../../../errors/environment-name-label/environment-name-label'
-import { ErrorMessage } from '../../../errors/error-message/error-message'
-import { ErrorOverlayToolbar } from '../../../errors/error-overlay-toolbar/error-overlay-toolbar'
-import { ErrorTypeLabel } from '../../../errors/error-type-label/error-type-label'
-import { IssueFeedbackButton } from '../../../errors/error-overlay-toolbar/issue-feedback-button'
import { Terminal } from '../../../terminal'
import { HotlinkedText } from '../../../hot-linked-text'
import { PseudoHtmlDiff } from '../../../../container/runtime-error/component-stack-pseudo-html'
@@ -23,16 +11,22 @@ import { CallStack } from '../../../call-stack/call-stack'
import { NEXTJS_HYDRATION_ERROR_LINK } from '../../../../../shared/react-19-hydration-error'
import { ErrorContentSkeleton } from '../../../../container/runtime-error/error-content-skeleton'
import { css } from '../../../../utils/css'
+import { getErrorTextFromBuildErrorMessage } from '../../../../container/build-error'
+import { IssuesTabContentLayout } from './issues-tab-content-layout'
+import type { DebugInfo } from '../../../../../shared/types'
+import type { ErrorType } from '../../../errors/error-type-label/error-type-label'
+import { IssuesTabEmptyContent } from './issues-tab-empty-content'
+// This consists of the Build Error, Runtime Error, etc.
export function IssuesTabContent({
notes,
buildError,
hydrationWarning,
errorDetails,
activeError,
- errorCode,
errorType,
debugInfo,
+ errorCode,
}: {
notes: string | null
buildError: OverlayState['buildError']
@@ -41,49 +35,63 @@ export function IssuesTabContent({
hydrationWarning: string | null
notes: string | null
reactOutputComponentDiff: string | null
- }
- activeError: ReadyRuntimeError
- errorCode: string | undefined
- errorType: ErrorType
+ } | null
+ activeError: ReadyRuntimeError | null
+ errorType: ErrorType | null
debugInfo: DebugInfo
+ errorCode: string | null | undefined
}) {
if (buildError) {
- return
+ return
}
- const errorMessage = hydrationWarning ? (
-
- ) : (
-
+ return (
+
)
+}
+
+function ErrorContent({
+ notes,
+ hydrationWarning,
+ errorDetails,
+ activeError,
+ errorType,
+ debugInfo,
+ errorCode,
+}: {
+ notes: string | null
+ hydrationWarning: string | null
+ errorDetails: {
+ hydrationWarning: string | null
+ notes: string | null
+ reactOutputComponentDiff: string | null
+ } | null
+ activeError: ReadyRuntimeError | null
+ errorType: ErrorType | null
+ debugInfo: DebugInfo
+ errorCode: string | null | undefined
+}) {
+ if (!activeError || !errorType) {
+ return
+ }
return (
-
-
-
-
-
- {activeError.error.environmentName && (
-
- )}
-
-
- }
- />
-
-
-
+
{notes ? (
<>
@@ -106,7 +114,7 @@ export function IssuesTabContent({
) : null}
- {errorDetails.reactOutputComponentDiff ? (
+ {errorDetails?.reactOutputComponentDiff ? (
@@ -114,7 +122,7 @@ export function IssuesTabContent({
}>
-
+
)
}
@@ -161,14 +169,29 @@ function RuntimeError({ error }: { error: ReadyRuntimeError }) {
)
}
+function BuildError({
+ message,
+ debugInfo,
+}: {
+ message: string
+ debugInfo: DebugInfo
+}) {
+ const error = new Error(message)
+ const formattedMessage = useMemo(
+ () => getErrorTextFromBuildErrorMessage(message) || 'Failed to compile',
+ [message]
+ )
+ return (
+
+
+
+ )
+}
+
// The components in this file shares the style with the Error Overlay.
-export const DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_STYLES = css`
- [data-nextjs-devtools-panel-tab-issues-content-container] {
- flex: 1;
- display: flex;
- flex-direction: column;
- overflow-y: auto;
- min-height: 0;
- padding: 14px;
- }
-`
+export const DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_STYLES = css``
diff --git a/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-empty-content.tsx b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-empty-content.tsx
new file mode 100644
index 000000000000..89643c7e4d92
--- /dev/null
+++ b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-empty-content.tsx
@@ -0,0 +1,64 @@
+import { Warning } from '../../../../icons/warning'
+import { css } from '../../../../utils/css'
+
+export function IssuesTabEmptyContent() {
+ return (
+
+
+
+
+
+
+ No Issues Found
+
+
+ Issues will appear here when they occur.
+
+
+
+ )
+}
+
+export const DEVTOOLS_PANEL_TAB_ISSUES_EMPTY_CONTENT_STYLES = css`
+ [data-nextjs-devtools-panel-tab-issues-empty] {
+ display: flex;
+ flex: 1;
+ padding: 12px;
+ min-height: 0;
+ }
+
+ [data-nextjs-devtools-panel-tab-issues-empty-content] {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ flex: 1;
+ border: 1px dashed var(--color-gray-alpha-500);
+ border-radius: 4px;
+ }
+
+ [data-nextjs-devtools-panel-tab-issues-empty-icon] {
+ margin-bottom: 16px;
+ padding: 8px;
+ border: 1px solid var(--color-gray-alpha-400);
+ border-radius: 6px;
+
+ background-color: var(--color-background-100);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ [data-nextjs-devtools-panel-tab-issues-empty-title] {
+ color: var(--color-gray-1000);
+ font-size: 16px;
+ font-weight: 500;
+ line-height: var(--line-height-20);
+ }
+
+ [data-nextjs-devtools-panel-tab-issues-empty-subtitle] {
+ color: var(--color-gray-900);
+ font-size: 14px;
+ line-height: var(--line-height-21);
+ }
+`
diff --git a/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab.tsx b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab.tsx
index bebfc262bf58..e701ac0dae14 100644
--- a/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab.tsx
+++ b/packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab.tsx
@@ -7,7 +7,6 @@ import { IssuesTabSidebar } from './issues-tab-sidebar'
import { IssuesTabContent } from './issues-tab-content'
import { css } from '../../../../utils/css'
import { useActiveRuntimeError } from '../../../../hooks/use-active-runtime-error'
-import { Warning } from '../../../../icons/warning'
export function IssuesTab({
debugInfo,
@@ -31,43 +30,26 @@ export function IssuesTab({
errorDetails,
} = useActiveRuntimeError({ runtimeErrors, getSquashedHydrationErrorDetails })
- if (!activeError) {
- return (
-
-
-
-
-
-
- No Issues Found
-
-
- Issues will appear here when they occur.
-
-
-
- )
- }
-
return (
-
+ {buildError ? null : (
+
+ )}
- {/* This is the copy of the Error Overlay content. */}
)
@@ -79,46 +61,4 @@ export const DEVTOOLS_PANEL_TAB_ISSUES_STYLES = css`
flex: 1;
min-height: 0;
}
-
- [data-nextjs-devtools-panel-tab-issues-empty] {
- display: flex;
- flex: 1;
- padding: 12px;
- min-height: 0;
- }
-
- [data-nextjs-devtools-panel-tab-issues-empty-content] {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- flex: 1;
- border: 1px dashed var(--color-gray-alpha-500);
- border-radius: 4px;
- }
-
- [data-nextjs-devtools-panel-tab-issues-empty-icon] {
- margin-bottom: 16px;
- padding: 8px;
- border: 1px solid var(--color-gray-alpha-400);
- border-radius: 6px;
-
- background-color: var(--color-background-100);
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- [data-nextjs-devtools-panel-tab-issues-empty-title] {
- color: var(--color-gray-1000);
- font-size: 16px;
- font-weight: 500;
- line-height: var(--line-height-20);
- }
-
- [data-nextjs-devtools-panel-tab-issues-empty-subtitle] {
- color: var(--color-gray-900);
- font-size: 14px;
- line-height: var(--line-height-21);
- }
`
diff --git a/packages/next/src/next-devtools/dev-overlay/container/build-error.tsx b/packages/next/src/next-devtools/dev-overlay/container/build-error.tsx
index ad3eff8b70be..1261955262f8 100644
--- a/packages/next/src/next-devtools/dev-overlay/container/build-error.tsx
+++ b/packages/next/src/next-devtools/dev-overlay/container/build-error.tsx
@@ -8,7 +8,7 @@ export interface BuildErrorProps extends ErrorBaseProps {
message: string
}
-const getErrorTextFromBuildErrorMessage = (multiLineMessage: string) => {
+export const getErrorTextFromBuildErrorMessage = (multiLineMessage: string) => {
const lines = multiLineMessage.split('\n')
// The multi-line build error message looks like:
// ::
diff --git a/packages/next/src/next-devtools/dev-overlay/styles/component-styles.tsx b/packages/next/src/next-devtools/dev-overlay/styles/component-styles.tsx
index 5e3362cbc328..3d5f19b2267f 100644
--- a/packages/next/src/next-devtools/dev-overlay/styles/component-styles.tsx
+++ b/packages/next/src/next-devtools/dev-overlay/styles/component-styles.tsx
@@ -37,6 +37,8 @@ import { ISSUE_FEEDBACK_BUTTON_STYLES } from '../components/errors/error-overlay
import { ERROR_CONTENT_SKELETON_STYLES } from '../container/runtime-error/error-content-skeleton'
import { SEGMENTS_EXPLORER_TAB_STYLES } from '../components/devtools-panel/devtools-panel-tab/segments-explorer-tab'
import { SEGMENTS_EXPLORER_STYLES } from '../components/errors/dev-tools-indicator/dev-tools-info/segments-explorer'
+import { DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_LAYOUT_STYLES } from '../components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content-layout'
+import { DEVTOOLS_PANEL_TAB_ISSUES_EMPTY_CONTENT_STYLES } from '../components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-empty-content'
export function ComponentStyles() {
return (
@@ -74,9 +76,11 @@ export function ComponentStyles() {
${DEVTOOLS_PANEL_VERSION_INFO_STYLES}
${DEVTOOLS_PANEL_TAB_SETTINGS_STYLES}
${DEVTOOLS_PANEL_TAB_ISSUES_STYLES}
+ ${DEVTOOLS_PANEL_TAB_ISSUES_EMPTY_CONTENT_STYLES}
${DEVTOOLS_PANEL_TAB_ISSUES_SIDEBAR_STYLES}
${DEVTOOLS_PANEL_TAB_ISSUES_SIDEBAR_FRAME_SKELETON_STYLES}
${DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_STYLES}
+ ${DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_LAYOUT_STYLES}
${ISSUE_FEEDBACK_BUTTON_STYLES}
${ERROR_CONTENT_SKELETON_STYLES}
${SEGMENTS_EXPLORER_TAB_STYLES}