Skip to content

🎨 Palette: Add keyboard shortcuts for main search input - #368

Open
mkk2026 wants to merge 1 commit into
masterfrom
palette/search-shortcut-4959276174044128335
Open

🎨 Palette: Add keyboard shortcuts for main search input#368
mkk2026 wants to merge 1 commit into
masterfrom
palette/search-shortcut-4959276174044128335

Conversation

@mkk2026

@mkk2026 mkk2026 commented Jun 7, 2026

Copy link
Copy Markdown
Owner

💡 What: Added a global keyboard shortcut (Cmd+K / Ctrl+K and /) to instantly focus the main search input on the dashboard. Also added a visual <kbd>⌘K</kbd> hint inside the input when it is empty.

🎯 Why: Power users frequently rely on keyboard shortcuts to navigate data-heavy applications. Adding a quick way to focus the search bar without reaching for the mouse significantly speeds up the workflow. The visual hint improves discoverability, and clicking the clear (X) button now intelligently refocuses the input so the user can immediately type a new query.

📸 Before/After:

  • Before: Standard search input. User must manually click to focus.
  • After: Search input displays ⌘K on the right side. Pressing / or Cmd/Ctrl+K instantly focuses the input, allowing immediate typing.

Accessibility:

  • Implemented a safe focus trap handler that explicitly checks document.activeElement. This ensures that if the user is already typing in an input or textarea, the shortcut is gracefully bypassed, preventing the accidental swallowing of standard text keystrokes (like typing a slash in a different form field).
  • Visual <kbd> element utilizes semantic HTML for screen readers and high-contrast visual queues.

Testing:

  • Unit tests and linters passed natively.
  • Playwright visual tests confirmed UI element logic and focus states.

PR created automatically by Jules for task 4959276174044128335 started by @corebrimtech

Summary by CodeRabbit

Release Notes

  • New Features

    • Added keyboard shortcuts (Ctrl/⌘+K and "/" ) to quickly focus the search input
    • Visual cue displaying keyboard shortcut hint (⌘K) in search field when empty
    • Enhanced focus management: search field automatically re-focuses after clearing queries
  • Style

    • Code formatting improvements for consistency

Co-authored-by: corebrimtech <175357468+corebrimtech@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

PR adds keyboard-driven search focus (Ctrl/⌘+K and /) with form-input-aware safety checks. Updates search input with ref, hint label, and clear-and-refocus behavior. Refactors filter pipeline and empty-state messaging, and reformats UI components for consistency.

Changes

Keyboard-driven search focus and dashboard UI updates

Layer / File(s) Summary
Keyboard shortcut infrastructure and search input focus system
.Jules/palette.md, src/app/page.tsx, src/components/ui/input.tsx
Added keyboard effect listener for Ctrl/⌘+K and / keystrokes with focus-safety checks against INPUT, TEXTAREA, and contenteditable elements. Imported useRef, created searchInputRef, and updated the Input component to destructure and forward the ref. Journal entry documents the focus-safety rule.
Search input UI enhancements
src/app/page.tsx
Wired searchInputRef to the search input, added a conditional ⌘K hint shown only when the query is empty, and updated the clear button handler to reset the search and re-focus the input.
Filter pipeline and empty-state behavior updates
src/app/page.tsx
Refactored memoized filtering (baseFilteredArticles, displayedArticles) and empty-state logic. Empty-state description now branches on hasFilters, and the "Scrape Now" button spinner rendering was restructured while preserving disabled={loading}.
UI component formatting and layout restructuring
src/app/page.tsx
Reformatted header subtitle, stats card animations and value rendering, Severity and Source select JSX, "Showing X of Y" summary, and main container props. No functional changes; layout and styling consistency improved.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • mkk2026/Security.News.Scraper#46: The PR's search input clear-and-refocus behavior directly extends the prior PR's addition of the clear button functionality.
  • mkk2026/Security.News.Scraper#5: Both PRs modify the dashboard search input and "Scrape" button, adding keyboard shortcuts and accessibility-related markup alongside UI restructuring.

Poem

🐰 A shortcut springs forth with a keystroke's dance,
/ and ⌘K give search a quick glance,
No forms interrupted by the focus we trace,
Clear queries with pride and a bounce back to place,
The dashboard now dances with keyboard finesse! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding keyboard shortcuts (Cmd/Ctrl+K and /) for the search input. It is clear, concise, and directly reflects the primary functionality added in the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch palette/search-shortcut-4959276174044128335

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/app/page.tsx

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

src/components/ui/input.tsx

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@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: b4410d2efe

ℹ️ 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 src/app/page.tsx
Comment on lines +74 to +76
if ((e.ctrlKey || e.metaKey) && e.key === "k") {
e.preventDefault();
searchInputRef.current?.focus();

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 Ignore Cmd/Ctrl+K while editing text

When focus is already inside a text field, this branch still calls preventDefault() for Ctrl/Cmd+K because the active-element guard is only applied to the / shortcut below. On macOS, Ctrl+K is a standard text-editing shortcut to delete to the end of the line, and rich text inputs commonly use Cmd/Ctrl+K for link insertion, so users typing in the search field or another input on the page lose those shortcuts. Apply the same input/textarea/contenteditable guard before swallowing this key combination.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/app/page.tsx (1)

445-451: 💤 Low value

Consider a platform-aware keyboard hint.

The hint currently displays "⌘K" (Mac-specific), which may be unfamiliar to Windows and Linux users who would press "Ctrl+K". Consider detecting the platform and showing "Ctrl+K" on non-Mac systems, or displaying both shortcuts for clarity.

Additionally, the "/" shortcut is not mentioned in the hint, which may reduce discoverability.

💡 Example platform-aware hint
{!searchQuery && (
  <div className="absolute right-4 top-1/2 transform -translate-y-1/2 pointer-events-none text-slate-400 opacity-50 flex items-center gap-1">
    <kbd className="hidden sm:inline-flex items-center gap-1 rounded border border-slate-200 bg-slate-100 px-1.5 font-mono text-[10px] font-medium text-slate-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-400">
      {typeof navigator !== 'undefined' && navigator.platform.toLowerCase().includes('mac') 
        ? '⌘K' 
        : 'Ctrl+K'}
    </kbd>
  </div>
)}

Or show both shortcuts:

<kbd ...>⌘K / Ctrl+K</kbd>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/page.tsx` around lines 445 - 451, The keyboard hint currently
hardcodes "⌘K" in the JSX block that renders when !searchQuery (the kbd inside
the conditional), which is Mac-specific and omits the "/" hint; update the
rendering logic in that conditional to be platform-aware or show both shortcuts
and include "/" for discoverability: detect platform via typeof navigator !==
'undefined' and navigator.platform (or use a helper isMac) to choose between
"⌘K" and "Ctrl+K", or render a combined label like "⌘K / Ctrl+K", and append " /
" + "/" (or a separate small kbd) to also display the "/" shortcut so non-mac
and keyboard-only users see both options; keep the same styling and replace the
inner text of the existing kbd element (in the same JSX block) rather than
adding a new element.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/page.tsx`:
- Line 82: Replace the attribute check on the active element with the DOM
property that reflects the computed editable state: instead of using
document.activeElement?.hasAttribute("contenteditable") use the element's
isContentEditable property (i.e., document.activeElement?.isContentEditable) so
elements with contenteditable="false" are treated correctly; update the
conditional in page.tsx where document.activeElement is tested to negate
isContentEditable (e.g., !document.activeElement?.isContentEditable) and keep
the optional chaining as present.
- Around line 74-77: The Cmd/Ctrl+K key handler currently always calls
e.preventDefault() and focuses searchInputRef.current, which can steal input;
update the handler (the block that checks (e.ctrlKey || e.metaKey) && e.key ===
"k") to first inspect document.activeElement and only call e.preventDefault()
and searchInputRef.current?.focus() when the active element is not an input,
textarea, or contenteditable (same pattern used by the "/" handler); reference
document.activeElement, searchInputRef, and the Ctrl/Cmd+K key-check in your
change.

---

Nitpick comments:
In `@src/app/page.tsx`:
- Around line 445-451: The keyboard hint currently hardcodes "⌘K" in the JSX
block that renders when !searchQuery (the kbd inside the conditional), which is
Mac-specific and omits the "/" hint; update the rendering logic in that
conditional to be platform-aware or show both shortcuts and include "/" for
discoverability: detect platform via typeof navigator !== 'undefined' and
navigator.platform (or use a helper isMac) to choose between "⌘K" and "Ctrl+K",
or render a combined label like "⌘K / Ctrl+K", and append " / " + "/" (or a
separate small kbd) to also display the "/" shortcut so non-mac and
keyboard-only users see both options; keep the same styling and replace the
inner text of the existing kbd element (in the same JSX block) rather than
adding a new element.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e9e3d145-61ff-408c-94ab-5c7251909c02

📥 Commits

Reviewing files that changed from the base of the PR and between 558fb10 and b4410d2.

📒 Files selected for processing (3)
  • .Jules/palette.md
  • src/app/page.tsx
  • src/components/ui/input.tsx

Comment thread src/app/page.tsx
Comment on lines +74 to +77
if ((e.ctrlKey || e.metaKey) && e.key === "k") {
e.preventDefault();
searchInputRef.current?.focus();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Cmd/Ctrl+K doesn't check activeElement before preventing default.

The Cmd/Ctrl+K handler always prevents default and focuses the search input, even when the user is typing in another input field, textarea, or contenteditable element. This violates the documented pattern in .Jules/palette.md (lines 27-29) and can steal keystrokes from modal dialogs, forms, and other interactive elements.

The "/" handler (lines 78-86) correctly checks document.activeElement before preventing default—apply the same pattern to Cmd/Ctrl+K.

🛡️ Proposed fix to add activeElement check
  const handleKeyDown = (e: KeyboardEvent) => {
-   if ((e.ctrlKey || e.metaKey) && e.key === "k") {
+   if (
+     (e.ctrlKey || e.metaKey) &&
+     e.key === "k" &&
+     document.activeElement?.tagName !== "INPUT" &&
+     document.activeElement?.tagName !== "TEXTAREA" &&
+     !document.activeElement?.isContentEditable
+   ) {
      e.preventDefault();
      searchInputRef.current?.focus();
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if ((e.ctrlKey || e.metaKey) && e.key === "k") {
e.preventDefault();
searchInputRef.current?.focus();
}
if (
(e.ctrlKey || e.metaKey) &&
e.key === "k" &&
document.activeElement?.tagName !== "INPUT" &&
document.activeElement?.tagName !== "TEXTAREA" &&
!document.activeElement?.isContentEditable
) {
e.preventDefault();
searchInputRef.current?.focus();
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/page.tsx` around lines 74 - 77, The Cmd/Ctrl+K key handler currently
always calls e.preventDefault() and focuses searchInputRef.current, which can
steal input; update the handler (the block that checks (e.ctrlKey || e.metaKey)
&& e.key === "k") to first inspect document.activeElement and only call
e.preventDefault() and searchInputRef.current?.focus() when the active element
is not an input, textarea, or contenteditable (same pattern used by the "/"
handler); reference document.activeElement, searchInputRef, and the Ctrl/Cmd+K
key-check in your change.

Source: Coding guidelines

Comment thread src/app/page.tsx
e.key === "/" &&
document.activeElement?.tagName !== "INPUT" &&
document.activeElement?.tagName !== "TEXTAREA" &&
!document.activeElement?.hasAttribute("contenteditable")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use isContentEditable instead of hasAttribute("contenteditable").

hasAttribute("contenteditable") checks only for the attribute's existence, not its value. Elements with contenteditable="false" would incorrectly pass this check and allow the shortcut to steal focus.

🔧 Proposed fix
    if (
      e.key === "/" &&
      document.activeElement?.tagName !== "INPUT" &&
      document.activeElement?.tagName !== "TEXTAREA" &&
-     !document.activeElement?.hasAttribute("contenteditable")
+     !document.activeElement?.isContentEditable
    ) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
!document.activeElement?.hasAttribute("contenteditable")
if (
e.key === "/" &&
document.activeElement?.tagName !== "INPUT" &&
document.activeElement?.tagName !== "TEXTAREA" &&
!document.activeElement?.isContentEditable
) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/page.tsx` at line 82, Replace the attribute check on the active
element with the DOM property that reflects the computed editable state: instead
of using document.activeElement?.hasAttribute("contenteditable") use the
element's isContentEditable property (i.e.,
document.activeElement?.isContentEditable) so elements with
contenteditable="false" are treated correctly; update the conditional in
page.tsx where document.activeElement is tested to negate isContentEditable
(e.g., !document.activeElement?.isContentEditable) and keep the optional
chaining as present.

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.

1 participant