Skip to content

ENG-1738: Render advanced search results as sidebar block#1071

Open
trangdoan982 wants to merge 15 commits into
mainfrom
eng-1738-platform-roam
Open

ENG-1738: Render advanced search results as sidebar block#1071
trangdoan982 wants to merge 15 commits into
mainfrom
eng-1738-platform-roam

Conversation

@trangdoan982

@trangdoan982 trangdoan982 commented May 22, 2026

Copy link
Copy Markdown
Member

https://www.loom.com/share/08c356bb7cd841868b34bcea39cbab3b

Summary

  • wire the advanced search footer action and Option + Enter shortcut to open a dedicated sidebar results block instead of opening individual pages
  • create a single summary block (Advanced search results: \"{query}\") with child wikilink rows for each currently displayed result
  • simplify the search dialog layout by removing preview-pane rendering and keeping results-focused list behavior

Test plan

  • Open DG: Open Node Search, search for a query, press Option + Enter, and confirm a single right-sidebar block opens
  • Verify the new sidebar block title includes the query and child blocks are wikilinks for all displayed results
  • Verify Open search sidebar in footer triggers the same behavior as Option + Enter

Made with Cursor

@linear-code

linear-code Bot commented May 22, 2026

Copy link
Copy Markdown

ENG-1738

@supabase

supabase Bot commented May 22, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@trangdoan982 trangdoan982 requested a review from mdroidian May 24, 2026 03:35
@mdroidian

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d392a6af2f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/roam/src/components/AdvancedNodeSearchDialog/AdvancedSearchDialog.tsx Outdated

@mdroidian mdroidian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite different than the functionality I was expecting.

On Apr 23 and May 7th, we discussed replicating the same functionality as the Roam native search which is to render the search as a component in the sidebar. But it looks like this did not make it into the scope doc/ticket. Upon looking at the scope doc/ticket, I can see where the confusion could have arose: "The active result opens in the main panel or side bar accordingly". This is quite ambiguous.

I believe this will be quite confusing to users based on the wording and it will leave them with multiple backlinks to clean up. I don't see the benefit of creating a page/blocks in this case as search is generally ephemeral.

That being said, there is a similar pattern in query builder called "Share To" where a user can insert search results as references to a given page, which may be something users request.

But for this use case let's change it to a rendered component or bring it up in the next Roam meeting / All Hands for clarification.

@trangdoan982 trangdoan982 force-pushed the eng-1738-platform-roam branch from d392a6a to 0f66bc2 Compare May 28, 2026 19:49
@graphite-app

graphite-app Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

PR size/scope check

This PR is over our review-size guideline.

  • Recommended: ~200 lines changed
  • Acceptable limit: up to 400 lines when well-scoped/self-contained
  • Preferred file count: fewer than 5 files

Please split this into smaller PRs unless there is a clear reason the changes need to land together.

If keeping it as one PR, please add a brief justification covering:

  • What single problem this PR solves
  • Why the files/changes are coupled

@trangdoan982

Copy link
Copy Markdown
Member Author

@trangdoan982 trangdoan982 requested a review from mdroidian May 31, 2026 04:24
@mdroidian

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0ca5ed69b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/roam/src/utils/openDgSearchInSidebar.tsx Outdated
Comment thread apps/roam/src/components/AdvancedNodeSearchDialog/AdvancedSearchSidebarPanel.tsx Outdated

@mdroidian mdroidian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The biggest blocking change is the issue we discussed in our 1:1 of the sidebar hijacking the last window instead of creating it's own window to use/persist. We mentioned that bringing this (expected way to load custom windows in sidebar) up in Roam dev slack would be a good idea and suggesting a custom sidebar window type.

Comment thread apps/roam/src/components/AdvancedNodeSearchDialog/AdvancedSearchSidebarPanel.tsx Outdated
Comment thread apps/roam/src/components/AdvancedNodeSearchDialog/AdvancedSearchSidebarPanel.tsx Outdated
Comment thread apps/roam/src/components/AdvancedNodeSearchDialog/AdvancedSearchSidebarPanel.tsx Outdated
Comment thread apps/roam/src/components/AdvancedNodeSearchDialog/AdvancedSearchSidebarPanel.tsx Outdated
Comment thread apps/roam/src/components/AdvancedNodeSearchDialog/AdvancedSearchSidebarPanel.tsx Outdated
Comment on lines +320 to +346
useEffect(() => {
if (!debouncedSearchTerm) {
setResults([]);
return;
}

if (isIndexLoading || indexError || !miniSearchRef.current) {
if (!isDockedQuery) setResults([]);
return;
}

const scoredHits = searchIndexedNodes({
miniSearch: miniSearchRef.current,
allResults: allResultsRef.current,
searchTerm: debouncedSearchTerm,
typeFilter: selectedNodeTypeIds.length ? selectedNodeTypeIds : undefined,
});

setResults(sortSearchResults({ hits: scoredHits, sort }));
}, [
debouncedSearchTerm,
indexError,
isDockedQuery,
isIndexLoading,
selectedNodeTypeIds,
sort,
]);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: derive search results during render instead of syncing with useEffect

Both AdvancedSearchDialog and AdvancedSearchSidebarPanel use an effect to run searchIndexedNodessortSearchResultssetResults whenever the debounced query, sort, filters, or index readiness change. That pattern causes an extra render on every search update (render → effect → setState → render).

Since search is synchronous, debounced, and capped at 50 results, this looks like derived data rather than a side effect. Consider replacing results state + the search useEffect with a useMemo (or inline derivation):

const results = useMemo(() => {
  if (!debouncedSearchTerm) return [];
  if (isIndexLoading || indexError || !miniSearchRef.current) {
    // Sidebar only: keep docked placeholder while index loads
    return isDockedQuery ? dockedResults : [];
  }
  const scoredHits = searchIndexedNodes({ /* ... */ });
  return sortSearchResults({ hits: scoredHits, sort });
}, [debouncedSearchTerm, isIndexLoading, indexError, selectedNodeTypeIds, sort, /* sidebar: isDockedQuery, dockedResults */]);

Benefits

  • One render per input change instead of two
  • Search logic lives in one place; no effect/state drift
  • Same behavior, simpler mental model (“results = f(query, index, filters, sort)”)

Keep as useEffect

  • Async index build (buildSearchIndex) — that’s a real side effect
  • Debounce timer — still belongs in an effect (or useDebouncedValue if you add one)

Optional follow-up: store the built index in state (searchIndex) instead of refs so the memo depends on real reactive data rather than isIndexLoading as a proxy for “refs are populated.” Could also extract a shared useAdvancedNodeSearchResults hook used by both dialog and sidebar.

Comment thread apps/roam/src/utils/openDgSearchInSidebar.tsx Outdated
trangdoan982 and others added 10 commits June 10, 2026 17:05
Switch advanced search sidebar behavior to create a single summary block with wikilink children, and wire Option+Enter/footer action to open that block in the right sidebar. This aligns the flow with Roam's native sidebar result rendering while keeping the search dialog focused on result-list interaction.

Co-authored-by: Cursor <cursoragent@cursor.com>
@trangdoan982 trangdoan982 force-pushed the eng-1738-platform-roam branch from 0ca5ed6 to d241625 Compare June 10, 2026 22:07
@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
discourse-graph Skipped Skipped Jun 10, 2026 10:59pm

Request Review

Comment on lines +305 to +324
useEffect(() => {
if (!debouncedSearchTerm) return;

onPersistState({
query: debouncedSearchTerm,
results,
selectedNodeTypeIds,
sort,
windowId,
dgSearchId,
});
}, [
debouncedSearchTerm,
dgSearchId,
onPersistState,
results,
selectedNodeTypeIds,
sort,
windowId,
]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

State persistence bug: When debouncedSearchTerm becomes empty (user clears search), the useEffect guard if (!debouncedSearchTerm) return; prevents state from being persisted. This leaves stale query/results in localStorage. If the sidebar window is closed and reopened, it will display outdated search results.

useEffect(() => {
  // Remove the guard or persist empty state explicitly
  onPersistState({
    query: debouncedSearchTerm,
    results,
    selectedNodeTypeIds,
    sort,
    windowId,
    dgSearchId,
  });
}, [
  debouncedSearchTerm,
  dgSearchId,
  onPersistState,
  results,
  selectedNodeTypeIds,
  sort,
  windowId,
]);
Suggested change
useEffect(() => {
if (!debouncedSearchTerm) return;
onPersistState({
query: debouncedSearchTerm,
results,
selectedNodeTypeIds,
sort,
windowId,
dgSearchId,
});
}, [
debouncedSearchTerm,
dgSearchId,
onPersistState,
results,
selectedNodeTypeIds,
sort,
windowId,
]);
useEffect(() => {
onPersistState({
query: debouncedSearchTerm,
results,
selectedNodeTypeIds,
sort,
windowId,
dgSearchId,
});
}, [
debouncedSearchTerm,
dgSearchId,
onPersistState,
results,
selectedNodeTypeIds,
sort,
windowId,
]);

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

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.

2 participants