fix: botões sem resposta — remove v7_startTransition + scroll-lock proativo + guard 300ms#328
Conversation
…a — limpa pointer-events preso do Radix
… travada 5x menor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Your plan includes 5 reviews of capacity. Refill in 31 minutes and 26 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
Pull request overview
Este PR corrige um cenário em que cliques/navegações aparentavam “não responder” na SPA, eliminando uma causa de navegação abandonada por concorrência, liberando scroll-lock residual de forma proativa e reduzindo a janela de recuperação do watchdog de interatividade.
Changes:
- Remove
v7_startTransition: truedoBrowserRouterpara evitar navegações “low priority” abandonadas sob carga de re-renders concorrentes. - Em toda mudança de rota, chama
releaseScrollLockIfIdle()para desfazerpointer-events: nonepreso em<html>/<body>quando não há overlay legítimo aberto. - Reduz o intervalo do
RootInteractivityGuardde 1500ms para 300ms e adensa timeouts de boot.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/App.tsx | Remove v7_startTransition do router e documenta o motivo do bug/fix. |
| src/components/common/RouteScrollReset.tsx | Libera scroll-lock residual do Radix em mudanças de rota antes do scroll reset. |
| src/components/system/RootInteractivityGuard.tsx | Acelera o watchdog e ajusta boot-time checks para reduzir janela de UI “travada”. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * BUG FIX: intervalo reduzido de 1500ms -> 300ms para encurtar a janela de | ||
| * tempo em que a UI pode ficar travada entre dois ciclos do watchdog. | ||
| * O overhead e negligivel (apenas getComputedStyle em 3 elementos por ciclo). | ||
| * Boot-time timeouts tambem adensados: [0, 100, 300, 600, 1000]. |
| // BUG FIX: intervalo reduzido 1500ms -> 300ms. Boot-times adensados. | ||
| const timeouts = [0, 100, 300, 600, 1000].map((d) => window.setTimeout(() => check(true), d)); | ||
| const interval = window.setInterval(() => check(true), 300); |
| * Em navegacoes SPA (PUSH/REPLACE), rola a window suavemente ate o topo, | ||
| * para que o conteudo da nova rota seja exibido a partir do inicio. | ||
| * | ||
| * Regras: | ||
| * - POP (back/forward) preserva o scroll do navegador. | ||
| * - Se a URL contém hash âncora (#id), respeita o destino e não força topo. | ||
| * - Se a URL contem hash ancora (#id), respeita o destino e nao forca topo. | ||
| * - Honra `prefers-reduced-motion` (fallback para `behavior: "auto"`). | ||
| * - Skip no primeiro mount (evita interferir em deep-links com âncora). | ||
| * - Skip no primeiro mount (evita interferir em deep-links com ancora). | ||
| * | ||
| * BUG FIX: A cada mudanca de rota, libera proativamente qualquer scroll-lock | ||
| * residual do Radix UI (pointer-events: none preso em <html>/<body>). Isso | ||
| * previne o cenario em que um Dialog/Dropdown fecha com race condition e | ||
| * deixa a UI completamente nao-clicavel ate o watchdog de 300ms agir. | ||
| * releaseScrollLockIfIdle() e no-op se houver overlay legitimo aberto. |
| {/* | ||
| * BUG FIX: v7_startTransition REMOVIDO. | ||
| * | ||
| * v7_startTransition: true envolvia toda chamada navigate() em | ||
| * React.startTransition(), tornando navegacoes low-priority. | ||
| * Com rendering concorrente ativo (Supabase Realtime, intervals | ||
| * do RootInteractivityGuard, etc.), o React abandonava transicoes | ||
| * de navegacao — a URL atualizava no window.history mas o | ||
| * componente nao re-renderizava, dando a impressao de que o clique | ||
| * nao fez nada. Hard refresh carregava a URL ja atualizada e | ||
| * parecia "executar" a acao. | ||
| * | ||
| * v7_relativeSplatPath mantido — normaliza apenas matching de | ||
| * splat routes e nao afeta rendering concorrente. | ||
| */} |
…ntInput main and this PR independently converged on a fix for the non-distributive Omit over the BridgeStatusEvent union. main shipped first (PR #328 chain) with a mapped-type `BridgeStatusEventInput`; this PR had an equivalent `DistributiveOmit`. Adopting main's version keeps a single source of truth and unblocks the merge.
* fix(supabase): realign frontend with live DB schema Regenerate src/integrations/supabase/types.ts from the live database (141->296 tables, 1->115 views, 65->385 functions) so the typed client matches reality, then fix every drift the accurate types surfaced. - Decode src/lib/supabase-untyped.ts and scripts/lint-untyped-from.sh, which were committed base64-encoded since #319 and broke compilation. - Fix nullability drift across admin/security, dashboard, quotes and intelligence hooks (DB columns are nullable; code assumed non-null). - Fix real runtime bugs hidden by the stale types: - quotes.client_name is NOT NULL -> stop inserting null. - quote_items.subtotal is required -> compute it on insert. - search_analytics uses user_id (not seller_id) and has no filters_used column -> correct the insert. - Restore the set_quote_number BEFORE INSERT trigger (migration) lost in the migration-replay drift; without it quote creation fails the quote_number NOT NULL constraint. Inserts now pass an empty quote_number for the trigger to populate. - Migrate intelligence untypedFrom() calls to typed supabase.from(); drop now-unnecessary `as any` casts in the kill-switch client/telemetry. tsc baseline: 484 errors (-24 vs 508, no regressions). eslint baseline clean. Build and affected unit tests pass. * fix(merge): resolve conflict with main — adopt main's BridgeStatusEventInput main and this PR independently converged on a fix for the non-distributive Omit over the BridgeStatusEvent union. main shipped first (PR #328 chain) with a mapped-type `BridgeStatusEventInput`; this PR had an equivalent `DistributiveOmit`. Adopting main's version keeps a single source of truth and unblocks the merge. * fix(merge): resolve conflict — adopt main's useKillSwitchBanner (lighthouse placeholder + dynamic import) * fix(merge): resolve conflict — adopt main's kill-switch-client tests * fix(merge): resolve conflict — adopt main's kill-switch-client (rollout gradual + typed cast) * fix(merge): resolve conflict — adopt main's kill-switch-telemetry (typed cast for kill_switch_hits) --------- Co-authored-by: Claude <noreply@anthropic.com>
* fix(supabase): realign frontend with live DB schema Regenerate src/integrations/supabase/types.ts from the live database (141->296 tables, 1->115 views, 65->385 functions) so the typed client matches reality, then fix every drift the accurate types surfaced. - Decode src/lib/supabase-untyped.ts and scripts/lint-untyped-from.sh, which were committed base64-encoded since #319 and broke compilation. - Fix nullability drift across admin/security, dashboard, quotes and intelligence hooks (DB columns are nullable; code assumed non-null). - Fix real runtime bugs hidden by the stale types: - quotes.client_name is NOT NULL -> stop inserting null. - quote_items.subtotal is required -> compute it on insert. - search_analytics uses user_id (not seller_id) and has no filters_used column -> correct the insert. - Restore the set_quote_number BEFORE INSERT trigger (migration) lost in the migration-replay drift; without it quote creation fails the quote_number NOT NULL constraint. Inserts now pass an empty quote_number for the trigger to populate. - Migrate intelligence untypedFrom() calls to typed supabase.from(); drop now-unnecessary `as any` casts in the kill-switch client/telemetry. tsc baseline: 484 errors (-24 vs 508, no regressions). eslint baseline clean. Build and affected unit tests pass. * fix(merge): resolve conflict with main — adopt main's BridgeStatusEventInput main and this PR independently converged on a fix for the non-distributive Omit over the BridgeStatusEvent union. main shipped first (PR #328 chain) with a mapped-type `BridgeStatusEventInput`; this PR had an equivalent `DistributiveOmit`. Adopting main's version keeps a single source of truth and unblocks the merge. * fix(merge): resolve conflict — adopt main's useKillSwitchBanner (lighthouse placeholder + dynamic import) * fix(merge): resolve conflict — adopt main's kill-switch-client tests * fix(merge): resolve conflict — adopt main's kill-switch-client (rollout gradual + typed cast) * fix(merge): resolve conflict — adopt main's kill-switch-telemetry (typed cast for kill_switch_hits) --------- Co-authored-by: Claude <noreply@anthropic.com>
Bug reportado
Diagnóstico: 3 causas raiz sobrepostas
Bug #1 — PRINCIPAL:
v7_startTransition: trueabandona navegações (App.tsx)v7_startTransition: truenoBrowserRouterenvolve todonavigate()emReact.startTransition(), tornando navegações low-priority.Sequência do problema:
navigate('/rota-x')é chamadoRootInteractivityGuarddisparasetRecoveries()a cada 1500ms, Supabase Realtime publica eventos, outros re-renders ocorrem — todos alta prioridadewindow.history(pushState ocorre), mas o componente React não re-renderiza/montaFix: Remove
v7_startTransition: true. O flagv7_relativeSplatPath: trueé mantido.Bug #2 —
pointer-events: nonepreso no body (RouteScrollReset.tsx)O próprio
scroll-lock.tsdocumenta: "A well-known race can leave those styles stuck after the overlay closes/unmounts, which makes the entire UI unclickable."O
RootInteractivityGuardcorrige isso, mas só checa a cada 1500ms. Quando Dialog/Dropdown/Sheet fecha com race condition, cliques são engolidos em silêncio por até 1,5 segundos.Fix:
RouteScrollResetagora chamareleaseScrollLockIfIdle()em toda mudança de rota — proativo, sem esperar o watchdog.releaseScrollLockIfIdle()é no-op se houver overlay legítimo aberto.Bug #3 — Intervalo do watchdog muito longo (
RootInteractivityGuard.tsx)Fix: Intervalo reduzido de 1500ms → 300ms. Overhead negligível (getComputedStyle em 3 elementos). Boot-time timeouts adensados: [0, 100, 300, 600, 1000].
Arquivos alterados
src/App.tsxv7_startTransition: truedo BrowserRoutersrc/components/common/RouteScrollReset.tsxreleaseScrollLockIfIdle()em toda mudança de rotasrc/components/system/RootInteractivityGuard.tsxAção adicional recomendada (não neste PR)
Mutations que gravam no Supabase devem chamar
queryClient.invalidateQueries()noonSuccess. Sem isso, a UI continua mostrando dados stale do cache (staleTime global = 10min) mesmo após a gravação ter sido bem-sucedida. Hard refresh forçarefetchOnMount: truee busca os dados atualizados.Exemplo padrão:
Summary by cubic
Corrige os “botões sem resposta” e navegações que falhavam silenciosamente. Cliques e trocas de rota agora aplicam de imediato, sem precisar de hard refresh.
v7_startTransitionnoBrowserRouter(react-router-dom) para evitar navegações abandonadas; mantémv7_relativeSplatPath.releaseScrollLockIfIdle()(impedepointer-events: nonepreso após overlays).RootInteractivityGuardde 1500ms para 300ms e adensa os boot checks [0, 100, 300, 600, 1000] para recuperação mais rápida.Written for commit 7298042. Summary will update on new commits. Review in cubic