Skip to content

Phones: Topology filters and the Resources kind list stop squeezing the content - #2324

Closed
nadaverell wants to merge 3 commits into
mobile/phone-layoutfrom
mobile/phone-sidebars
Closed

nadaverell wants to merge 3 commits into
mobile/phone-layoutfrom
mobile/phone-sidebars

Conversation

@nadaverell

@nadaverell nadaverell commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #2321 (phone layout without the 800px content floor). This PR's base is that branch, so the diff shows only the sidebar changes. Merge #2321 first, or together.

What

With the content floor gone on phones (#2321), the Topology filter panel (224px) and the Resources kind list (224px) each took about two thirds of a 390px screen, leaving the graph and the table a sliver.

  • Topology: on phones the filters start collapsed to their icon rail (expand, plus quick toggles for the first few kinds). Expanded, the panel overlays the graph instead of squeezing it. The panel and graph sit in their own positioned box so the overlay anchors to the topology area, not the whole content column (which also hosts the dock and the expanded drawer).
  • Resources: on phones the kind list moves into a modal drawer, built on k8s-ui's DialogPortal (focus trap, Escape captured before the table's own shortcuts, focus returned to the opener). A toolbar button names the current kind and opens it; picking a kind, tapping the backdrop or pressing Escape closes it. While it's open the table's own shortcuts (/, row navigation, [ / ]) pause. The toolbar wraps so search keeps a full row. Workspace kind views (for example CloudNativePG) get the same button in a slim bar above the view.

