Skip to content

fix(sidebar): keep the notification repair state from blocking the session row - #171

Open
Luke-Norland wants to merge 1 commit into
devswha:mainfrom
Luke-Norland:fix/sidebar-bell-repair-row
Open

Luke-Norland wants to merge 1 commit into
devswha:mainfrom
Luke-Norland:fix/sidebar-bell-repair-row

Conversation

@Luke-Norland

@Luke-Norland Luke-Norland commented Oct 6, 2026 •

Copy link
Copy Markdown

Bug

When a session's completion notifications are turned on but the current browser has no push subscription (for example, the bell was turned on from another device), the bell enters the repair state and shows "Repair notifications when the assistant has a reply ready on this device".

SessionCompletionBell rendered that sentence as visible text (max-w-48 text-xs text-destructive, about 192px, wrapping to five lines) inside a flex shrink-0 wrapper in the row's actions slot. On the desktop sidebar this:

  • squeezed the row's open button (flex min-w-0 flex-1) to about 12px;
  • laid the red text over the session name, so clicking the name hit the text span and the session could not be opened;
  • pushed the wrench (repair) button past the sidebar's right edge, where overflow clipped it.

The environmental reasons (permission denied or not granted, secure context required, iOS install required, unsupported) also showed visible text, so they had the same effect.

How to reproduce

  1. Run a local agent session in tmux so it appears in the sidebar.
  2. Turn on completion notifications for it from one browser, then open ChatMux in a browser that has no push subscription (or call PUT /api/settings/completion-notifications with watched: true).
  3. The row shows the wrapped red sentence. Clicking the session name does nothing, and the wrench is cut off at the sidebar edge.

Fix

  • The status span is always sr-only. It is still announced (role="status", aria-live="polite") and still the buttons' aria-describedby.
  • In the repair state the row shows only the bell and the wrench, at the bell's existing size. The wrench already carries the repair sentence as title and aria-label, and still calls repairDevice.
  • For an environmental reason, the sentence is added to the bell's tooltip.
  • External and live rows both use this component, so both are fixed.

No notification logic, watch semantics or layout tokens change.

Tests

SessionCompletionBell.test.tsx:

  • the environmental-guidance test now asserts the guidance is not visible row text, is still announced, and is in the bell's tooltip;
  • a new test asserts that the repair state renders a wrench whose title and aria-label are the repair sentence, with no visible status text.

Both tests fail on main (7 pass, 2 fail) and pass with the fix (9/9). Restoring the visible status class turns the same two tests red. The sidebar placement, external-row and live-row tests still pass. npm run typecheck and eslint on the touched files are clean.

Browser check

A dev server with one session in the repair state and one normal session, in Chromium at 1400×900 and at 390×844 (sidebar opened from the menu), light and dark:

main this PR
elementFromPoint at the session name's centre is inside the open button no (hits the status text) yes
wrench lies inside the sidebar no (clipped) yes
open button width, desktop 12px 138px

In the repair state the open button is about half the row, so a long session name truncates until the device is repaired. A normal row is unchanged.

Summary by CodeRabbit

  • Accessibility
    • Completion-status messages remain available to screen readers while no longer appearing as visible row text.
    • Bell tooltips show environmental-action guidance when applicable, and repair-required status is announced accessibly.
  • Bug Fixes
    • Environmental errors do not display a repair button; watched sessions requiring repair continue to show one.

…ssion row

A watched session whose browser has no push subscription shows the
repair state: "Repair notifications when the assistant has a reply ready
on this device". The bell rendered that sentence as visible row text
(max-w-48, about 192px, wrapping to five lines) inside a shrink-0
wrapper in the row's actions slot. It squeezed the row's open button to
about 12px, covered the session name so clicks landed on the text, and
pushed the repair (wrench) button past the sidebar's edge, where it was
clipped. The session could not be opened from the sidebar.

The status span is now always sr-only. It is still announced and still
the buttons' aria-describedby. In the repair state the row shows only
the bell and the wrench at the bell's existing size; the wrench already
carries the repair sentence as its title and aria-label and still runs
repairDevice. Environmental reasons that used to show visible text
(permission denied, insecure context, iOS install, unsupported) become
part of the bell's tooltip. External and live rows share the component.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 957714bb-d15c-4935-abcb-876546706a75
📥 Commits

Reviewing files that changed from the base of the PR and between b258b57 and b334b8b.

📒 Files selected for processing (2)
  • src/components/sidebar/view/subcomponents/SessionCompletionBell.test.tsx
  • src/components/sidebar/view/subcomponents/SessionCompletionBell.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The session completion bell now keeps status text out of the visible row while preserving screen-reader announcements. Its tooltip includes environmental status text when action is required and device repair is not required. Tests cover these behaviors and repair-required status.

Changes

Session completion status

Layer / File(s) Summary
Status presentation and coverage
src/components/sidebar/view/subcomponents/SessionCompletionBell.tsx, src/components/sidebar/view/subcomponents/SessionCompletionBell.test.tsx
The status text is always screen-reader-only. The bell title uses the computed tooltip text. Tests check environmental guidance and repair-required status.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to b334b

Status guidance remains available through screen-reader announcements and applicable tooltips. No supported issue blocks merging.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: preventing the notification repair state from obstructing the session row.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/components/sidebar/view/subcomponents/SessionCompletionBell.test.tsx

Oops! Something went wrong! :(

ESLint: 9.39.5

Error: Error while loading rule 'tailwindcss/no-contradicting-classname': Could not find tailwindcss
Occurred while linting /src/components/sidebar/view/subcomponents/SessionCompletionBell.test.tsx
at new TailwindUtils (/.eslint-tmp/node_modules/tailwind-api-utils/dist/index.cjs:375:13)
at resolve (/.eslint-tmp/node_modules/eslint-plugin-tailwindcss/lib/util/customConfig.js:21:27)
at getTailwindConfig (/.eslint-tmp/node_modules/eslint-plugin-tailwindcss/lib/util/tailwindAPI.js:9:17)
at Object.create (/.eslint-tmp/node_modules/eslint-plugin-tailwindcss/lib/rules/no-contradicting-classname.js:71:26)
at createRuleListeners (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:1019:15)
at /.eslint-tmp/node_modules/eslint/lib/linter/linter.js:1151:7
at Array.forEach ()
at runRules (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:1085:31)
at #flatVerifyWithoutProcessors (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:2115:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:2203:43)

src/components/sidebar/view/subcomponents/SessionCompletionBell.tsx

ESLint skipped: the matched ESLint configuration already failed (plugin-compatibility).


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

This branch has not been deployed

No deployments
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