Skip to content

fix: use scoped ref instead of global .glass-card querySelector for wizard scroll - #1381

Open
omoh5 wants to merge 5 commits into
LabsCrypt:mainfrom
omoh5:fix/1227-scoped-wizard-scroll
Open

fix: use scoped ref instead of global .glass-card querySelector for wizard scroll#1381
omoh5 wants to merge 5 commits into
LabsCrypt:mainfrom
omoh5:fix/1227-scoped-wizard-scroll

Conversation

@omoh5

@omoh5 omoh5 commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces a fragile global DOM query (document.querySelector('.glass-card')) with a scoped ref (dialogRef.current) for the wizard's scroll-to-top behavior, eliminating the risk of accidentally scrolling the wrong element.

Problem

StreamCreationWizard.tsx:325-327handleNext uses document.querySelector('.glass-card') to scroll the modal into view when advancing to the next step:

const modal = document.querySelector('.glass-card');
if (modal && typeof modal.scrollTo === 'function') {
  modal.scrollTo({ top: 0, behavior: 'smooth' });
}

.glass-card is a shared CSS class used across many unrelated components (stream detail cards, stat cards, event history panels, etc.). If any other .glass-card element renders earlier in the DOM while the wizard is open, the wrong element scrolls — a latent, hard-to-debug UI regression.

Solution

Replaced the global querySelector with dialogRef.current — the ref already attached to the wizard's own scrollable container via useModalDialog. This is a one-line fix:

// Before (fragile — matches any .glass-card in the DOM)
const modal = document.querySelector('.glass-card');

// After (scoped — always targets the wizard's own container)
if (dialogRef.current && typeof dialogRef.current.scrollTo === 'function') {
  dialogRef.current.scrollTo({ top: 0, behavior: 'smooth' });
}

dialogRef is returned by useModalDialog and attached to the wizard's inner <div className="glass-card ... max-h-[90vh] overflow-y-auto">, so it always points to the correct scroll container.

Files Changed

File Change
frontend/src/components/stream-creation/StreamCreationWizard.tsx Replace document.querySelector('.glass-card') with dialogRef.current
frontend/src/__tests__/stream-creation-wizard-scroll.test.tsx New test file with 2 tests

Tests

Created stream-creation-wizard-scroll.test.tsx with two tests:

  1. "scrolls the wizard's own container, not a different .glass-card element" — Renders the wizard alongside a sibling .glass-card element, spies on scrollTo of both, clicks "Next", and verifies only the wizard's container was scrolled.

  2. "does not query the global DOM for .glass-card when scrolling" — Monkey-patches document.querySelector to throw if .glass-card is queried, then clicks "Next" and verifies no such call was made.

Both tests pass alongside all existing tests (31 total in the related test files).

Closes #1227

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com

dedukpe and others added 5 commits August 30, 2026 15:05
Replace npm install with npm ci in backend/Dockerfile (both builder and
runner stages), render.yaml, and vercel.json to ensure deterministic,
lockfile-pinned dependency installs in production builds. This eliminates
the risk of dependency drift between CI-tested and deployed versions.

Closes LabsCrypt#1256

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
The setInterval(updateClaimable, 1000) in stream-details-content.tsx
was running every second regardless of whether the tab was visible,
wasting CPU/battery on backgrounded tabs. This mirrors the approach
already used by the useStreamingAmount hook (requestAnimationFrame +
document.hidden guard) but keeps the bigint arithmetic intact.

- Extract computeClaimable() so the value can be recalculated on demand
- Guard the interval callback with document.hidden check
- Add visibilitychange listener to resync immediately when tab returns
  to foreground (matching useStreamingAmount's resync behavior)
- Add test verifying no state updates occur while document.hidden is true

Closes LabsCrypt#1242

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
The catch block in useStreamEvents.handleEvent was silently ignoring
JSON.parse failures with an empty catch and no logging. This made it
impossible to diagnose malformed SSE frames in production. Now logs
the error, event type, and raw payload via logger.error for debugging.

- Import logger from @/lib/logger (consistent with codebase convention)
- Log parse failures with type, raw payload, and error details
- Add MockEventSource.emitRaw() helper for testing non-JSON payloads
- Add test verifying a malformed SSE frame produces a logged error

Closes LabsCrypt#1210

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
…izard scroll

handleNext used document.querySelector('.glass-card') to scroll the
modal to top when advancing steps. Since .glass-card is reused across
many unrelated components, this could accidentally scroll the wrong
element if another .glass-card rendered earlier in the DOM.

Replaced with dialogRef.current — the ref already attached to the
wizard's own scroll container via useModalDialog. This guarantees
the scroll always targets the correct element regardless of what
other .glass-card elements exist on the page.

- Replace document.querySelector('.glass-card') with dialogRef.current
- Add test: scroll targets wizard's own container, not sibling .glass-card
- Add test: no document.querySelector('.glass-card') call during scroll

Closes LabsCrypt#1227

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
The backend Dockerfile uses npm ci (from PR LabsCrypt#1256) which requires a
package-lock.json. Since this is an npm workspaces monorepo, the
lockfile lived only at the root and wasn't available in the backend/
build context. Generated a standalone backend/package-lock.json so
npm ci can resolve exact dependency versions in the Docker build.

Also added a root .dockerignore for future-proofing.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
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.

[Audit] Fragile DOM-query-based scroll-to-top in the wizard

2 participants