Skip to content

Console - Full-screen page mode for SQL and RPCN editors - #2576

Merged
SpicyPete merged 11 commits into
masterfrom
polish/full-screen-rpcn-support
Aug 4, 2026
Merged

Console - Full-screen page mode for SQL and RPCN editors#2576
SpicyPete merged 11 commits into
masterfrom
polish/full-screen-rpcn-support

Conversation

@SpicyPete

Copy link
Copy Markdown
Contributor

Summary

  • Footer pins to the viewport bottom on short pages.
  • Topics and security-tab pages drop ListLayout's forced min-h-screen (min-h-0 override), removing large dead whitespace at bottom.
  • Embedded Console cancels the Cloud UI host gutters with measured negative margins and owns its page gutter (px-12) — deploy-order-safe with cloud-ui removing its p-10 later.
  • New expanded-page mode: data-page-expanded on (utils/page-expanded)
    • useExpandedPageMode hook release every shell's horizontal constraints via global CSS while the page stays in document flow, footer below. The SQL studio's fixed-overlay fullscreen is replaced by this in-flow mode, and the RPCN pipeline editor gains the same toggle; both place the shared ExpandedPageToggle at the top-right of their work surface, clear of Save.
  • /sql becomes a normal route; new breadcrumbOnlyHeader staticData flag keeps the app header breadcrumb-only for pages with their own title bar.

Screenshots

Footer always bottom

Before -> After
Screenshot 2026-07-23 at 2 21 26 PM
Screenshot 2026-07-23 at 2 21 45 PM

RPCN full screen
Screenshot 2026-07-23 at 2 22 30 PM Screenshot 2026-07-23 at 2 22 43 PM Screenshot 2026-07-23 at 2 23 00 PM

SpicyPete and others added 2 commits July 23, 2026 14:02
- Footer pins to the viewport bottom on short pages (CSS flex chain in
  standalone, measured min-height in embedded) and keeps centering to the
  content column; bottom padding 8px -> 16px.
- Topics and security-tab pages drop ListLayout's forced min-h-screen
  (min-h-0 override), removing large dead whitespace.
- Embedded Console cancels the Cloud UI host gutters with measured negative
  margins and owns its page gutter (px-12) — deploy-order-safe with cloud-ui
  removing its p-10 later.
- New expanded-page mode: data-page-expanded on <html> (utils/page-expanded)
  + useExpandedPageMode hook release every shell's horizontal constraints via
  global CSS while the page stays in document flow, footer below. The SQL
  studio's fixed-overlay fullscreen is replaced by this in-flow mode, and the
  RPCN pipeline editor gains the same toggle; both place the shared
  ExpandedPageToggle at the top-right of their work surface, clear of Save.
- /sql becomes a normal route; new breadcrumbOnlyHeader staticData flag keeps
  the app header breadcrumb-only for pages with their own title bar.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🚨 Registry drift detected

App: frontend · Scope: diff vs origin/master · Files: 20

Count
⚠️ Outdated registry components 2
🛠 Locally-modified components 1
❓ Unknown to registry 0
🎨 Off-token palette colours 0
🔢 Ad-hoc utility classes 0
Components needing attention
Status Component Uses Detail
⚠️ outdated data-table installed 2.4.0 → latest 2.4.1
⚠️ outdated tabs installed 2.4.0 → latest 2.4.1
🛠 locally-modified theme no tagged release matches installed bytes

Refresh command:

bunx shadcn@latest add @redpanda/data-table @redpanda/tabs --overwrite

Generated by lookout audit-changes.

@SpicyPete

Copy link
Copy Markdown
Contributor Author

@claude review

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Claude finished @SpicyPete's task in 3m 1s —— View job


Code review

  • Read the diff and new files
  • Analyze layout/CSS changes (footer, expanded-page mode)
  • Analyze RPCN + SQL editor changes
  • Analyze routing / federation changes
  • Post review feedback

Reviewed against origin/master (PR range ce69db1..HEAD). Overall this is a strong, well-reasoned change — the standout is replacing the SQL studio's imperative fixed-overlay + scroll-lock machinery (-274 lines) with a shared in-flow useExpandedPageMode hook reused by RPCN. The comments explaining the why (measured margins for deploy-order safety, visibility via ResizeObserver, specificity of the global CSS) are genuinely helpful. Nicely done.

A few things worth a look before merge:


1. measureReservedBelow counts #mainLayout's own (negative) bottom margin — footer.tsx

In embedded mode useCancelHostGutters writes a negative margin-bottom onto #mainLayout. measureReservedBelow adds the target's own marginBottom into reserved:

for (let el = target; el && el !== document.documentElement; el = el.parentElement) {
  reserved += Number.parseFloat(style.marginBottom) || 0;   // target's own margin included
  ...
}

A negative marginBottom makes reserved negative, which inflates minHeight by the host's bottom-padding amount, so #mainLayout can be stretched slightly taller than the viewport → spurious vertical scrollbar in embedded mode. The MutationObserver on style re-measures but converges to the same inflated value. Consider clamping the target's own margin contribution to >= 0, or skipping the target's margin entirely (a negative margin isn't "reserved space below"). Worth verifying visually in the embedded Cloud UI host. Fix this →

2. Hardcoded h-[calc(100dvh-7rem)] in embedded mode — sql-workspace.tsx / RPCN index.tsx

The comment reads "7rem = app header + pt-8". That's correct for the self-hosted __root layout, but the federated layout (federated-routes.tsx) doesn't render Console's app header (the host does) and doesn't wrap the outlet in pt-8. So in embedded mode the real top offset differs from 7rem, and the surface can end up short or overflow by that delta. Since RPCN already shipped this way it may be acceptable in practice — but now that SQL adopts the same value, it'd be good to confirm both look right embedded, or derive the offset rather than hardcode it.

3. Two JS mechanisms both mutate #mainLayout and observe overlapping nodes

useBottomPinnedFooter sets min-height while useCancelHostGutters sets margin, and the footer's MutationObserver intentionally re-fires on the margin write. The change-guards mean it converges (cancel-gutters doesn't observe #mainLayout itself, so there's no true cycle), but it's worth a quick check for ResizeObserver loop completed with undelivered notifications warnings in embedded mode under resize. Not blocking, just a watch item.

4. max-width: 100vw in the release rule — index.scss

100vw includes the scrollbar gutter, so it can exceed the available content width when a vertical scrollbar is present (classic 100vw overflow gotcha). Here it's a max-width cap on a flex/container child whose width is already parent-bound, so it likely never binds — but 100% would sidestep the gotcha entirely if the cap is only there to give the transition something to animate to.


Minor / nits

  • ListLayout internally does cn('... min-h-screen ...', className), so the min-h-0 overrides passed on topics/security tabs resolve correctly via tailwind-merge. ✅ Good, verified.
  • useExpandedPageMode correctly clears data-page-expanded on unmount via the ref(null) callback and on display:none via the ResizeObserver 0×0 signal — the stale-attribute-bleeds-to-next-page risk called out in the doc comment is handled. ✅
  • SQL keeps the prior rp-sql-studio-mode storage key, so existing user fullscreen prefs carry over. ✅
  • Hook ordering in AppFooter is safe — useBottomPinnedFooter(hidden) is called before the if (hidden) return null. ✅
  • ExpandedPageToggle has both aria-label and title. ✅

Nothing here is a hard blocker; #1 is the one I'd most want confirmed against the embedded host. I didn't run the build/tests (review-only) — bun run type:check && bun run lint && bun run test per the frontend guide would be the standard gate.
· branch polish/full-screen-rpcn-support

* Attach `ref` to the page root — the attribute is held only while the root is
* visible (embedded Cloud UI keeps Console mounted but hidden on host routes).
*/
export function useExpandedPageMode({ storageKey }: { storageKey: string }): {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm missing where we unset this when the page is unmounted. iirc there's a tanstack util that can help with this when you change routes

Comment on lines +89 to +93
/**
* Cancels the host gutters around the federated Console outlet with equal negative
* margins. Measured, not hardcoded, so either project can deploy first. Top padding
* is left alone — cancelling it would pull Console under the host's header.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to do this is classname specificity on the body element rather than in a use layout effect? has a weird code smell to it..

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in this case, as the padding is coming from CloudV2, so this is to account for when CloudV2 removes that padding, we don't want to double-add it in the meantime while the deploys differ, especially when there may be older version of console running.

Comment thread frontend/src/index.scss

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not extend the SCSS file unless we can help it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will have to modify a SCSS file, but I moved it to globals instead

<div className="container mx-auto max-w-[1500px] px-12">
{/* Centered page column; the gutter and the width cap are released while a
page is expanded (index.scss). */}
<div className="page-expanded-flush page-expanded-uncap container mx-auto flex max-w-[1500px] flex-1 flex-col px-12 transition-[max-width,padding] duration-300 ease-in-out">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we stick to tailwind?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so in this case, or at least not in a way which is as understandable, as we have to add a class which targets attributes at the body level, which is owned by the CloudV2 federating app most of the time

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. The variant CSS isn't reliably in the loaded stylesheets. Expressed as an arbitrary variant on the element — [html[data-page-expanded]_&]:px-0 on #mainLayout — the generated rule was present when loading /sql and absent when loading /rp-connect/create: same element, same class string, full page loads both times. Plain px-12 applied everywhere; only the variant rule was chunk-dependent in the federated build. A @custom-variant doesn't help — it's still a JIT-generated utility subject to the same chunking. Hand-written CSS in an entry stylesheet is always loaded.

  2. Two apps have to release in lockstep. The attribute is a contract with Cloud UI: Console drops its gutter and width cap while cloud-ui's wrapper drops expandableWidth. Only one side of that lives in this repo's className strings; the signal has to be a document-level attribute either way.

  3. The state isn't the element's own. Whether the page is expanded is set by a hook on , not by the component rendering #mainLayout — so a utility on that element would have to be conditionally applied by a component that doesn't own the state, which is what the release-hook classes avoid.

@SpicyPete

Copy link
Copy Markdown
Contributor Author

Failure seems to be related to a console-enterprise change, will fix it there if it isn't fixed by Tuesday

);
};

// Bottom placement is CSS: `.footer` has `margin-top: auto` inside #mainLayout's flex column.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is so useful while we still have scss styles using selectors here

return (
<div>
// Expanded pages release #mainLayout's gutter; keep the header off the viewport edge.
<div className="page-expanded-inset transition-[padding] duration-300 ease-in-out">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

surprised you don't have to use a template string for [padding] is that some new tailwind compiler thing that maps to a var?

@eblairmckee eblairmckee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this is fine for now. albeit over engineered in some sense because we're having to deal with scss, tailwind, and interpolated styles.. but long term i would LOVE to just kill chakra from layouts altogether in cloud and console.
all said, I do feel good seeing the LOC diff being nearly 0

Image

@SpicyPete
SpicyPete merged commit 8a1932d into master Aug 4, 2026
17 checks passed
@SpicyPete
SpicyPete deleted the polish/full-screen-rpcn-support branch August 4, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants