fix(taxonomic-filter): close reveal barrier on mount when already searching - #70212
Conversation
…rching The reveal barrier hides the result list until every visible group's async fetch settles, so a slower group can't render on top of a stale/partial list. It started open on every mount (`useState(true)`) and only closed via an effect that fires when the search query changes after mount. When the component mounts directly with a non-empty search query already set (e.g. reopening a saved filter), that "change" never happens, so the barrier stays open from the first render. Synchronous rows built straight from props (recents/pinned) can then paint before async-fetched rows (like the "URL contains <query>" shortcut) resolve, producing a nondeterministic row order. Compute `searching` at the point `revealBarrierOpen` is declared and use it to initialize the barrier's starting state, so it starts closed whenever the component mounts already in a search. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🤖 CI report✅ Bundle size — no changeUncompressed size of every built Total: 68.08 MiB · no change No file changed by more than 1000 B. Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report ✅ Eager graph — within budgetHow much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy
🟢 Largest files eagerly shipped from
|
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 668 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 278.2 KiB | ../node_modules/.pnpm/posthog-js@1.399.2/node_modules/posthog-js/dist/rrweb.js |
| 266.9 KiB | ../node_modules/.pnpm/@posthog+icons@0.37.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 234.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 221.5 KiB | ../node_modules/.pnpm/posthog-js@1.399.2/node_modules/posthog-js/dist/module.js |
| 164.0 KiB | src/queries/validators.js |
| 154.2 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Dist folder size — no change
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1283.90 MiB · no change
⚠️ Playwright — 2 failed
🎭 Playwright report · View test results →
❌ 2 failed tests:
- password-protected insight sharing (chromium)
- service facet passes serviceNames to API (chromium)
These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!
…ori/70212 # Conflicts: # frontend/src/lib/components/TaxonomicFilter/menu/Combobox.tsx
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
There was a problem hiding this comment.
Trivial, contained fix to initial state derivation in a frontend combobox; no risky territory, author has strong familiarity, and it's well explained with test verification.
- Author wrote 100% of the modified lines and has 17 merged PRs in these paths (familiarity STRONG).
- 👍 on the PR from hex-security-app[bot].
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 6L, 1F substantive — within ceiling |
| tier | ✓ | T1-agent / T1a-trivial (6L, 1F, single-area, fix) |
| stamphog 2.0.0b3 | .stamphog/policy.yml @ f221814 · reviewed head d2c25e7 |
Problem
The taxonomic filter's rebuilt combobox menu has a "reveal barrier" that holds the result list behind skeletons on a fresh search, until every visible group's fetch settles. This stops a slow group from rendering on top of a stale/partial list.
The barrier started open on every mount (
useState(true)) and only closed via an effect keyed on the search query changing after mount. When the component mounts directly with a non-empty search query already set (for example, reopening a saved filter), that "change" never happens, so the barrier stays open from the very first render.That let synchronous rows built straight from props (recents/pinned) paint before async-fetched rows (like the "URL contains <query>" shortcut) resolved, producing a nondeterministic row order. This surfaced as a flaky Jest test, quarantined by Trunk:
Combobox.test.tsx > MenuFilterCombobox > pageview url-contains shortcut leads the series picker All surface > puts the "url contains <query>" shortcut first, then recent, then pinned.Changes
frontend/src/lib/components/TaxonomicFilter/menu/Combobox.tsx: hoisted thesearchingderivation (!drillItems && !!searchQuery.trim()) up to whererevealBarrierOpenis declared, and used it to compute the barrier's initial state (useState(() => !searching)) instead of hardcodingtrue. Removed the now-duplicatesearchingdeclaration further down in the file. No behavior change for the steady-state (typing into an empty box) path — only the mount-with-a-query path is affected.How did you test this code?
Ran the target test in a loop to confirm the fix holds:
Combobox.test.tsxsuite (36 tests), all passing, no regressionsI attempted to reproduce the flake against unpatched
origin/masterfirst (80+ runs, sequential and with parallel contention), but did not hit a failure locally — the race is timing-sensitive and apparently rarer to trigger outside the original CI environment. The root cause is clear from reading the effect/mount logic, and the fix directly closes the gap: the barrier can no longer start open when the component mounts already in a search state.Automatic notifications
Docs update
N/A — internal test-stability fix, no user-facing or documented behavior changes.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
I (Claude, via Claude Code) diagnosed and applied this fix. The investigation started from a Trunk-quarantined flaky test; I traced the root cause to the reveal barrier's mount-time initialization in
Combobox.tsx, applied the minimal fix (compute-at-mount instead of hardcodedtrue), and validated it with repeated local test runs as described above.