Repository: vercel/next.js
Pull request: [devtools] add correct scrollbar to dialog body

Since the scrollbar is applied to the whole dialog by default, the header and the footer, which are children of the dialog, were also included in the overflow. Therefore, this PR ensures that the DevTools panel's dialog only targets the dialog body to have the overflow.

### Before

https://github.com/user-attachments/assets/82722635-6f8c-4608-9b73-9e60090dbbfe

### After

https://github.com/user-attachments/assets/0fb4e9a2-bac6-493b-96bf-fec796a15455

Changed files:
filename: packages/next/src/next-devtools/dev-overlay/components/devtools-panel/devtools-panel.tsx
patch: @@ -97,7 +97,7 @@ export function DevToolsPanel({
             aria-describedby="nextjs__container_dev_tools_panel_desc"
             onClose={onCloseDevToolsPanel}
           >
-            <DialogContent>
+            <DialogContent data-nextjs-devtools-panel-dialog-content>
               <DialogHeader data-nextjs-devtools-panel-dialog-header>
                 <div data-nextjs-devtools-panel-header>
                   <div data-nextjs-devtools-panel-header-tab-group>
@@ -143,7 +143,7 @@ export function DevToolsPanel({
                   </div>
                 </div>
               </DialogHeader>
-              <DialogBody>
+              <DialogBody data-nextjs-devtools-panel-dialog-body>
                 <DevToolsPanelTab
                   activeTab={activeTab}
                   devToolsPosition={state.devToolsPosition}
@@ -172,6 +172,20 @@ export const DEVTOOLS_PANEL_STYLES = css`
     margin-bottom: 0 !important;
   }
 
+  [data-nextjs-devtools-panel-dialog-content] {
+    /* Make DialogContent expand to push footer to bottom. */
+    flex: 1;
+    /* Hide overflow of devtools panel dialog since we want it on the dialog body only. */
+    overflow: hidden;
+  }
+
+  [data-nextjs-devtools-panel-dialog-body] {
+    overflow: auto;
+    /* Make DialogBody a flex container so its children can expand. */
+    display: flex;
+    flex-direction: column;
+  }
+
   [data-nextjs-devtools-panel-overlay] {
     padding: initial;
     margin: auto;
@@ -218,7 +232,6 @@ export const DEVTOOLS_PANEL_STYLES = css`
     border-radius: var(--rounded-xl);
     box-shadow: var(--shadow-lg);
     position: relative;
-    overflow-y: auto;
     width: 100%;
     max-height: 50vh;
     min-height: 450px;

filename: packages/next/src/next-devtools/dev-overlay/components/dialog/dialog-body.tsx
patch: @@ -3,14 +3,15 @@ import * as React from 'react'
 export type DialogBodyProps = {
   children?: React.ReactNode
   className?: string
-}
+} & React.HTMLAttributes<HTMLDivElement>
 
 const DialogBody: React.FC<DialogBodyProps> = function DialogBody({
   children,
   className,
+  ...props
 }) {
   return (
-    <div data-nextjs-dialog-body className={className}>
+    <div data-nextjs-dialog-body className={className} {...props}>
       {children}
     </div>
   )

filename: packages/next/src/next-devtools/dev-overlay/components/dialog/dialog-content.tsx
patch: @@ -3,14 +3,15 @@ import * as React from 'react'
 export type DialogContentProps = {
   children?: React.ReactNode
   className?: string
-}
+} & React.HTMLAttributes<HTMLDivElement>
 
 const DialogContent: React.FC<DialogContentProps> = function DialogContent({
   children,
   className,
+  ...props
 }) {
   return (
-    <div data-nextjs-dialog-content className={className}>
+    <div data-nextjs-dialog-content className={className} {...props}>
       {children}
     </div>
   )