Skip to content

feat(search): include folders as navigable search results - #14

Merged
arpit-bruno merged 10 commits into
usebruno:mainfrom
sundram-bruno:feat/search-folder-results
Jul 30, 2026
Merged

feat(search): include folders as navigable search results#14
arpit-bruno merged 10 commits into
usebruno:mainfrom
sundram-bruno:feat/search-folder-results

Conversation

@sundram-bruno

@sundram-bruno sundram-bruno commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Problem

Docs search indexed requests only. Folders never appeared as results. They existed in search purely as a filter chip and as the breadcrumb line under a matched request. Searching a folder by name returned nothing, and there was no way to reach a folder page from search, even though those pages exist and are routable.

JIRA : BRU-3949

Behaviour

Folders are results

  • A folder is returned as its own result, at any nesting depth, matched on its name.
  • The row shows a folder icon where a request shows its method, the folder name, its breadcrumb, and how many requests it holds , counted through subfolders, ignoring script files.
  • Matched characters in the name are bolded.
  • Choosing a folder opens its page and expands the sidebar to it.

Folders rank above requests

  • Every matching folder is listed before any matching request. Relevance orders each group internally.

What gets matched

  • Requests match on name and URL. Folders match on name only, a folder has no endpoint.
  • Breadcrumbs are no longer matched. Typing a folder name returns that folder, not the requests inside it.

Breadcrumbs

  • Shown on both folder and request rows, so two folders sharing a name in different branches (billing/customers/auth vs products/users/auth) can be told apart.
  • A top-level item shows none, having no chain.
  • A chain of more than three folders is shortened to first / … / last.
  • The result name keeps the width it needs and the breadcrumb yields first, so a long chain can no longer squeeze the name out or push the list into a sideways scroll.
  • Where text was cut — by a shortened chain or by the row running out of room, hovering it reveals the full text.

Filters

  • An active method chip hides folders, which have no method.
  • The folder filter returns the chosen folder itself as well as its contents.
image

@sundram-bruno
sundram-bruno marked this pull request as ready for review July 28, 2026 20:17
@arpit-bruno
arpit-bruno requested a review from sachin-bruno July 29, 2026 11:10
@sachin-bruno

Copy link
Copy Markdown
Contributor

The search-key removal is done (Fuse matches name+url only ✓), but the breadcrumb is still shown in every result row, and the tests/CSS/fixtures all encode showing it. So the code intends to display breadcrumbs — the PR's "breadcrumbs no longer shown in the search results UI" is stale. Reconcile: if breadcrumbs should stay (the code + tests say yes), fix the PR description; if they should truly go, delete the rendering + its tests. This is the item you asked me to verify.

Two e2e tests pass vacuously — search.spec.ts tests "a result name shown whole gets no tooltip" and "a breadcrumb shown whole gets no tooltip". Both assert toHaveCount(0) right after hover(); toHaveCount(0) succeeds on the first poll (count is 0 before the 500ms dwell), so a regression that opens the tooltip for un-clipped text would ship uncaught. Fix: await page.waitForTimeout(900) before the assertion, like the sibling "leaving a breadcrumb before the dwell…" test.

Can you please check these edge cases @sundram-bruno

@sundram-bruno sundram-bruno changed the title feat(search): include folders as navigable search results (BRU-3949) feat(search): include folders as navigable search results Jul 29, 2026
@sundram-bruno

Copy link
Copy Markdown
Contributor Author

@sachin-bruno handled the comment 2 . first one was already handled.

@sundram-bruno
sundram-bruno force-pushed the feat/search-folder-results branch from 440f1fb to ffbca1e Compare July 29, 2026 13:06
Index folder nodes alongside requests so a folder can be found by name and
opened from the palette. Folder rows show a folder glyph, the folder name,
its breadcrumb and a recursive request count, and rank above request results.

Search now matches on name and url only; the breadcrumb is display-only and
is shown on both row types so folders sharing a name across branches stay
distinguishable. Long chains are elided and revealed in full on hover.
The tooltip anchor is a plain span inside the row button, so it never takes
focus and its bubble is aria-hidden. On an elided chain that left keyboard and
screen-reader users with only "Hotels / … / v3", which defeats the breadcrumb's
purpose of telling same-named folders apart; the span now carries the full
chain as its accessible name.

A chain shown whole no longer mounts a tooltip at all, since the bubble would
only repeat what is already on screen.
Folder names are free text and may contain " / " themselves, so splitting the
joined chain back apart mis-segmented it and elided to the wrong folders. The
record now carries ancestorNames and the chain is only ever joined for paint.

Also covers requestCountLabel directly, and pins the tooltip's cancel-on-leave
path: the folders fixture gains a branch deep enough for a breadcrumb to elide,
which is the only case that shows a tooltip at all.
Mounts a collection built to be hostile to the search palette: chains deep
enough to elide, folders sharing a name across branches, names long enough to
fight the row for width, a folder whose own name contains the breadcrumb
separator, and folders counting zero or one request.

No automated spec reads it, so hostile cases can be added freely without
destabilising the fixtures the e2e suites depend on.
The title row had no min-width and the breadcrumb would not shrink, so the
row's minimum width was the whole chain. That pushed the body wider than the
panel: the name collapsed to an ellipsis, the results list scrolled sideways,
and the row's hover background stopped at the container edge because the
button is only ever as wide as its container.

The name now takes the width it needs and the chain yields, capped at 45% and
ellipsised, with the list refusing horizontal overflow outright.

A chain can now be cut by width as well as by depth, and a CSS ellipsis leaves
no marker in the text, so the tooltip trigger is measured on the laid-out node
instead of inferred from the segment count. The name gets the same treatment,
since a clipped name is otherwise unreadable.
Growing the name filled the row with blank space beside short names, pushing
the chain to the far edge away from the name it qualifies, and the 45% cap then
cut the chain regardless of how much room was actually going spare.

Neither part grows now, so the chain sits beside the name, and the chain
carries a far higher shrink factor so it is what yields under pressure. The
name only truncates once the chain has given up its width, and the arbitrary
cap is gone.
The name span had no test id, so the overflow spec reached for its class,
against the page-object rule that parts are found by role or test id. It has
one now, along with a page-object locator for its tooltip.

The name tooltip shipped with no coverage at all: two cases now pin it, a
narrow viewport where the name cannot fit and a wide one where it can.

TOOLTIP_DELAY_MS loses its BREADCRUMB_ prefix, since the name tooltip reads it
too.
Both "shown whole gets no tooltip" cases asserted a count of zero immediately
after hovering. The tooltip waits 500ms before opening, so the assertion was
satisfied on its first poll by the bubble simply not having appeared yet, and
would have kept passing had the trigger regressed to always-open.

Verified by stubbing the clip check to always return true: the old form still
passed, the waiting form fails.
…nfig

Trailing commas and double-quoted strings, autofixed. The branch was written
against the old per-package eslint config and predates the root one, which
adds @Stylistic and lints only the lines a PR changes.
@sundram-bruno
sundram-bruno force-pushed the feat/search-folder-results branch from ffbca1e to eff6232 Compare July 29, 2026 13:12
Defaulting a null box to zero let the width comparison pass while the
breadcrumb was rendered but unpainted: 343 > 0 holds whether or not the chain
is visible. A display:none regression shipped green.

Both boxes are now null-checked first, matching the other bounding-box reads
in this file, and a failure names which box was missing instead of reporting
0 not greater than 0.
@arpit-bruno
arpit-bruno merged commit 68c8714 into usebruno:main Jul 30, 2026
2 checks passed
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.

3 participants