Skip to content

Mobile web UI [4/7]: Collapse the cron and memory side panes into drawers - #296

Open
alex-clickhouse wants to merge 1 commit into
alex-clickhouse/mobile-page-headerfrom
alex-clickhouse/mobile-panes
Open

Mobile web UI [4/7]: Collapse the cron and memory side panes into drawers#296
alex-clickhouse wants to merge 1 commit into
alex-clickhouse/mobile-page-headerfrom
alex-clickhouse/mobile-panes

Conversation

@alex-clickhouse

Copy link
Copy Markdown
Collaborator

Fourth step on #271, stacked on #295#294#293. Review the stack in order.

The problem

Both pages split the viewport into fixed columns and never reconsider it. At 412px:

  • /cron — a 220px job list next to the run table left the table showing two of its six columns (Job, Started). Duration, Status, Output and the rest were off-screen.
  • /memory — a 208px types/categories rail, the facts list and the detail pane, all sharing 412px: roughly 130px each.

The change

Below md the list pane becomes a left drawer, matching the chat session list from #293 — same anchor, same toggle button, same icon pair. "Show me the list" is now the same gesture in the same corner on every page that has a list. /cron's table goes from two visible columns to five; /memory's facts get the full width.

Both headers move to PageHeader in the same pass. Converting the bodies without the headers would have left these two as the only pages still scrolling sideways from the old header row — half-converted is worse than either end state.

A latent bug in #295, found here

Worth calling out because it changes a line that PR added.

The PageHeader title wrapper used flex-1, which is flex: 1 1 0%. A zero flex-basis means the title contributes nothing to flex line-fitting, so the filter row packs onto the same line and squeezes the title to zero width.

It looked correct on the three pages in #295 purely by accident: each has visible action buttons whose width pushed the line past its limit, forcing the wrap I wanted. /memory hides its counts below lg, so nothing pushed the line over — and the title rendered at 0px wide, invisible, while the tabs sat where it should have been.

Two changes, so the layout no longer depends on a neighbour to overflow the line:

  • title wrapper is flex-auto — content-width basis, still truncating via min-w-0
  • filter and search rows claim basis-full, taking a line of their own unconditionally

Verified across all five migrated pages: page overflow 0px everywhere, and every <h1> measures a real width (56/55/129/96/182px).

Notes for review

  • MemuPage's hooks had to go above its if (loading) return. Added below it, they changed the hook order between renders and blanked the whole page the moment loading flipped to false. React threw "change in the order of Hooks"; the page rendered as a black rectangle.
  • Both drawers close on selection and on crossing the breakpoint, adjusted during render (same pattern as the chat drawer) so the overlay is never painted over the content for a frame.
  • CronSidebar and MemuPage's Sidebar take an inDrawer prop that drops the fixed width and their own right border — the drawer supplies both.
  • The /cron run table still scrolls horizontally within its own container at five columns. That is the P2 table work, deliberately not in this PR.

Verification

  • npm run build clean; eslint clean on all touched files (one pre-existing warning in MemuPage.tsx:595)
  • 412×915: both drawers open, close on selection, and both bodies use the full width
  • 1280×900 against main: both pages unchanged — inline sidebars, same header order, same controls

Still to do for #271

P2 tables (/cron, /diagnostics), the touch-target pass, and the detail pages (/tasks/:id, /plans/:id, /skills/:id, /mcp/:serverName) which remain unsurveyed.

@alex-clickhouse alex-clickhouse changed the title Collapse the cron and memory side panes into drawers Mobile web UI [4/7]: Collapse the cron and memory side panes into drawers Aug 9, 2026
@alex-clickhouse
alex-clickhouse requested a balanced review from Copilot August 9, 2026 17:56

Copilot AI 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.

Pull request overview

Makes Cron and Memory layouts mobile-friendly by moving side panes into drawers and standardizing headers.

Changes:

  • Adds reusable pane toggle controls.
  • Converts Cron and Memory sidebars into mobile drawers.
  • Fixes responsive PageHeader wrapping behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
web/src/pages/MemuPage.tsx Adds responsive memory drawer and header.
web/src/pages/CronPage.tsx Adds responsive cron drawer and header.
web/src/components/ui/PaneToggle.tsx Introduces the drawer toggle control.
web/src/components/ui/PageHeader.tsx Corrects responsive title and row sizing.
web/src/components/Cron/CronSidebar.tsx Supports drawer-specific sidebar sizing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread web/src/pages/MemuPage.tsx Outdated
// Close the drawer when the tab changes or the layout crosses the
// breakpoint. During render, not in an effect, so the overlay is never
// painted over the content for a frame first.
const paneScope = `${isMobile}:${activeTab}`;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. Sidebar takes an onSelect that fires from both the category buttons and the Clear-filter button, and the drawer closes on it. Creating a category happens inside the pane and deliberately does not fire it. Dropped the scope watcher for this — it would also have missed re-tapping the active category, which clears the filter, so the list underneath does change.

Comment thread web/src/pages/CronPage.tsx Outdated
// Shut the drawer once a job is picked, and whenever the layout crosses the
// breakpoint. Adjusted during render, not in an effect, so the overlay is
// never painted over the table for a frame first.
const paneScope = `${isMobile}:${selectedJobId}`;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. CronSidebar takes an onSelect that fires after every plain selection, including "All Jobs" and re-picking the job already selected, and CronPage closes listOpen directly from it. The modified-click and middle-click paths open a new tab and select nothing, so they do not fire it. The remaining render-time adjustment only handles crossing the breakpoint.

Both pages split the viewport into fixed columns. At 412px that left
/cron's run table showing two of its six columns, and gave /memory's
three panes roughly 130px each.

Below `md` the list pane becomes a left drawer, matching the chat session
list — same anchor, same toggle, same icons — so "show me the list" is
the same gesture in the same corner everywhere. /cron's table goes from
two visible columns to five; /memory's facts get the full width.

Both headers move to PageHeader in the same pass. Converting the body
without the header would have left them the only pages still scrolling
sideways from the old header row. PageHeader gains a `leading` slot for
the pane toggle, so it sits where the chat header's sidebar toggle sits.

Both drawers close the moment a selection is made, driven by the pane's
own handler rather than by watching the selected id. Watching the id
misses the case where the tap picks what is already picked: on /cron
that is "All Jobs", on /memory it is the active category (which clears
the filter, so the list underneath does change). Either way the drawer
would have stayed parked over the content it was asked to reveal.
Crossing the breakpoint still retires the drawer, adjusted during render
so the overlay is never painted over the content for a frame.

MemuPage's hooks go above its `if (loading) return` — added below it
they changed the hook order between renders and blanked the page as soon
as loading flipped.

Desktop is unchanged on both pages.

Refs #271
@alex-clickhouse
alex-clickhouse force-pushed the alex-clickhouse/mobile-panes branch from def0406 to b91bc35 Compare August 9, 2026 18:32
@alex-clickhouse
alex-clickhouse marked this pull request as ready for review August 9, 2026 18:40
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.

2 participants