Skip to content

fix(ui): usable phone layout - drawer sidebar, no overlapping bars (#189) - #671

Open
SpyrosPsarras wants to merge 2 commits into
PegaProx:Testingfrom
SpyrosPsarras:fix/issue-189-mobile-layout
Open

fix(ui): usable phone layout - drawer sidebar, no overlapping bars (#189)#671
SpyrosPsarras wants to merge 2 commits into
PegaProx:Testingfrom
SpyrosPsarras:fix/issue-189-mobile-layout

Conversation

@SpyrosPsarras

@SpyrosPsarras SpyrosPsarras commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

User description

Fixes the worst of #189. This is not the multi-week mobile pass discussed in
that issue - it is a pragmatic layer that takes a phone from "unusable" to
"usable", with no desktop impact.

Why

On a Pixel 8 (412px wide) the dashboard was unusable:

  • the sidebar is a fixed 288px, so it ate most of the screen and squeezed the
    content into a strip
  • content overflowed sideways, so the page background showed as a white band
    on the right
  • the header did not wrap, so the global search box landed on top of the title
  • the fixed bottom Tasks bar covered a strip of content at every scroll position
  • tab labels truncated to "All Clus...", "Overvi..."

There was no phone logic in the codebase at all - no isMobile, no drawer, and
only 4 @media rules in the whole shell, the smallest at max-width: 768px.

What changed

One @media (max-width: 820px) block in web/index.html.original, plus a small
amount of JSX in web/src/dashboard.js. Every CSS rule lives inside that media
query, so desktop is untouched.

  • Sidebar → drawer. Off-canvas, slides in from the left. The hamburger
    toggle sits in the header, so it is always reachable and cannot paint over
    content. Backdrop closes it.
  • Header wraps. The global search gets its own full-width line.
  • Tasks bar goes static on phones instead of being fixed to the bottom.
  • Tables scroll sideways instead of being crushed.
  • Modals capped to the viewport.
  • Tab strip scrolls instead of truncating labels.

JS is limited to the drawer: one mobileSidebarOpen state, a toggle button and
a backdrop.

Note on overflow-x

html, body { overflow-x: clip }, not hidden. hidden turns the element into
a scroll container, which kills position: sticky on the header. Worth writing
down, it cost a round of testing.

Testing

Built with web/Dev/build.sh and deployed to a real 1.0 instance, then checked
on a Pixel 8 in Firefox Mobile and at 412px / 1400px in a desktop browser.

  • 412px: no horizontal overflow, drawer opens and closes, header does not
    overlap, Tasks bar no longer covers content, sticky header still sticks
  • 1400px: Tasks bar still fixed, hamburger hidden, sidebar static, no change

Known limits

  • Tapping an item in the drawer does not auto-close it, the backdrop does. Easy
    follow-up if it annoys people.
  • This does not touch touch-target sizing or the per-table mobile design the
    issue asks for. It is a layout layer, not the redesign.

CodeAnt-AI Description

Make the dashboard usable on phone-sized screens

What Changed

  • Replaced the full-width sidebar with an off-canvas drawer that opens from a header button, closes with a backdrop or close button, and closes after navigation.
  • Reflowed the header so search has its own line without covering the page title; search results now fit within the phone’s search field.
  • Removed the fixed bottom Tasks bar on phones so it no longer covers page content.
  • Let tables, tabs, and oversized content scroll or wrap within the available screen width.
  • Capped modals and their contents to the phone viewport.

Impact

✅ Usable navigation on 412px phone screens
✅ No content hidden behind the Tasks bar
✅ Search, tables, tabs, and modals fit narrow screens

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features
    • Added a responsive mobile layout for improved usability on smaller screens.
    • Introduced an off-canvas sidebar with toggle, close, and backdrop controls.
    • Sidebar automatically closes after navigation.
    • Improved mobile handling for headers, search, task bars, tables, popups, and horizontally scrolling tabs.
    • Desktop behavior remains unchanged.

…egaProx#189)

The dashboard was built for wide screens only. On a 412px phone the sidebar
alone took 288px, the content overflowed sideways, and the header, the tab
strip and the fixed Tasks bar all covered each other.

This is a CSS-first mobile layer behind a single `@media (max-width: 820px)`
block. Desktop rendering is unchanged - every rule lives inside that block.

- sidebar becomes an off-canvas drawer, with a hamburger toggle in the header
  and a backdrop that closes it
- the header row wraps, so the global search gets its own full-width line
  instead of landing on top of the title
- the fixed bottom Tasks bar goes static on phones, so it stops covering a
  strip of content at every scroll position
- wide tables scroll sideways instead of being crushed
- modals are capped to the viewport
- the tab strip scrolls instead of truncating labels to "All Clus..."

`overflow-x: clip` (not `hidden`) on html/body: `hidden` turns the element
into a scroll container and kills the sticky header.

Only the drawer needs JS - one `mobileSidebarOpen` state, a toggle button and
a backdrop. Everything else is CSS.
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@codeant-ai-for-open-source codeant-ai-for-open-source Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Aug 8, 2026
Comment thread web/index.html.original Outdated
.pp-header-search input { width: 100% !important; }

/* wide tables scroll sideways instead of being crushed */
table { display: block; width: 100%; overflow-x: auto; white-space: nowrap; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Scope this mobile table rule to the application table wrapper or a dedicated responsive-table class instead of styling every table globally, so unrelated tables and embedded components do not inherit block layout, nowrap text, and horizontal scrolling. [custom_rule]

Severity Level: Major ⚠️

Why it matters? ⭐

The rule applies globally to every table at phone widths, including tables in unrelated or embedded components. This creates avoidable coupling because all such tables inherit block layout, nowrap text, and horizontal scrolling, so scoping the rule to the application’s responsive table wrapper would improve maintainability without changing the intended mobile behavior.

Rule source 📖

CodeAnt dashboard (rule "agent-persona-maintainability")

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/index.html.original
**Line:** 3550:3550
**Comment:**
	*Custom Rule: Scope this mobile table rule to the application table wrapper or a dedicated responsive-table class instead of styling every table globally, so unrelated tables and embedded components do not inherit block layout, nowrap text, and horizontal scrolling.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

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.

Partly fixed in fc7fd68.

Dropped white-space: nowrap, which was the part that actually leaked into unrelated tables - property grids can wrap again.

Kept display: block + overflow-x: auto global on purpose. Scoping it means adding a class to 130+ <table> elements across 20 files, and for a table that already sits in an overflow-x-auto wrapper the extra scroll box is inert - the inner box only scrolls when a row really is wider than it. Happy to do the wrapper class instead if you would rather have it scoped properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Customized review instruction saved!

Instruction:

Do not flag the intentional global use of display:block and overflow-x:auto on tables; retain this behavior to support existing tables without adding responsive wrapper classes.

Applied to:

  • web/index.html.original

💡 To manage or update this instruction, visit: CodeAnt AI Settings

Comment thread web/index.html.original
Comment on lines +3554 to +3557
.modal-backdrop > *, .corp-vm-modal-overlay > * {
width: 100% !important; max-width: 100% !important;
max-height: 88vh !important; overflow-y: auto;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Replace this broad descendant selector with a modal-specific content class or explicit modal container selector, so every direct child of every modal does not unexpectedly become a full-width scroll container on phones. [custom_rule]

Severity Level: Major ⚠️

Why it matters? ⭐

The selector affects every direct child of every matching modal overlay, rather than specifically targeting the modal panel. As modal structures evolve or contain multiple direct children, unrelated elements can unexpectedly receive full-width sizing and scrolling, creating avoidable coupling and making the CSS harder to maintain. A dedicated modal-content selector would preserve the intended behavior more safely.

Rule source 📖

CodeAnt dashboard (rule "agent-persona-maintainability")

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/index.html.original
**Line:** 3554:3557
**Comment:**
	*Custom Rule: Replace this broad descendant selector with a modal-specific content class or explicit modal container selector, so every direct child of every modal does not unexpectedly become a full-width scroll container on phones.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

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.

Fixed in fc7fd68.

Dropped the width: 100% !important, which was the part that stretched every direct child. Kept max-width / max-height, so a modal that already fits is untouched and only an oversized one gets capped.

A dedicated modal-content class would be cleaner, but the pattern is fixed inset-0 ... modal-backdrop with the panel as the direct child in ~100 places, so that is a separate sweep.

Comment thread web/index.html.original
Comment on lines +3488 to +3494
.pp-sidebar {
position: fixed !important;
top: 0; left: 0; bottom: 0;
width: min(85vw, 300px) !important;
z-index: 1200;
transform: translateX(-100%);
transition: transform .2s ease;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The open drawer is stacked above the header and its toggle: pp-sidebar uses z-index 1200 while the header remains z-50, so the toggle is covered whenever the drawer is open and cannot be used to close it. Keep the toggle above the drawer or provide an in-drawer close control. [incorrect condition logic]

Severity Level: Major ⚠️
- ⚠️ Open drawer cannot be closed using its header toggle.
- ⚠️ Users must discover and tap the backdrop to close navigation.
- ⚠️ Drawer content can cover the header controls.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/index.html.original
**Line:** 3488:3494
**Comment:**
	*Incorrect Condition Logic: The open drawer is stacked above the header and its toggle: `pp-sidebar` uses z-index 1200 while the header remains z-50, so the toggle is covered whenever the drawer is open and cannot be used to close it. Keep the toggle above the drawer or provide an in-drawer close control.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

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.

Correct, fixed in fc7fd68.

Added a close control inside the drawer itself (.pp-drawer-close), so closing it does not depend on discovering the backdrop. I kept the toggle in the header rather than lifting it above the drawer - the header is a z-50 stacking context, so raising the button alone would not have worked, and raising the whole header over the drawer causes its own problems.

Verified at 412px: toggle opens it, the close control shuts it.

Comment thread web/index.html.original
.pp-header-row > * { min-width: 0; max-width: 100%; }
.pp-header-actions { width: 100%; flex-wrap: wrap; row-gap: 8px; }
.pp-header-search { flex: 1 1 100%; }
.pp-header-search input { width: 100% !important; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The search results panel remains fixed at w-[28rem] while the search field is made full-width on phones. On a 412px viewport the 448px panel extends beyond the viewport, and the new overflow-x: clip rule clips the overflowing portion, making part of every result panel inaccessible. Cap the dropdown width to the viewport and position it within the mobile header. [css layout issue]

Severity Level: Major ⚠️
- ⚠️ Mobile global-search results exceed narrow phone viewports.
- ❌ Search-result controls can be clipped and inaccessible.
- ⚠️ Tag suggestions and result content may be partially hidden.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/index.html.original
**Line:** 3547:3547
**Comment:**
	*Css Layout Issue: The search results panel remains fixed at `w-[28rem]` while the search field is made full-width on phones. On a 412px viewport the 448px panel extends beyond the viewport, and the new `overflow-x: clip` rule clips the overflowing portion, making part of every result panel inaccessible. Cap the dropdown width to the viewport and position it within the mobile header.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

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.

Correct, and this one was a real regression from the overflow-x: clip rule in this PR. Good catch. Fixed in fc7fd68.

The dropdown is now sized off the search field rather than the viewport - it is absolutely positioned inside .pp-header-search, so calc(100vw - ...) ignores the header padding and still spilled by 8px. width: 100% of the field is exact.

Measured at 412px: left 24px, right 378px, fully inside the viewport.

Related one that was not flagged, fixed in the same commit: with the header now wrapping, the dropdown painted underneath the flag/user row that sits below it. .pp-header-search gets its own stacking context.

Comment thread web/index.html.original Outdated
.pp-header-search input { width: 100% !important; }

/* wide tables scroll sideways instead of being crushed */
table { display: block; width: 100%; overflow-x: auto; white-space: nowrap; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This selector applies to every table in the application, including property-grid tables such as VM detail panels and cloud tables that already have their own scrolling wrapper. Forcing all of them to white-space: nowrap prevents intended cell wrapping and can make narrow detail content horizontally overflow; scope the rule to the inventory tables that actually require it. [css layout issue]

Severity Level: Major ⚠️
- ⚠️ VM detail property grids lose natural value wrapping.
- ⚠️ Modal detail content can require unnecessary horizontal scrolling.
- ⚠️ Existing datacenter scroll wrappers can become nested scrollers.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/index.html.original
**Line:** 3550:3550
**Comment:**
	*Css Layout Issue: This selector applies to every table in the application, including property-grid tables such as VM detail panels and cloud tables that already have their own scrolling wrapper. Forcing all of them to `white-space: nowrap` prevents intended cell wrapping and can make narrow detail content horizontally overflow; scope the rule to the inventory tables that actually require it.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

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.

Correct, fixed in fc7fd68 - white-space: nowrap is gone.

Verified on the Top Resources table at 412px: table width 384px, scrollWidth 810px, so it scrolls inside its own box, and computed white-space is normal, so cells wrap again.

On the nested-scroller point: a table inside an existing overflow-x-auto wrapper now has its own scroll box too, but it only scrolls when a row is genuinely wider than the table, so in practice the outer wrapper still does the work.

Comment thread web/src/dashboard.js
<div className={`relative pp-main-wrap ${isCorporate ? 'max-w-full mx-0 px-0 py-0' : 'max-w-[1600px] mx-auto px-6 py-6'}`}>
{/* #189 - drawer backdrop. The toggle itself lives in the header. */}
{/* ponytail: backdrop tap closes it. Auto-close on picking a VM needs a handler in the tree - add if it annoys. */}
{mobileSidebarOpen && <div className="pp-drawer-backdrop" onClick={() => setMobileSidebarOpen(false)} />}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Opening the drawer adds a backdrop that is only removed by its own click handler. The numerous sidebar item handlers update the selected view but never call setMobileSidebarOpen(false), so selecting a cluster, VM, node, topology view, or similar item leaves the drawer and backdrop over the newly selected content on phones. [state/lifecycle]

Severity Level: Major ⚠️
- ⚠️ Mobile navigation remains obstructed after selecting destinations.
- ⚠️ Users must perform an extra backdrop tap after every selection.
- ⚠️ Content remains dimmed and inaccessible behind the open drawer.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/src/dashboard.js
**Line:** 14192:14192
**Comment:**
	*State Lifecycle: Opening the drawer adds a backdrop that is only removed by its own click handler. The numerous sidebar item handlers update the selected view but never call `setMobileSidebarOpen(false)`, so selecting a cluster, VM, node, topology view, or similar item leaves the drawer and backdrop over the newly selected content on phones.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

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.

Correct, fixed in fc7fd68.

Rather than adding setMobileSidebarOpen(false) to each sidebar handler, the drawer closes from an effect watching the selection state - selectedGroup, selectedCluster, selectedPBS, selectedVMware, the three selectedSidebar* and activeTab. That covers every handler at once and does not rot the moment somebody adds another one.

Verified at 412px: tapping a cluster in the drawer closes it and removes the backdrop.

- drop `white-space: nowrap` from the mobile table rule. The scroll box
  (`display: block` + `overflow-x`) is what makes a wide table usable;
  nowrap was the harmful half, it stopped cells wrapping in the property-grid
  tables (VM details and friends) and forced horizontal scrolling where
  wrapping was the better answer
- stop forcing `width: 100%` on modal children. A modal can have more than
  one direct child; cap the size instead of stretching everything
- cap the global-search dropdown, which is a fixed `w-[28rem]` (448px) and so
  wider than a 412px phone. Sized off the search field rather than the
  viewport, because it is positioned inside `.pp-header-search` and viewport
  math ignores the header padding
- give `.pp-header-search` a stacking context, so the dropdown paints above
  the flag/user row that the wrapped header now puts underneath it
- add a close control inside the drawer. The drawer sits above the header, so
  the header toggle is covered while it is open and could not close it
- close the drawer when navigation lands somewhere, via an effect on the
  selection state. There are dozens of sidebar handlers; watching the state
  covers all of them and does not rot when someone adds another
@SpyrosPsarras

Copy link
Copy Markdown
Contributor Author

Pushed a second commit addressing the review.

  • Table rule - dropped white-space: nowrap. The scroll box (display: block + overflow-x: auto) is what makes a wide table usable on a phone, nowrap was the harmful half: it stopped cells wrapping in the property-grid tables and forced horizontal scrolling where wrapping is the better answer. Kept the rule global rather than adding a class to 130+ tables, but happy to scope it to a dedicated wrapper class if you prefer that.
  • Modal children - stopped forcing width: 100%, kept the max-width/max-height cap. A modal can have more than one direct child, so the cap is the safe half.
  • Search dropdown - real bug, and the new overflow-x: clip is what made it unreachable. The dropdown is a fixed w-[28rem] (448px), wider than a 412px phone. Now sized off the search field instead of the viewport, since it is positioned inside .pp-header-search and viewport math ignores the header padding.
  • Drawer could not be closed from the header toggle - correct, the drawer stacks above the header. Added a close control inside the drawer itself.
  • Drawer stayed open after selecting something - fixed with an effect on the selection state instead of patching each handler. There are dozens of sidebar handlers and a per-handler fix rots the moment somebody adds another.

One more that came out of testing and was not in the review: with the header wrapping, the results dropdown painted underneath the flag/user row. .pp-header-search now gets its own stacking context.

Verified against a live 1.0 instance at 412px (Pixel 8 width) and at 1400px:

  • 412px: dropdown fits and stacks on top, the Top Resources table fits the screen and scrolls internally while cells still wrap, drawer opens, close control works, selecting a cluster closes it, page overflow 0
  • 1400px: hamburger and close control hidden, sidebar static with no transform, Tasks bar still fixed, header does not wrap, page overflow 0

@MrMasterbay

Copy link
Copy Markdown
Contributor

@CodeAnt-AI: review

@codeant-ai-for-open-source codeant-ai-for-open-source Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Aug 8, 2026
Comment thread web/src/dashboard.js
Comment on lines +8339 to +8342
useEffect(() => { setMobileSidebarOpen(false); }, [
selectedGroup, selectedCluster, selectedPBS, selectedVMware,
selectedSidebarVm, selectedSidebarNode, selectedSidebarDatastore, activeTab,
]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Replace the manually maintained dependency list with a single centralized navigation-change signal or shared navigation helper that closes the drawer, so newly added navigation paths cannot silently leave the drawer open. [custom_rule]

Severity Level: Major ⚠️

Why it matters? ⭐

The drawer-close behavior depends on a manually maintained list of navigation state variables. The surrounding comment acknowledges that there are many handlers and that new navigation paths may be added; a newly introduced navigation state omitted from this dependency list could leave the drawer open. Centralizing navigation changes or using a shared navigation helper would reduce this coupling and make the behavior easier to maintain.

Rule source 📖

CodeAnt dashboard (rule "agent-persona-maintainability")

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/src/dashboard.js
**Line:** 8339:8342
**Comment:**
	*Custom Rule: Replace the manually maintained dependency list with a single centralized navigation-change signal or shared navigation helper that closes the drawer, so newly added navigation paths cannot silently leave the drawer open.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread web/index.html.original

/* The Tasks bar is fixed to the bottom, so it covered a strip of content at
every scroll position. On a phone it just lives at the end of the page. */
.pp-taskbar { position: static !important; height: auto !important; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The mobile rule forces .pp-taskbar to height: auto !important, overriding the component's inline expanded height and its user-resized height. An expanded task list can therefore grow without the existing bounded panel contract, pushing a large amount of content into the page and making the resize control ineffective. Preserve a viewport-bounded height on mobile while removing the fixed positioning. [logic error]

Severity Level: Major ⚠️
- ❌ Expanded mobile TaskBar can grow with the full task table.
- ⚠️ Mobile dashboard content is pushed far below the viewport.
- ⚠️ TaskBar resizing no longer controls rendered height.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/index.html.original
**Line:** 3534:3534
**Comment:**
	*Logic Error: The mobile rule forces `.pp-taskbar` to `height: auto !important`, overriding the component's inline expanded height and its user-resized height. An expanded task list can therefore grow without the existing bounded panel contract, pushing a large amount of content into the page and making the resize control ineffective. Preserve a viewport-bounded height on mobile while removing the fixed positioning.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread web/src/dashboard.js
return (
<div
className={`fixed bottom-0 left-0 right-0 z-40 transition-all ${isResizing ? '' : 'duration-300'}`}
className={`pp-taskbar fixed bottom-0 left-0 right-0 z-40 transition-all ${isResizing ? '' : 'duration-300'}`}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: On phones, the pp-taskbar rule overrides the inline height with height: auto !important, so an expanded task list grows to its full natural height instead of respecting the user-resized viewport-bounded height. The resize handle still changes height and persists it, but that value has no visual effect on mobile; hide or disable resizing there, or preserve a bounded height with scrolling. [logic error]

Severity Level: Major ⚠️
- ⚠️ Mobile task lists can expand the page substantially.
- ⚠️ Mobile resize controls and persisted heights become ineffective.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/src/dashboard.js
**Line:** 166:166
**Comment:**
	*Logic Error: On phones, the `pp-taskbar` rule overrides the inline `height` with `height: auto !important`, so an expanded task list grows to its full natural height instead of respecting the user-resized viewport-bounded height. The resize handle still changes `height` and persists it, but that value has no visual effect on mobile; hide or disable resizing there, or preserve a bounded height with scrolling.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread web/src/dashboard.js
Comment on lines +8339 to +8342
useEffect(() => { setMobileSidebarOpen(false); }, [
selectedGroup, selectedCluster, selectedPBS, selectedVMware,
selectedSidebarVm, selectedSidebarNode, selectedSidebarDatastore, activeTab,
]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The drawer-closing effect depends on the entire selectedSidebarVm object, but the metrics refresh effect replaces that object whenever CPU, memory, or status changes. While the drawer is open, any live metrics update therefore sets mobileSidebarOpen to false even though navigation did not occur. Depend on stable navigation identity fields or close the drawer only when the logical selection changes. [state]

Severity Level: Major ⚠️
- ⚠️ Corporate mobile drawer closes during live VM updates.
- ⚠️ Users must repeatedly reopen navigation while monitoring resources.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** web/src/dashboard.js
**Line:** 8339:8342
**Comment:**
	*State: The drawer-closing effect depends on the entire `selectedSidebarVm` object, but the metrics refresh effect replaces that object whenever CPU, memory, or status changes. While the drawer is open, any live metrics update therefore sets `mobileSidebarOpen` to false even though navigation did not occur. Depend on stable navigation identity fields or close the drawer only when the logical selection changes.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The dashboard adds responsive mobile styling for viewports up to 820px. The sidebar becomes a drawer with toggle, backdrop, and close controls. Header, task bar, search, tables, popups, results, and corporate tabs receive mobile layout behavior.

Changes

Mobile dashboard responsiveness

Layer / File(s) Summary
Drawer state and navigation closure
web/src/dashboard.js
The dashboard tracks the mobile sidebar state and closes the drawer when selection or active-tab navigation changes.
Drawer controls and layout hooks
web/src/dashboard.js
The header adds an accessible drawer toggle. The layout adds hooks, a backdrop, and an explicit close control.
Responsive layout styling
web/index.html.original, web/src/dashboard.js
Mobile CSS adjusts the drawer, task bar, header, search, tables, popups, search results, and corporate tabs. Desktop behavior remains unchanged.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant DashboardHeader
  participant DashboardState
  participant SidebarDrawer
  User->>DashboardHeader: Activate drawer toggle
  DashboardHeader->>DashboardState: Update mobile sidebar state
  DashboardState->>SidebarDrawer: Apply open or closed state
  User->>SidebarDrawer: Activate backdrop or close control
  SidebarDrawer->>DashboardState: Close mobile sidebar
Loading

Suggested reviewers: mkellermann97, mrmasterbay, gyptazy

🚥 Pre-merge checks | ✅ 10
✅ Passed checks (10 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Secret Handling ✅ Passed The full diff changes only web UI files; scans found no credential formats, secret logging, or additions under config or backup/archive paths.
Server-Side Authorization ✅ Passed The PR changes only web/index.html, web/index.html.original, and web/src/dashboard.js; it adds or modifies no Flask routes or server-side VM, cluster, or user queries.
Encryption Invariants ✅ Passed The PR changes only frontend files for mobile UI; encryption, schema, migration, and keystore files are unchanged, and no sensitive field or key-loader behavior is added.
Migration Safety ✅ Passed The PR changes only mobile CSS and dashboard drawer state; it adds no live migration, ESXi import, evacuation, rolling update, or site recovery failure branch.
Agpl Attribution ✅ Passed The PR changes only mobile CSS/JS and generated HTML; NOTICE and attribution-bearing portal files are unchanged, and no dependency manifest or licence-incompatible dependency was added.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses the required fix prefix and clearly summarizes the mobile layout and drawer sidebar changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/src/dashboard.js`:
- Line 13713: Remove the English fallback literals from the accessibility labels
in this component, including the toggleNavigation usage near the referenced
locations and the corresponding close usage. Add or verify toggleNavigation and
close translations in all seven locale resources, then pass the translated
values directly through t() without hardcoded defaults.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 18afb79d-1acc-4159-b0b3-642b6737b482

📥 Commits

Reviewing files that changed from the base of the PR and between ac9bcb6 and fc7fd68.

📒 Files selected for processing (3)
  • web/index.html
  • web/index.html.original
  • web/src/dashboard.js

Comment thread web/src/dashboard.js
{/* #189 - drawer toggle. In the header so it is always reachable and
can never paint on top of the content. Hidden above 820px. */}
<button className="pp-drawer-toggle"
aria-label={t('toggleNavigation') || 'Toggle navigation'}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove the hardcoded English accessibility-label fallbacks.

Ensure toggleNavigation and close exist in all seven locale resources, then use the translated values without English literals in this component.

Proposed fix
-aria-label={t('toggleNavigation') || 'Toggle navigation'}
+aria-label={t('toggleNavigation')}

-aria-label={t('close') || 'Close'}
+aria-label={t('close')}

As per path instructions, new user-facing strings must go through the i18n layer — the project ships seven languages.

Also applies to: 14205-14205

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/dashboard.js` at line 13713, Remove the English fallback literals
from the accessibility labels in this component, including the toggleNavigation
usage near the referenced locations and the corresponding close usage. Add or
verify toggleNavigation and close translations in all seven locale resources,
then pass the translated values directly through t() without hardcoded defaults.

Source: Path instructions

@mkellermann97 mkellermann97 reopened this Aug 9, 2026
@github-actions
github-actions Bot changed the base branch from main to Testing August 9, 2026 15:32
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

👋 Thanks for the PR! We develop on the Testing branch and fast-forward main only at
release time, so I've retargeted this onto Testing for you — nothing needed on your side.

(Maintainers: add the base:main label and reopen if a PR genuinely needs to target main.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants