Skip to content

ENG-2113 Add footer action bar with open in new tab and split - #1292

Open
trangdoan982 wants to merge 6 commits into
eng-2109-create-node-search-modal-with-ranked-results-and-previewfrom
eng-2113-add-footer-action-bar-with-open-in-active-pane-and-split
Open

ENG-2113 Add footer action bar with open in new tab and split#1292
trangdoan982 wants to merge 6 commits into
eng-2109-create-node-search-modal-with-ranked-results-and-previewfrom
eng-2113-add-footer-action-bar-with-open-in-active-pane-and-split

Conversation

@trangdoan982

@trangdoan982 trangdoan982 commented Aug 12, 2026

Copy link
Copy Markdown
Member

https://www.loom.com/share/85492db69f9f4c0d92f09d3234d64eb7

Scope check

  • Ran $scope-check against ENG-2113 and the final diff.
  • Scope beyond Done When: two deliberate deviations, both cosmetic-to-small.
    1. Enter opens a new tab in the main panel, not the active pane. Done When only requires that "both actions open the correct note and close the modal", so this stays inside the acceptance boundary — but it contradicts the ticket's Solution, which specified app.workspace.getLeaf(false), and the ticket title. Replacing the note the user was already reading loses their place, which is the opposite of what a lookup surface should do. The footer label reads "open in new tab" to match.
    2. An esc close hint. A third, non-clickable footer item for Escape, which Obsidian's modal scope already handles. Included so the footer matches Roam's AdvancedSearchFooter and the native quick switcher, both of which show one.
  • Required now: (1) yes — it is the behaviour actually wanted from the surface, and shipping getLeaf(false) first would mean changing it immediately. (2) No, easily dropped.
  • Anyone affected or consulted: requested directly by @Trang-Doan during review of the working build.
  • Decision: not recorded in Linear. The ticket's Solution and title should be updated to say "new tab" rather than "active pane" — flagging rather than editing the ticket myself.

Stacked on #1285 (ENG-2109) — review that first. Base is its branch, not main.

What this does

F8. Enter opens the active result in a new tab in the main panel, Shift+Enter opens it in a split, both close the modal, and both are clickable in a new footer.

Mod+Enter and Alt+Enter deliberately fall through untouched so ENG-2114's insert-at-cursor can claim Mod+Enter, the same combo Roam uses. Shift+Enter has no native conflict: it means "create new file" only inside Obsidian's own quick switcher, which this modal does not offer.

The Enter branch lives in the existing wrapper onKeyDown — ENG-2109 moved that handler off the input specifically so result actions would have one place to live. It also guards isComposing, so committing an IME candidate never opens a file.

Both open helpers (openFileInNewTab, openFileInNewLeaf) already existed and are reused unchanged, so no file outside the search feature is modified.

Avoiding ENG-2000

Roam's footer hardcodes Blueprint's macOS glyph icons per action (keyIcons={["key-option", "key-enter"]}), so Windows users see ⌘/⌥ while the handler actually accepts Ctrl. Rather than port that shape, every hint here goes through one keyboardHints.ts map keyed on Platform.isMacOS. No call site can name a platform-specific symbol.

formatHintKeys takes isMacOS as a parameter so the Windows/Linux branch is verifiable without that platform:

macOS       ["↵","⇧ ↵","⌘ ↵","⌥ ↵","esc"]
win/linux   ["Enter","Shift Enter","Ctrl Enter","Alt Enter","Esc"]

Native styling

  • The footer reuses Obsidian's own prompt-instructions / prompt-instruction / prompt-instruction-command classes — what SuggestModal.setInstructions() emits.
  • Matching closely with Roam design

Beyond that it only needed flex-shrink: 0 (the .modal-content column is fixed-height with overflow: hidden) and a reset for Obsidian's global button chrome.

🤖 Generated with Claude Code

trangdoan982 and others added 2 commits August 12, 2026 14:41
Obsidian renders modifiers as glyphs on macOS and as words on Windows and
Linux. Roam's search footer hardcoded the macOS glyphs at each call site and
showed the wrong hint on Windows (ENG-2000); routing every hint through one
map is what keeps that from repeating.

`formatHintKeys` takes `isMacOS` so the non-mac branch can be exercised
without that platform.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Enter opens the active result in the current pane, Shift+Enter in a split, and
both close the modal. Mod+Enter and Alt+Enter deliberately fall through, so
the insert action (ENG-2114) can claim Mod+Enter as it does in Roam.

The footer reuses Obsidian's own `prompt-instruction` markup, the classes
`SuggestModal.setInstructions()` emits, so it matches the native quick
switcher. This modal extends plain `Modal`, so that API is unavailable. Its
actions are left-aligned rather than centred because they sit under a
full-width result list.

The Enter branch lives in the existing wrapper `onKeyDown`, which ENG-2109
moved off the input so result actions would have one place to live.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Aug 12, 2026

Copy link
Copy Markdown

ENG-2113

@supabase

supabase Bot commented Aug 12, 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 ↗︎.

@vercel

vercel Bot commented Aug 12, 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 Aug 12, 2026 9:08pm

Request Review

@devin-ai-integration devin-ai-integration Bot left a comment

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.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

Replacing the page the user was already reading loses their place, which is the
opposite of what a lookup surface should do. `getLeaf("tab")` adds a tab to the
main panel instead, so the previous note stays open behind it.

This reuses the existing `openFileInNewTab`, so the `openFileInActivePane`
helper added earlier in this branch is no longer needed. The label now reads
"open in new tab" to match.

Diverges from the ticket's stated Solution, which specified `getLeaf(false)`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@trangdoan982 trangdoan982 changed the title ENG-2113 Add footer action bar with open in active pane and split ENG-2113 Add footer action bar with open in new tab and split Aug 12, 2026
trangdoan982 and others added 2 commits August 12, 2026 16:43
Obsidian's `prompt-instruction-command` is bold with no border, which made the
lone `esc` hint read as emphasis rather than as a key. Roam's search footer
draws every key as a bordered cap instead, so `esc` sits with the rest of the
set.

Keeps the `prompt-instructions` container for its native type and spacing, and
takes the cap's border, radius, and background from Obsidian's CSS variables so
it still follows the active theme.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Obsidian renders `aria-label` as a hover tooltip, so labelling the listbox meant
a tooltip covered the results as soon as the pointer entered the list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The close hint was the only footer item that ignored a click, which read as
broken next to two working actions. It now goes through the same `FooterAction`
as the others and calls the modal's own close.

The badge carried both `title` and `aria-label` with the same text, so hovering
one stacked a native tooltip on top of Obsidian's. Keeping `aria-label`, since
Obsidian's is the themed one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@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: 005b5a2036

ℹ️ 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 on lines 433 to +434
event.preventDefault();
moveActiveIndex(event.key === "ArrowDown" ? 1 : -1);
openActiveResult(event.shiftKey ? openFileInNewLeaf : openFileInNewTab);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Let focused footer buttons handle Enter

When a keyboard user Tabs into a footer button, its bubbling Enter keydown is still intercepted here, preventDefault() suppresses the button's native click, and the selection shortcut runs instead. Consequently, Enter on the close button opens the active result in a new tab, while Enter on the split button also opens a new tab; ignore Enter events originating from footer buttons or scope this shortcut to the search input.

Useful? React with 👍 / 👎.

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.

onClick: () => void;
};

// Roam's footer renders each key as a bordered cap rather than bold text, which

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.

I'm not sure what this comment is supposed to be informing me. Was there a different choice made in Obsidian as opposed to Roam that this comment is trying to infer about?

className="prompt-instruction dg-search-footer-action"
disabled={disabled}
onClick={onClick}
// Same reason as the result rows: keep focus in the query input so arrow-key

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.

What is the same reason?

Comment on lines 433 to +434
event.preventDefault();
moveActiveIndex(event.key === "ArrowDown" ? 1 : -1);
openActiveResult(event.shiftKey ? openFileInNewLeaf : openFileInNewTab);

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 footer sits under a full-width result list, so the actions line up with
its left edge instead. `flex-shrink` keeps the footer from collapsing inside
the fixed-height flex column above it. */
.dg-node-search-modal .dg-search-footer {

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.

prefer tailwind where we can

export type HintKey = "Mod" | "Alt" | "Shift" | "Enter" | "Escape";

// Obsidian shows glyphs on macOS and spelled-out words everywhere else, so the
// same shortcut has to render two ways. Roam's search footer hardcoded the macOS

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.

Some unnecessary comments here

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