Skip to content

fix(mobile-ui): batch 1 — 6 mobile UI fixes + 5 follow-ups (#21-#26)#29

Merged
FireTable merged 12 commits into
mainfrom
fix/mobile-ui-batch1
Jul 10, 2026
Merged

fix(mobile-ui): batch 1 — 6 mobile UI fixes + 5 follow-ups (#21-#26)#29
FireTable merged 12 commits into
mainfrom
fix/mobile-ui-batch1

Conversation

@FireTable

@FireTable FireTable commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Mobile UI smoke pass — six narrowly-scoped fixes for issues you only notice on a phone, plus a chain of narrower follow-ups caught in review.

Issue Fix
#21 wrap-break-word on memory profile value cells so R2 object URLs and thread ids wrap inside the card. Follow-up: stack the threads-summarize Expand + Delete buttons vertically on mobile so they don't sit jammed against the card edge; round 4 refactor (with help from the test author) extracts SummaryContent as a React element rendered twice (md:hidden mobile copy inside the action wrapper, hidden md:block desktop copy below the header) so the two buttons read as one action group on mobile while keeping the desktop 4-col grid unchanged.
#22 Observability panel: bump stat-tile breakpoint from sm to md; flip timeline container from overflow-hidden to overflow-x-auto / overflow-y-hidden; follow-ups: drop the top header sticky on mobile (too tall), cap waterfall columns at max-w-[50%] with overflow-hidden on mobile (240 px label was 62 % of an iPhone viewport), hide the hover TooltipPopup below md. v5 polish: per-card label clip (line-clamp-1 + text-ellipsis), force grid-cols-4 at every breakpoint, shorten tokentok on the tile values, sticky-label bg-background, legend strip sticky left-0.
#23 Drop the hideSettings prop from the mobile sheet's <UserButton/> so the built-in Settings entry renders the same on mobile and desktop.
#24 Gate composer autoFocus on (pointer: fine) && maxTouchPoints === 0 so the soft keyboard stays hidden until the user taps the composer on touch devices. Edit-composer still autoFocuses (line 572).
#25 Landing bento: drop auto-rows-fr and the big/wide min-h-* from the default (mobile) layer; follow-up: kill the md: bento intermediate step — between 768 and 1024 px the 2-col grid stretches cards to match the tallest sibling, leaving empty whitespace beneath the short ones. Single-col flex all the way until lg:.
#26 Memory delete dialog: pin cross-axis to items-end on mobile (sm:items-center sm:justify-end desktop, full-width Cancel + Delete buttons on mobile / auto width on md+) so the buttons sit right-aligned and easy to reach on touch instead of left-aligned against the modal edge.

Closes #21 #22 #23 #24 #25 #26.

Commits (11, in order)

SHA Message
b24fba6 fix(mobile-ui): wrap memory card values to prevent URL overflow (#21)
ae7f71a fix(mobile-ui): mobile observability tiles reflow + scrollable waterfall (#22)
c8f5581 fix(mobile-ui): show Settings entry in mobile user menu (#23)
0f5e070 fix(mobile-ui): skip chat composer autofocus on touch devices (#24)
0410ff3 fix(mobile-ui): landing bento cards stack on content height (#25)
af831ac fix(mobile-ui): memory delete modal stops stretching buttons edge-to-edge (#26)
6f62277 fix(mobile-ui): stack threads-summarize action buttons vertically on mobile (#21 follow-up)
07f8f2d fix(mobile-ui): drop sticky + cap waterfall columns + hide tooltip on mobile (#22 follow-up)
9067a63 fix(mobile-ui): kill md bento intermediate step on landing (#25 follow-up)
0be7260 fix(mobile-ui): move About-you Delete below value + reorder thread-summarize actions (#21 v3)
da3f043 fix(mobile-ui) #21 v4 + #26 v2: full-width Delete below value, Expand+Delete grouped, dialog footer right-aligned + tests
0c5f051 fix(mobile-ui): observability v5 — stat tile polish for narrow viewports

How to test

git checkout fix/mobile-ui-batch1
pnpm dev  # if not already running, reuse the session on :3000

Then in Chrome DevTools → toggle device toolbar → iPhone 14 (390×844, hasTouch):

  1. [Bug]: Mobile Settings → Memory section text overflows (long URLs bleed past card edge) #21/settings/memory with a long-value row → URL wraps inside the card; a thread summary row shows Expand then SummaryContent then Delete stacked full-width (or click Delete directly to open the dialog).
  2. [Bug]: Mobile Observability panel — strict-grid tiles + clipped waterfall timeline (no horizontal scroll/drag) #22 — send a chat message, wait for the assistant response, tap the activity icon. Sheet shows 8 stat tiles in 2 cols + horizontally-scrollable waterfall; top header is NOT pinned (it scrolls with the rows); tooltip popup does not appear on hover.
  3. [Bug]: Mobile user button menu is missing Settings entry (menu items not shared with desktop) #23 — tap the hamburger → user button → menu shows Memory · Settings · Sign Out.
  4. [Bug]: Mobile chat composer auto-focuses on page load (soft keyboard pops up unsolicited) #24/chat fresh → soft keyboard stays hidden; chat history visible.
  5. [Bug]: Mobile landing-page bento cards use grid (causes equal-height empty whitespace); should switch to flex column on mobile #25/ → scroll into #features; cards stacked single-column with content-height; no inflated whitespace. At iPad portrait (~768 px) the cards still stack — the asymmetric bento only appears at iPad landscape / desktop (~1024 px+).
  6. [Bug]: Mobile Settings → Memory delete-confirmation modal not adapted for small viewports (edge-to-edge, no safe-area padding) #26 — open either the profile-row Delete or the thread-row Delete dialog. Modal sits centered with breathing room; Cancel + Delete stack right-aligned, full-width on mobile, intrinsic width on md+. Destructive action is easy to reach on touch.

Verification status

Captured via Playwright + iPhone 14 emulation against the running dev server with a real session cookie. Screenshots at .claude/screenshots/verify-{21..26}.png, all MD5s unique each run.

Issue Verdict Evidence
#21 ✅ verified (original + follow-ups + v4) Profile .wrap-break-word cells render overflow-wrap: break-word; scrollW === docW === 390 (no horizontal overflow). About-you store Delete has col-span-2 w-full md:col-span-1 md:w-auto (full row below value on mobile). Thread-summarize stores SummaryContent element and renders it twice (verified by test: data-slot="thread-body" count === 2 with mobile md:hidden + desktop hidden md:block ancestors).
#22 ✅ verified (original + follow-ups + v5) Stat-tile grid → 4 cols at every breakpoint (was 2 → 3 → 4); waterfall overflow-x: auto. Follow-up: topCardSticky=false (top header not sticky on mobile), tooltipsVisible=0 (hover popup hidden via hidden md:block). v5 polish: per-card line-clamp-1 + text-ellipsis clips long labels; tokentok keeps the value on one line at 4-col phone width.
#23 ✅ verified Sheet open + [role='menuitem'] items = ["Memory", "Settings", "Sign Out"] on mobile.
#24 ✅ verified Fresh /chat load → document.activeElement === <body>; composer unfocused.
#25 ✅ verified (original + follow-up) All 6 feature cards measured: height ≈ scrollHeight ± 2px. Follow-up commit 9067a63 collapses the md bento step — desktop (≥ lg) retains the asymmetric grid, everything below lg is single-column flex.
#26 ✅ verified (original + v2) Dialog left=24px right=24px; footer align-items: flex-end, flex-direction: column-reverse; buttons full-width on mobile (Cancel 292 px + Delete 292 px), reverting to intrinsic width on md+. Both profile and thread dialogs covered (asserted via data-slot="dialog-footer" class + Cancel/Delete button class assertions).

Tests added (6 new, 3 existing updated)

tests/frontend/settings/memory-view.test.tsx:

  • mobile (#21): Profile store Delete is full-width + col-span-2 — pinned by className inspection on every Profile-store Delete button (w-full, col-span-2, md:col-span-1, md:w-auto).
  • mobile (#21): Thread-summarize Delete is full-width on mobile + w-auto at md+ — className on the data-slot="thread-collapse" row's Delete.
  • mobile (#21): Thread body rendered twice (mobile + desktop) — counts data-slot="thread-body" elements per thread (2 per row) and checks each copy is wrapped in the right responsive ancestor (.md:hidden for mobile, .hidden.md:block for desktop).
  • mobile (#26): Dialog footer is right-aligned on mobile (items-end)[data-slot="dialog-footer"] must contain items-end and not items-start; opens the profile-delete dialog before checking.
  • mobile (#26): Profile dialog Cancel + Delete are full-width on mobile + auto on md+ — same className pattern on both buttons, dialog open.
  • mobile (#26): Thread dialog Cancel + Delete are full-width on mobile + auto on md+ — same check, thread-dialog open.

Existing tests that depended on getByText(/intro question/) / getByText(/Summary · N/) were switched to queryAllByText(...).length >= 1 because the new SummaryContent rendered twice (mobile + desktop) makes the same Q&A text show up in two DOM slots in jsdom. The parent <Collapsible open> keeps both copies coordinated.

Caveats

Skipped (out of scope)

Triaged but moved to follow-up PRs:

Files changed

File Commits
components/settings/memory-view.tsx b24fba6, 6f62277, 0be7260, da3f043
components/observability/panel.tsx ae7f71a, 07f8f2d
app/assistant.tsx c8f5581
components/assistant-ui/thread.tsx 0f5e070
components/landing/features.tsx 0410ff3, 9067a63
components/ui/dialog.tsx af831ac, da3f043
tests/frontend/settings/memory-view.test.tsx da3f043

Total: 7 files, 10 commits, +209 −92 (final git diff --stat main..fix/mobile-ui-batch1).

Long unbroken strings (Cloudflare R2 object URLs, thread ids) were
rendered on a single line and bled past the card edge on mobile, forcing
horizontal page scroll. Add wrap-break-word to the primitive value div
and the thread-id meta line so URLs break inside their container.
…all (#22)

Two changes:
1. Stat tiles: bump the multi-column breakpoint from sm (640px) to md (768px)
   so 8 tiles get 2 cols on phones + tablet portrait, 3 cols on small landscape,
   4 cols on desktop — prevents the squished 2-col layout from looking cramped.
2. Waterfall timeline: change the outer container from overflow-hidden to
   overflow-x-auto/overflow-y-hidden so long bars can be reached by
   horizontal scroll on narrow viewports. Sticky label column + header
   remain pinned to the left edge during scroll.
The mobile sheet sidebar was passing hideSettings to UserButton, dropping
the Settings entry from the expanded menu on mobile while desktop kept it.
Drop the prop so both surfaces render the same menu items via the shared
UserButton source — single source of truth, no per-renderer drift.
autoFocus on the Composer caused the soft keyboard to pop up the moment
the chat page loaded on mobile, eating half the viewport before the user
tapped anything. Gate autoFocus on (pointer: fine) + maxTouchPoints===0
so the keyboard stays hidden until the user explicitly taps the composer.
Edit-composer still autoFocuses (line 572) — it's edit-in-place, focus
is the intended behavior.
auto-rows-fr + the big/wide card min-heights forced every bento cell to
match the tallest sibling, leaving ~50% empty whitespace below each card
on mobile. Switch auto-rows-fr to md+ only (single-column stack on phones
sizes by content) and demote the min-heights to md+ so the wide / big
cards keep their footers on tablet and desktop where the row needs to
fill the row's tallest sibling.
…edge (#26)

Two compounding layout issues made the destructive dialog feel hostile on
mobile:
1. items-stretch is flex default — on a flex-col footer the buttons
   stretched to fill the modal width, sitting at the viewport edge.
   Pin cross-axis to items-start on mobile (sm:items-center for desktop
   row layout) so buttons take intrinsic width.
2. Modal itself was max-w-[calc(100%-2rem)] — only 16px gutter on each
   side, which leaves destructive actions tight against the edge. Bump
   to max-w-[min(calc(100%-3rem),28rem)] on mobile so the modal sits in
   the comfortable center; desktop sm:max-w-lg unchanged.
@FireTable FireTable changed the title fix(mobile-ui): batch 1 — mobile UI fixes fix(mobile-ui): batch 1 — 6 mobile UI fixes (#21 #22 #23 #24 #25 #26) Jul 10, 2026
@FireTable FireTable changed the title fix(mobile-ui): batch 1 — 6 mobile UI fixes (#21 #22 #23 #24 #25 #26) fix(mobile-ui): batch 1 — mobile UI fixes Jul 10, 2026
@FireTable FireTable changed the title fix(mobile-ui): batch 1 — mobile UI fixes fix(mobile-ui): batch 1 — 6 mobile UI fixes (#21 #22 #23 #24 #25 #26) Jul 10, 2026
…mobile (#21)

Original #21 fix wrapped the thread-id text but left the Expand + Delete
buttons jammed into a 4-col grid alongside the icon + title, so on narrow
viewports the Delete button sat tight against the card edge.

On mobile: collapse the outer grid to 2 cols (icon + title) and wrap the
two action buttons in a col-span-full flex-col container so each button
takes the full row width. On md+: the wrapper becomes display: contents
and the buttons slot back into the original 4-col grid for the desktop
row layout.
… mobile (#22 follow-up)

Three mobile-only observability follow-ups from the user's review pass:

1. Top axis header (the time-axis bar pinned to the top of the waterfall)
   was `position: sticky` on all viewports — on mobile the sticky bar
   stole a quarter of the sheet's already-tight vertical space and
   fought with the ScrollText-using thread row that scrolls behind it.
   Switch to `md:sticky md:top-0 md:z-20` so the sticky behavior only
   kicks in at md+ where the panel has room for it.

2. Waterfall columns were sized 240px label + remainder bar in math
   (LABEL_WIDTH constant) and pinned via inline `style={{ width }}` —
   on iPhone-class viewports 240/390 = 62 % is over half the screen and
   the right-side bar squeezed to < 40 % with no clipping safety. Cap
   every column div at `max-w-[50%] md:max-w-none` with `overflow-hidden`
   on mobile so neither side bleeds past its slice and text labels truncate
   cleanly. Desktop widths unchanged.

3. The hover-only TooltipPopup sat at `z-50 fixed`; on touch devices
   long-press events can fire it even though there's no cursor. Hide it
   via `hidden md:block` so it never renders below md.
…w-up)

Original #25 fix kept a single mid-size grid step in the landing
bento: below md (768) the cards stack in a single column, between
md and lg (768-1024) they go back into a 2-col layout with
auto-rows-fr + 260 / 140 px min-heights, and only at lg+ does the
4-col bento kick in. The md branch is the worst of both worlds —
the smaller Dual-graph and Observability cards stretch their
row-height up to the 260 px Chat anything card, leaving 50 %
empty whitespace beneath their text. Same content, bigger card.

Drop the md breakpoint entirely. Below lg everything is single-
column flex (mobile layout); the asymmetric bento only appears
at lg+ where there's room for the 2×2 / 2×1 / 1×1 spans to
actually fit.
@FireTable FireTable changed the title fix(mobile-ui): batch 1 — 6 mobile UI fixes (#21 #22 #23 #24 #25 #26) fix(mobile-ui): batch 1 — 6 mobile UI fixes + 3 follow-ups (#21-#26) Jul 10, 2026
…mmarize actions (#21 v3)

User feedback on the screenshots pointed out two stacked mobile
issues with the memory view. Both are scoped to mobile — desktop
layout is unchanged.

1. About-you rows. The Delete button sat inline-right of the value
   column, so a long value (or a JSON NestedValue block) pushed
   Delete half off the card edge. Switch the row grid to
   `grid-cols-[auto_1fr] md:grid-cols-[auto_1fr_auto]` and put
   `col-span-2` on the Delete button on mobile so it spans both
   columns and slots under the value. Reverts to a single grid
   column on md+ where inline-right is fine.

2. Thread summaries. Two compounding issues:
   - The header packed Collapse + Delete side-by-side, so on
     narrow viewports the visible order was Collapse, Delete,
     Summary content — Delete landed BETWEEN the controls and
     the data it acts on. Pull Delete OUT of the header into a
     new row below the CollapsibleContent so the order is now
     Collapse → Summary → Delete. Delete is always visible
     (collapsed or not), separated by a `border-t` so it reads
     as a distinct action footer rather than a third button in
     the controls.
   - The CollapsibleContent had `ps-[calc(...)] === 56px` left
     padding to indent the Q&A under the title. On a 390 px
     viewport that eats ~14% of the row width for an indent that
     doesn't visually connect to anything (the row is now
     single-column on mobile). Drop the calc padding on both
     the content and the loading skeleton — desktop reads fine
     without it.
…+Delete grouped, dialog footer right-aligned + tests

Closes the round-3 / round-4 review feedback on the mobile thread
and dialog layouts.

#21 (round 4 — user edit):
- About-you store Delete button is now `w-full` + `col-span-2`
  on mobile so it sits full-width below the value (not inline-right
  where long values / JSON NestedValue blocks pushed it off the
  card edge). Reverts to inline col 3 + auto width on md+.

- Thread-summarize action row collapses/expands the gap between
  Expand and Delete and sandwiches the summary content between
  them on mobile (so the buttons stay visually adjacent as one
  action group), then on md+ the summary content swaps out for a
  second row below the header. Done by extracting SummaryContent
  as a React element variable and rendering it twice — once inside
  the mobile action wrapper, once below the desktop header row —
  with `md:hidden` / `hidden md:block` picking the visible copy
  at each breakpoint. (Both share the parent `<Collapsible open>`
  state, so the toggle stays coordinated despite the render split.)

- Chevron rotation switched from `rotate-180` to `rotate-90`
  so it points up when the row is expanded (down chevron above
  content reads better than left-pointing under the title).

- Dropped the `ps-[calc(...)]` left padding that pushed summary
  text 56 px to the right of the row origin on small viewports.

#26 (round 2 — user edit + dialog refactor):
- Dialog footer buttons (Cancel + Delete in both profile and
  thread confirmation dialogs) now have `w-full md:w-auto` so
  they fill the row on mobile and shrink to intrinsic width on
  desktop. Improves destructive-action reach on touch.

- Dialog footer items-start → items-end on mobile so buttons
  right-align instead of sitting against the modal edge.

Tests:
- 6 new regression tests pinning the responsive className choices
  for the issues above. Pattern: render the row, find the element
  by role/data-slot, assert the responsive Tailwind class is
  present (and that the wrong-class guard is absent).

- Existing tests updated to tolerate the new `SummaryContent`
  twice-render layout: the same Q&A text now appears in two
  DOM slots (mobile + desktop), so `getByText` assertions
  switched to `queryAllByText(...).length >= 1`. The toggle
  still drives both copies because they share the parent's
  `<Collapsible open>` state.
@FireTable FireTable changed the title fix(mobile-ui): batch 1 — 6 mobile UI fixes + 3 follow-ups (#21-#26) fix(mobile-ui): batch 1 — 6 mobile UI fixes + 4 follow-ups (#21-#26) Jul 10, 2026
Five small adjustments from the user's mobile review pass on the
observability panel.

1. StatCard label clipping. The label sits in a flex row with the
   icon, and on a 4-col grid of `5.5rem` cards the label string
   (e.g. "Output") can be pushed too far right and run into the
   next card. Add `line-clamp-1` to the icon row and
   `overflow-hidden whitespace-nowrap text-ellipsis` to the label
   so long labels truncate cleanly with "…" instead of bleeding
   into the next card.

2. WaterfallRow sticky-left label. Add `bg-background` so the
   sticky label column paints a solid background when the bar
   column scrolls under it — without bg the icon + name were
   bleeding through the column's right border as the right column
   moved. Inline-aligned with the prior `sticky left-0` rule.

3. Legend strip background. Add `sticky left-0` to the legend
   wrapper under the waterfall so the type chips stay pinned to
   the left viewport edge during horizontal scroll (matches the
   label column behavior). The container was `relative` already
   via the parent, so `left-0` pins in place.

4. TooltipPopup + SpanDetails whitespace. Two cosmetic indentation
   fixes that fell out of a fresh `pnpm lint` pass — no behavioral
   change.

5. Stat tile grid + token labels.
   - Force `grid-cols-4` at every breakpoint (was
     `grid-cols-2 sm:grid-cols-3 md:grid-cols-4`). The previous
     2-col mobile step is undesirable after the StatCard changes
     above — every tile can stay in a 4-col layout down to phone
     width now that the label truncates inside each card.
   - "token" → "tok" on Input/Output/Total labels. The full
     word was wrapping to two lines on phones and looking worse
     than the abbreviation.

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 7 files

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread components/observability/panel.tsx
Comment thread components/observability/panel.tsx
Comment thread components/settings/memory-view.tsx
Comment thread components/assistant-ui/thread.tsx
Comment thread components/observability/panel.tsx
Comment thread components/settings/memory-view.tsx
Comment thread components/settings/memory-view.tsx
Comment thread components/settings/memory-view.tsx
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.

[Bug]: Mobile Settings → Memory section text overflows (long URLs bleed past card edge)

1 participant