Skip to content

fix(ui): keep the chat-create error until it is dismissed - #6912

Merged
kovtcharov-amd merged 1 commit into
amd:mainfrom
ityashag:fix/agent-ui-toast-and-mobile
Nov 7, 2026
Merged

kovtcharov-amd merged 1 commit into
amd:mainfrom
ityashag:fix/agent-ui-toast-and-mobile

Conversation

@ityashag

@ityashag ityashag commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Summary

The "chat was created, but..." error now stays visible until you dismiss it, and it no longer covers the chat box. The mobile-access button now follows window resizes through useMediaQuery.

Why

That error can say your message wasn't sent and is waiting in the chat's box, but it faded out after 2.5 seconds, which isn't long enough to read it. It also stayed in the page, invisible and still marked as an alert, until the next chat started.

App.tsx also read window.innerWidth during render, so nothing told it when the width changed. Usually the sidebar's own update re-renders it, but not when the drawer is already open.

Linked issue

Closes #4819

The issue's third defect, download progress polling at 5 s, is already fixed on main by createStatusPoller, so this PR doesn't touch it.

Changes

  • Adds a Dismiss button to the error, reusing the existing banner.dismiss text, which already has an Arabic translation.
  • Adds .toast-dismissible: no fade-out, clickable, and placed at the top of the window.
  • App.tsx uses useMediaQuery('(max-width: 768px)') for the mobile-access button.
  • Sidebar.tsx drops its own innerWidth read and uses the phone value it already had. This one is a cleanup: its test passes with or without the change.
  • Adds tests to App.newTask.test.tsx.

Decisions to check

  • Stays until dismissed, instead of clearing after the fade: this is a message someone may need to act on, so I kept it on screen.
  • Top of the window: at the default bottom position, it covered the chat box holding the unsent message. At the top, it can cover the banner and chat title until dismissed.

Test plan

Run in a node:22-slim container:

  • npx tsc --noEmit: passes.
  • npm test, rebased on current main: 272 files and 3,164 tests pass.
  • npx vite build: passes.
  • python util/lint.py --all: passes, with the existing mypy warnings. This PR changes no Python, so I didn't run pytest tests/unit/.
  • npm run test:rtl (light project): 7 failures with this PR and 8 without it, and all 7 also fail without it. Neither run reaches 0 in my container, so CI is the better check here.

With the source changes reverted, the new tests for the error and the mobile-access button fail:

× stays until it is dismissed
× offers mobile access as soon as a window widens with its drawer open
Tests  2 failed | 34 passed (36)

Evidence

The production build with visual/fixtures.ts and a refused permission-mode request, at 1200x760 in Chromium. The chat content is fixture data.

Measured main This PR
Error opacity after 6 s 0, still in the page 1
Dismiss button None Yes, and the error leaves the page
Mobile-access button 150 ms after widening with the drawer open Not shown Shown
Mobile-access button when narrowing or widening with the drawer closed Correct Correct

Main, after 1 s: the error covers the chat box

Main after 1 second

Main, after 6 s: the error has faded

Main after 6 seconds

This PR, after 6 s: the error is visible and the chat box is clear

This PR after 6 seconds

  • Agent exposed in the Agent UI: Agent UI shell only, shown above from a production build with fixture data, without a running backend or model.
  • MCP tools / servers: N/A
  • CLI: N/A
  • HTTP API / REST: N/A

Checklist

  • I have linked a GitHub issue above (Closes #N / Fixes #N / Refs #N).
  • I have described why this change is being made, not just what changed.
  • I have run linting and tests locally (python util/lint.py --all, pytest tests/unit/). Partly: util/lint.py and the web checks above. No Python changed, so I didn't run pytest.
  • I have attached real-world evidence matched to the surface I changed (see Evidence above), or marked each surface N/A.
  • I have updated documentation if user-visible behavior changed (see CONTRIBUTING.md). N/A: I found no docs describing this error.

@github-actions github-actions Bot added the electron Electron app changes label Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Verdict: Approve with suggestions

The "chat was created, but…" error used to fade after 2.5 s. It now stays on screen until it is dismissed, and it sits at the top of the window so it no longer covers the chat box holding the unsent message. The mobile-access button also updates when the window is resized with the drawer open. The fix is small and covered by tests that fail without it, and nothing here blocks the merge.

  • On the desktop app the error now sits inside the invisible strip that drags the window. Dragging on its text moves the window, and on a narrow Windows window it can slide under the minimise/close buttons. Excluding it from the drag strip is a one-line fix. Worth also checking the toast on the packaged app in Arabic before release.

Real-world evidence

N/A: no evidence bundle was produced for this run. The PR description embeds before/after screenshots from a production build with fixture data. On main the error covers the chat box at 1 s and has faded at 6 s; with this PR it is still visible at 6 s and the chat box is clear. That is the browser build, not the packaged desktop app, so the title-bar interaction below rests on static review only.

🔍 Technical details

Issues

🟢 Toast sits in the desktop title-bar drag band (src/gaia/apps/webui/src/styles/index.css:604)
With top: 16px, the toast lands inside the 48 px :root[data-titlebar] body::before drag region. .toast-dismiss is a button, so it is already no-drag and Dismiss works. The role="alert" container is not in the no-drag list, though, so a press on the message text drags the window instead of selecting the error to copy it. Suggested fix:

.toast-dismissible {
    top: 16px;
    bottom: auto;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: min(560px, calc(100vw - 32px));
    width: max-content;
    pointer-events: all;
    -webkit-app-region: no-drag;
    animation: toastIn var(--duration-spring) var(--ease-spring);
}

Separately, a 560 px centred toast on a window of about 770–900 px overlaps the Windows overlay controls (--titlebar-controls-w, top right) until it is dismissed. Either use top: calc(var(--titlebar-h) + 8px) under :root[data-titlebar], or accept it as a known trade-off; the PR's "Decisions to check" already names the banner overlap.

🟢 toastIn slides up from below at the top position (index.css:613)
The entry keyframe starts at translateY(8px), so the top toast rises into place rather than dropping in. This is cosmetic only; mention it if you want the motion to match the new position.

Checked, no issue

  • X and t are already in scope in App.tsx, and banner.dismiss has an Arabic string, so the button label goes through useT.
  • createError is still cleared when the next chat starts (App.tsx:492), so a stale error can't outlive a new chat.
  • useMediaQuery subscribes to change and cleans up. In Sidebar.tsx, phone is the same (max-width: 768px) query, so replacing isMobile there changes no behaviour.
  • The other toastOut user (ChatView.css:434) is untouched.

Strengths

  • Reuses the existing useMediaQuery hook and banner.dismiss string rather than adding new ones.
  • The tests drive real matchMedia change events, and the PR shows they fail with the source reverted.
  • The evidence table measures opacity at 6 s on both builds instead of only asserting it.

@kovtcharov-amd
kovtcharov-amd added this pull request to the merge queue Nov 7, 2026
Merged via the queue into amd:main with commit 4703c5b Nov 7, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

electron Electron app changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent UI shell: download progress polls at 5 s instead of 2 s, and the chat-create error toast never clears

2 participants