Desktop is unchanged: everything is behind the existing max-width: 639px check (a small useMediaQuery hook in k8s-ui, matching web's), apart from the Topology wrapper, which lays out identically (measured: panel 51–900px and footer at 867–900px in both builds at 1440×900).

Topology (before, after, filters expanded)
Topology

Resources (before, after, kind drawer open)
Resources

Not in this PR

Traffic's filter sidebar and the scheduled-workload Execution view's run history (288px each) have the same problem. The demo cluster has no traffic source or CronJob runs to render them with, so I left them for a change that can be verified.

Verified

  • Live at 390px and 320px (iPhone 13 touch emulation, kind cluster with the GitOps demo fixtures): Topology collapsed by default, expanded overlay; Resources button, drawer at the left edge full height, focus moves in and 40 Tabs stay inside, Escape closes and returns focus to the button, pick DaemonSet (navigates to /resources/daemonsets, drawer closes, focus returns), toolbar wrap.
  • Desktop 1440px before and after: Topology and Resources identical.
  • make tsc; k8s-ui vitest (resources, topology, hooks): 2214 passed; web vitest: 3005 passed.

@nadaverell
nadaverell requested a review from hisco as a code owner October 26, 2026 03:28
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Keep Topology and Resources content usable on phones

✨ Enhancement 🕐 20-40 Minutes

Grey Divider

AI Description

• Collapse Topology filters by default on phones and overlay them when expanded, preserving graph
 width.
• Move the Resources kind list into a dismissible drawer, preserving table and workspace-view width.
• Wrap the phone toolbar so search retains a full row; leave desktop layouts unchanged.
Diagram

graph TD
  Phone["Phone viewport"] --> Query["Media query"] --> Resources["Resources view"] --> Drawer["Kind drawer"]
  Resources --> Content["Resource content"]
  Phone --> App["Topology app"] --> Filters["Filter panel"]
  App --> Graph["Topology graph"]
Loading
High-Level Assessment

Keep the responsive overlays around the existing sidebars. This preserves their selection and filtering behavior without introducing separate phone navigation; replacing them with new mobile-specific components would add duplication for little benefit.

Files changed (3) +79 / -9

Enhancement (3) +79 / -9
ResourcesView.tsxPresent resource kinds as a phone drawer +45/-5

Present resource kinds as a phone drawer

• The kind sidebar overlays resource content on phones and closes on selection, backdrop click, Escape, or a switch to a wider viewport. A current-kind button opens it from the table toolbar or a bar above workspace kind views, and the phone toolbar wraps search onto its own row.

packages/k8s-ui/src/components/resources/ResourcesView.tsx

useMediaQuery.tsAdd a responsive media-query hook to k8s-ui +21/-0

Add a responsive media-query hook to k8s-ui

• Adds an SSR-safe hook that reads a media query and subscribes to viewport changes, matching the existing web hook.

packages/k8s-ui/src/hooks/useMediaQuery.ts

App.tsxOverlay expanded Topology filters on phones +13/-4

Overlay expanded Topology filters on phones

• Initializes Topology filters collapsed at the phone breakpoint. A positioned Topology container anchors expanded filters over the graph rather than letting them reduce its width.

web/src/App.tsx

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (2) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Phone comments describe the old layout 📘 Rule violation ⚙ Maintainability
Description
The added AppInner comment says the panel took two thirds of the width, describing prior layout
behavior instead of documenting only the current design intent. This historical wording can become
misleading as the responsive layout evolves.
Code

web/src/App.tsx[R601-602]

+  // Phones start with the filters collapsed to their icon rail: expanded, the
+  // panel took two thirds of the width from the graph.
Evidence
The changed comment states that the panel took two thirds of the width, which is an explicit
reference to previous layout behavior and conflicts with the prohibition on diff or change-history
references in code comments.

Rule 3036538: Disallow references to tickets or PR history in code comments
web/src/App.tsx[601-602]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new comment refers to the panel's prior width usage, which is explicit change-history wording in code comments.
## Fix Focus Areas
- web/src/App.tsx[601-602]
## Recommended Fix
Replace the historical explanation with a concise statement of the current responsive intent, or remove the comment if the surrounding code and class names already make that intent clear.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. The phone drawer backdrop ignores theme colors 📘 Rule violation ⚙ Maintainability
Description
The resources drawer backdrop uses the hardcoded utility class bg-black/40 instead of a theme
background token. When the kind drawer is open on a phone, this raw black overlay bypasses the
application's theme color system.
Code

packages/k8s-ui/src/components/resources/ResourcesView.tsx[R6103-6105]

+      {!hideSidebar && isPhone && kindsDrawerOpen && (
+        <div className="absolute inset-0 z-30 bg-black/40" aria-hidden onClick={() => setKindsDrawerOpen(false)} />
+      )}
Evidence
The changed backdrop element includes bg-black/40, a hardcoded background color utility. The
checklist permits only bg-theme-base, bg-theme-surface, bg-theme-elevated, or bg-theme-hover
for background utility classes unless a documented exception exists, and no such exception appears
here.

Rule 3036653: Use theme background tokens instead of hardcoded utility color classes
packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The phone kind drawer backdrop uses the hardcoded `bg-black/40` background utility, which bypasses the approved theme background tokens.
## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6105]
## Recommended Fix
Replace `bg-black/40` with the appropriate theme background utility or add and use a documented theme overlay token that preserves the intended backdrop opacity across themes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Keyboard users can tab past the kind drawer 🐞 Bug ≡ Correctness
Description
kindsDrawerOpen mounts the sidebar without moving focus from the toolbar button into it or
containing focus there. On a phone, forward Tab from the button reaches the background resource
controls rather than the drawer’s filter and kinds.
Code

packages/k8s-ui/src/components/resources/ResourcesView.tsx[R6106-6108]

+      {!hideSidebar && (!isPhone || kindsDrawerOpen) && (
     <ResourcesSidebar
+          className={isPhone ? 'absolute inset-y-0 left-0 z-40 shadow-theme-lg' : undefined}
Evidence
The trigger remains in the toolbar after it opens the separately mounted sidebar. The sidebar only
auto-focuses its filter for fine pointers, and the drawer adds no focus management.

packages/k8s-ui/src/components/resources/ResourcesView.tsx[6086-6096]
packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6108]
packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[276-284]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Opening the phone kind drawer leaves keyboard focus on its trigger, and forward Tab moves into the background instead of the drawer.
## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6129]
- packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[276-284]
## Recommended Fix
Move focus into the sidebar when the drawer opens regardless of pointer type, contain keyboard focus while it is open, and restore focus to the trigger when it closes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (2)
4. Drawer keys can act on the hidden table 🐞 Bug ≡ Correctness
Description
ResourcesView leaves its table and kind-navigation shortcuts enabled while kindsDrawerOpen is
true. When focus is on a sidebar button, the document shortcut handler does not suppress its keys,
so arrows can change the background row highlight and kind-navigation keys can change the selected
kind.
Code

packages/k8s-ui/src/components/resources/ResourcesView.tsx[R6106-6108]

+      {!hideSidebar && (!isPhone || kindsDrawerOpen) && (
     <ResourcesSidebar
+          className={isPhone ? 'absolute inset-y-0 left-0 z-40 shadow-theme-lg' : undefined}
Evidence
Resource shortcuts remain registered with table-based enablement, while the shortcut provider treats
button targets as unsuppressed and dispatches their keys at document level.

packages/k8s-ui/src/components/resources/ResourcesView.tsx[4619-4668]
packages/k8s-ui/src/hooks/useKeyboardShortcuts.tsx[61-73]
packages/k8s-ui/src/hooks/useKeyboardShortcuts.tsx[163-236]
packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[153-179]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Keyboard events from the open phone kind drawer can invoke resource-table and kind-navigation shortcuts behind it.
## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6129]
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[4619-4668]
## Recommended Fix
Disable or scope background resource shortcuts while the phone drawer is open, while retaining Escape to close the drawer and keyboard operation of its own controls.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Phone users lose their kind-list settings 🐞 Bug ≡ Correctness
Description
Closing the phone drawer unmounts ResourcesSidebar, resetting its local kindFilter and
showEmptyKinds state. Reopening it after a backdrop tap or kind selection clears the filter and
hides confirmed-empty kinds again, so users must repeat those choices.
Code

packages/k8s-ui/src/components/resources/ResourcesView.tsx[6106]

+      {!hideSidebar && (!isPhone || kindsDrawerOpen) && (
Evidence
The new conditional removes the sidebar on close, while both user-visible settings are initialized
in sidebar-local state; the Show empty value controls whether confirmed-empty kinds remain visible.

packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6113]
packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[261-264]
packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[400-423]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Conditionally unmounting the phone sidebar resets its resource-kind filter and Show empty setting whenever the drawer closes.
## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6113]
- packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[261-264]
## Recommended Fix
Keep the sidebar mounted while hiding the closed drawer, or lift the filter and Show empty state to the parent so reopening restores the user's choices.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread web/src/App.tsx
Comment on lines +601 to +602
// Phones start with the filters collapsed to their icon rail: expanded, the
// panel took two thirds of the width from the graph.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Phone comments describe the old layout 📘 Rule violation ⚙ Maintainability

The added AppInner comment says the panel took two thirds of the width, describing prior layout
behavior instead of documenting only the current design intent. This historical wording can become
misleading as the responsive layout evolves.
Agent Prompt
## Issue description
The new comment refers to the panel's prior width usage, which is explicit change-history wording in code comments.

## Fix Focus Areas
- web/src/App.tsx[601-602]

## Recommended Fix
Replace the historical explanation with a concise statement of the current responsive intent, or remove the comment if the surrounding code and class names already make that intent clear.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +6103 to +6105
{!hideSidebar && isPhone && kindsDrawerOpen && (
<div className="absolute inset-0 z-30 bg-black/40" aria-hidden onClick={() => setKindsDrawerOpen(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.

Remediation recommended

2. The phone drawer backdrop ignores theme colors 📘 Rule violation ⚙ Maintainability

The resources drawer backdrop uses the hardcoded utility class bg-black/40 instead of a theme
background token. When the kind drawer is open on a phone, this raw black overlay bypasses the
application's theme color system.
Agent Prompt
## Issue description
The phone kind drawer backdrop uses the hardcoded `bg-black/40` background utility, which bypasses the approved theme background tokens.

## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6105]

## Recommended Fix
Replace `bg-black/40` with the appropriate theme background utility or add and use a documented theme overlay token that preserves the intended backdrop opacity across themes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +6106 to +6108
{!hideSidebar && (!isPhone || kindsDrawerOpen) && (
<ResourcesSidebar
className={isPhone ? 'absolute inset-y-0 left-0 z-40 shadow-theme-lg' : undefined}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Keyboard users can tab past the kind drawer 🐞 Bug ≡ Correctness

kindsDrawerOpen mounts the sidebar without moving focus from the toolbar button into it or
containing focus there. On a phone, forward Tab from the button reaches the background resource
controls rather than the drawer’s filter and kinds.
Agent Prompt
## Issue description
Opening the phone kind drawer leaves keyboard focus on its trigger, and forward Tab moves into the background instead of the drawer.

## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6129]
- packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[276-284]

## Recommended Fix
Move focus into the sidebar when the drawer opens regardless of pointer type, contain keyboard focus while it is open, and restore focus to the trigger when it closes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +6106 to +6108
{!hideSidebar && (!isPhone || kindsDrawerOpen) && (
<ResourcesSidebar
className={isPhone ? 'absolute inset-y-0 left-0 z-40 shadow-theme-lg' : undefined}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. Drawer keys can act on the hidden table 🐞 Bug ≡ Correctness

ResourcesView leaves its table and kind-navigation shortcuts enabled while kindsDrawerOpen is
true. When focus is on a sidebar button, the document shortcut handler does not suppress its keys,
so arrows can change the background row highlight and kind-navigation keys can change the selected
kind.
Agent Prompt
## Issue description
Keyboard events from the open phone kind drawer can invoke resource-table and kind-navigation shortcuts behind it.

## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6129]
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[4619-4668]

## Recommended Fix
Disable or scope background resource shortcuts while the phone drawer is open, while retaining Escape to close the drawer and keyboard operation of its own controls.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

{!hideSidebar && isPhone && kindsDrawerOpen && (
<div className="absolute inset-0 z-30 bg-black/40" aria-hidden onClick={() => setKindsDrawerOpen(false)} />
)}
{!hideSidebar && (!isPhone || kindsDrawerOpen) && (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

5. Phone users lose their kind-list settings 🐞 Bug ≡ Correctness

Closing the phone drawer unmounts ResourcesSidebar, resetting its local kindFilter and
showEmptyKinds state. Reopening it after a backdrop tap or kind selection clears the filter and
hides confirmed-empty kinds again, so users must repeat those choices.
Agent Prompt
## Issue description
Conditionally unmounting the phone sidebar resets its resource-kind filter and Show empty setting whenever the drawer closes.

## Fix Focus Areas
- packages/k8s-ui/src/components/resources/ResourcesView.tsx[6103-6113]
- packages/k8s-ui/src/components/resources/ResourcesSidebar.tsx[261-264]

## Recommended Fix
Keep the sidebar mounted while hiding the closed drawer, or lift the filter and Show empty state to the parent so reopening restores the user's choices.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

…he content

On a phone the Topology filter panel and the Resources kind list each took
about two thirds of the width. Topology now starts with its filters
collapsed to the icon rail, and expanded they overlay the graph. Resources
moves the kind list into a drawer over the table, opened from a toolbar
button that names the current kind and closed by a pick, a backdrop tap or
Escape; its toolbar wraps so search keeps a full row.
@nadaverell
nadaverell force-pushed the mobile/phone-sidebars branch from e79b4d5 to 957cc30 Compare October 26, 2026 03:50
nadaverell added a commit that referenced this pull request Oct 26, 2026
… phone layout (#2321)

## What

The foundation for phone layouts in Radar Cloud (and, incidentally,
standalone Radar):

- **What counts as a phone:** a narrow, touch-first screen, `(max-width:
639px) and (pointer: coarse)`. A desktop browser window narrowed below
640px is *not* a phone. It keeps the 800px content floor and the full
desktop layout. Browser dev-tools device mode emulates touch, so it
still gets the phone layout for testing.
- **One rule everywhere:** k8s-ui exports `PHONE_MEDIA_QUERY`,
`usePhoneLayout()` and a `phone:` Tailwind variant (defined in
`theme/tailwind-theme.css`, which both Radar and Radar Cloud import).
- **Shell floor:** 800px on desktop as before; 360px on a phone (the
narrowest current phones, such as most Samsung Galaxy models).
- **Per-view opt-in:** `PHONE_READY_VIEWS` in `App.tsx` lists the views
that have a deliberate phone layout. On a phone, every other view keeps
its 800px desktop width inside a container that scrolls sideways. Before
this, the floor clipped the right half of every view with no way to
reach it. The list starts empty; each view joins it in its own PR, after
its own design pass.
- **Shared shells:** the page header and the detail shell wrap on phones
(`phone:` variant), so every view inherits a usable header.

## Desktop

Nothing changes on a desktop at any window size: the phone rule needs a
touch-first pointer, and the new wrapper element is `display: contents`
outside phone mode.

## Follow-up PRs (stacked on this one)

Issues, Helm, Home, Resources (#2324) and Topology each get their own PR
with phone captures inside Radar Cloud and a desktop before/after
comparison.
nadaverell added a commit that referenced this pull request Oct 26, 2026
This replaces #2324, which was built on the earlier version of #2321 and
also carried the Topology change (now its own PR).

## What

On a phone, the 224px kind list left the resource table a sliver.

- The kind list opens as a modal drawer (focus trap, Escape, focus
return) from a toolbar button that names the current kind ("Pod"), and
closes when you pick a kind.
- The toolbar wraps, and search gets its own row.
- Table shortcuts, including `[` and `]`, pause while the drawer is
open.
- Resources joins `PHONE_READY_VIEWS`.

The table keeps its desktop columns: Name and Namespace fit at 390px,
and the rest scroll sideways inside the table. A phone-specific column
set (Name and Status) is a possible follow-up.

## Desktop

Unchanged. The drawer and its button exist only under `usePhoneLayout()`
(narrow, touch-first screens), and the toolbar changes are behind the
`phone:` variant. Compared pixel by pixel against main on an EKS cluster
(Pods, Deployments, ConfigMaps, a resource drawer) at 1440 and 1024px:
matching within live-data noise. Clicking a kind in the sidebar and `[`
/ `]` behave the same on both.

## Screenshots

Radar Cloud on a GKE cluster with touch emulation. "Before" is radar
main at 390px, where the 800px floor clips the table.


![phone](https://github.com/user-attachments/assets/a94405e5-7373-4eb9-895a-36136922c870)
@nadaverell nadaverell closed this Oct 26, 2026
nadaverell added a commit that referenced this pull request Oct 26, 2026
)

## What

On a phone, Topology's filter panel took two thirds of the width from
the graph.

- The filters start collapsed to their icon rail on phones.
- When expanded, they overlay the graph instead of squeezing it.
- The graph itself pans and zooms as before.
- Topology joins `PHONE_READY_VIEWS`.

Split out of #2324, which is superseded by this PR and #2328.

## Desktop

Unchanged. The initial collapsed state and both new wrappers apply only
under the phone rule; outside it the wrappers are `display: contents`.
Compared against main on an EKS cluster (one namespace, since the whole
cluster is too large to graph) at 1440 and 1024px, including collapsing
and expanding the filters: differences are at the level of main against
itself (1–2%, the graph layout varies between loads).

## Screenshots

Radar Cloud on a GKE cluster with touch emulation. "Before" is radar
main at 390px.


![phone](https://github.com/user-attachments/assets/df3fa29a-b615-4aeb-b92f-6af1e78f308c)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant