fix(web): collapse the mobile "Live" badge into the action bar (IDEA-2297) - #1038
Merged
Conversation
…2297) At <=768px the collection page hid the h1 (the name lives in MobileContextBar) but left the SSE status badge in .title-group, so that row rendered a full line containing nothing but "* Live". The badge now has a mobile mount at the trailing edge of .header-actions, collapsed to the coloured dot alone, and .title-group drops out of layout entirely -- a 0-height flex item still collected .title-row's 12px column gap, which was the last of the wasted row. Desktop is unchanged: the labelled badge stays beside the title. Compact mode CLIPS the label rather than removing it. The span is a role="status" live region and live regions announce on text-content change, so an aria-label-only element wouldn't reliably announce a drop to "Offline". Also gives the action bar one control height (IDEA-2297's second half). The row mixed four: the quick-actions trigger ~22px, New ~24px (no border), the view dropdown ~26px, icon buttons 28px. All are 28px now. The trigger is normalised in the page rather than in QuickActionsMenu because ItemDetail's .meta-actions band sizes the same trigger to its own padding-based metrics; a height baked into the shared component would fight it. Same override shape and specificity reasoning that band already documents -- the child's scoped .trigger-btn.svelte-<hash> is (0,2,0), so a bare :global(.trigger-btn) would tie and be settled by cross-file source order. Mobile gaps go 12px -> 4px. The six controls total ~255px, so the dot's 12px inset didn't fit on one line at 360px (a common Android width) and wrapped, re-creating the row this change removes. Only the gaps shrink; the controls stay 28px, so touch targets are untouched. Verified in the browser against the installed binary: single row with a 12px inset at 430/390/375/360 (wraps at 340, as before); desktop badge still in .title-group with its label visible and aria-label="Live updates: Live" intact on both breakpoints; no horizontal overflow. npm run check clean, 490 web unit tests pass. Claude-Session: https://claude.ai/code/session_01E2fRi12n8rARczvdEa2LYT
Codex review of #1038: with the label clipped in compact mode, hue was the only thing separating Live from Offline -- colour-alone conveyance (WCAG 1.4.1), and red/green is the exact pair dichromatic vision collapses. Healthy is now a FILLED dot and every unhealthy state is a hollow ring, so the distinction that matters ("is the stream up?") is carried by shape. Reconnecting stays separated from Offline by its pulse, and by hue for anyone running reduced-motion. Scoped to compact mode -- the labelled desktop variant already names the state in words. Verified by forcing each status class onto the live badge and reading computed styles at 390px: connected is a filled green 8px dot (border-width 0), reconnecting/disconnected/unauthorized are transparent with a 2px currentColor ring in their own hue, all 8px. Claude-Session: https://claude.ai/code/session_01E2fRi12n8rARczvdEa2LYT
Codex re-review of #1038: the hollow ring told Live apart from the unhealthy states, but Reconnecting leaned on its pulse to separate itself from Offline -- and the pulse is switched off under prefers-reduced-motion, leaving amber-vs-red as the only difference for those users. Reconnecting now takes a dashed ring. Three states, three shapes -- filled, dashed ring, solid ring -- independent of both hue and motion. Verified at 390px by forcing each status class and reading computed styles under both prefers-reduced-motion settings: connected filled (border-width 0), reconnecting transparent + 2px dashed, disconnected transparent + 2px solid; the pulse animation resolves to none under reduce while the dashed ring persists. Claude-Session: https://claude.ai/code/session_01E2fRi12n8rARczvdEa2LYT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes IDEA-2297.
The wasted row
At ≤768px the collection page hides the
<h1>(the collection name lives in MobileContextBar since IDEA-1835) but leftSSEStatusIndicatorin.title-group— so that row rendered a full line containing nothing but "● Live", stacked above the toolbar.The badge now has a mobile mount at the trailing edge of
.header-actions, collapsed to the coloured dot, pushed right bymargin-left: auto(.header-actionsiswidth: 100%under 768px, so nojustify-contentchange is needed)..title-groupdrops out of layout entirely on mobile — with no rendered children it was still a 0-height flex item collecting.title-row's 12px column gap, which was the last of the wasted row.Desktop is unchanged — the labelled badge stays beside the title.
Compact mode clips
.sse-state-labelrather than removing it: the span is arole="status"live region, and live regions announce on text-content change, so anaria-label-only element wouldn't reliably announce a drop to "Offline".Uniform control height
IDEA-2297's second half. The row mixed four heights — quick-actions ⚡ trigger ~22px, New ~24px (no border), view dropdown ~26px, icon buttons 28px. All 28px now.
The ⚡ trigger is normalised in the page, not in
QuickActionsMenu:ItemDetail's.meta-actionsband sizes that same trigger to its own padding-based metrics, and a height baked into the shared component would fight it. This uses the same override shape and specificity reasoning that band already documents — the child's scoped.trigger-btn.svelte-<hash>is (0,2,0), so a bare:global(.trigger-btn)would tie and be settled by cross-file source order; the child combinator takes it to (0,3,0).Mobile gaps 12px → 4px
The six controls total ~255px, so the dot's 12px inset didn't fit on one line at 360px (a common Android width) and wrapped — re-creating the row this PR removes. Only the gaps shrink; the controls stay 28px, so touch targets are untouched.
Verification
Playwright against the installed binary,
/dave/docapp/bugs:.header-actionsheightDesktop: badge still in
.title-group, label visible,aria-label="Live updates: Live"intact on both breakpoints. All four controls measure 28px on both breakpoints. No horizontal overflow at any width tested.npm run checkclean (no new warnings), 490 web unit tests pass. No E2E selector depends on.sse-stateor.title-group; the nine.trigger-btnlocators inweb/e2e/are click/visibility assertions, anditem-action-bar-band.spec.tsscopes to.meta-actions, which these rules don't reach.https://claude.ai/code/session_01E2fRi12n8rARczvdEa2LYT