Skip to content

[MC-460-A] fix(frontend): scroll active concept into view in Compare/Tags too#650

Merged
TrueNorth49 merged 1 commit into
mainfrom
mc-460-a-global-concept-scroll
Jun 3, 2026
Merged

[MC-460-A] fix(frontend): scroll active concept into view in Compare/Tags too#650
TrueNorth49 merged 1 commit into
mainfrom
mc-460-a-global-concept-scroll

Conversation

@TrueNorth49

Copy link
Copy Markdown
Collaborator

MC Task: MC-460 — Concept menu auto-scroll only works on Annotate / Lane MC-460-A

Summary

The concept-menu auto-scroll (keep the selected entry in view) was intended to work in every mode, but only fired on the Annotate page.

Root cause

The scroll effect in ParseUI.tsx depended solely on selectedRealizationKey:

useEffect(() => {
  if (!selectedRealizationKey) return;   // bails when null
  // …scroll the [data-realization-key] chip into view
}, [selectedRealizationKey]);
  • Annotate navigates by realization (goToRealizationOffset), which sets selectedRealizationKey → effect fires → menu scrolls. ✅
  • Compare / Tags navigate by concept (goToConceptOffset), which explicitly does setSelectedRealizationKey(null) and only updates conceptId. The effect bailed at the null guard, so the menu never followed the selection. ❌

The effect itself was already global and the sidebar (ConceptSidebar) is shared across all modes — the trigger was just realization-specific, a value only Annotate produces.

Fix

When no realization is selected, fall back to scrolling the active concept's parent row ([data-testid="concept-parent-button-${conceptId}"], already rendered by ConceptSidebar), and add conceptId to the dependency array so concept-level navigation also triggers the scroll.

Testing

  • Added a regression test: in Compare mode, ArrowDown between concepts scrolls the active concept's parent row into view (asserts scrollIntoView is called on concept-parent-button-3).
  • npx vitest run src/ParseUI.test.tsx — 138 passed / 7 skipped
  • npx tsc --noEmit — clean
  • npm run build — green

🤖 Generated with Claude Code

…Tags too

The sidebar auto-scroll effect only depended on selectedRealizationKey.
Annotate navigates by realization (which sets that key), but Compare/Tags
navigate by concept via goToConceptOffset, which clears selectedRealizationKey
and only updates conceptId. The effect bailed on the null key, so the concept
menu never followed the selection outside Annotate.

Fall back to the active concept's parent row ([data-testid=concept-parent-button-N])
when no realization is selected, and add conceptId to the dependency array.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TrueNorth49 TrueNorth49 added MC-460 Mission Control MC-460 bugfix Bug fix labels Jun 3, 2026
@TrueNorth49

Copy link
Copy Markdown
Collaborator Author

Self-review — [MC-460-A]

Overview: Generalizes the sidebar auto-scroll so it follows the active concept in Compare/Tags, not just realization pills in Annotate. Single effect change + regression test.

Correctness ✅

  • concept-parent-button-${concept.id} is rendered for every concept row in ConceptSidebar, so the fallback selector always resolves to a real element.
  • Branch logic is sound: realization key present → scroll the pill (Annotate, unchanged); absent → scroll the active concept row (Compare/Tags). conceptId added to deps so concept-level navigation re-fires the effect.
  • conceptId is a numeric state (useState(1)), so interpolating it into the selector string is injection-safe.
  • typeof … === 'function' guard retained for jsdom/no-scroll environments.

Notes / minor

  • Behavior change on mount and on Annotate concept-level fallback: the effect now also scrolls when selectedRealizationKey is null (previously a no-op). { block: 'nearest' } makes this a no-op when the row is already visible, so it's harmless and actually more consistent.
  • Tags mode benefits on click selection; arrow keys still return early before concept navigation in Tags (pre-existing, out of scope).

Tests ✅

  • Added Compare-mode regression test asserting scrollIntoView fires on concept-parent-button-3 after ArrowDown. Mutates Element.prototype.scrollIntoView and restores in finally.
  • vitest src/ParseUI.test.tsx 138 passed / 7 skipped · tsc --noEmit clean · npm run build green.

No blockers.

@TrueNorth49 TrueNorth49 merged commit 1ff9a14 into main Jun 3, 2026
4 checks passed
@TrueNorth49 TrueNorth49 deleted the mc-460-a-global-concept-scroll branch June 3, 2026 11:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Bug fix MC-460 Mission Control MC-460

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant