Skip to content

🎨 Palette: Add Cmd+K keyboard shortcut to search - #154

Open
mkk2026 wants to merge 1 commit into
masterfrom
palette-keyboard-shortcut-search-6607717908807149004
Open

🎨 Palette: Add Cmd+K keyboard shortcut to search#154
mkk2026 wants to merge 1 commit into
masterfrom
palette-keyboard-shortcut-search-6607717908807149004

Conversation

@mkk2026

@mkk2026 mkk2026 commented Mar 24, 2026

Copy link
Copy Markdown
Owner

💡 What: Added a global keyboard shortcut (Cmd+K / Ctrl+K) to quickly focus the main search bar, complete with a visual hint inside the input field.

🎯 Why: Power users expect a quick way to search without reaching for the mouse. Adding a keyboard shortcut significantly speeds up navigation and filtering, improving the overall workflow.

📸 Before/After:
Before: The search input was only focusable via mouse click or manual tabbing.
After: The search input can be focused instantly with Cmd+K (Mac) or Ctrl+K (Windows/Linux). A visual hint (e.g., ⌘K) is displayed when the input is empty to teach users the shortcut.

♿ Accessibility:

  • Added aria-keyshortcuts to the Input element so screen readers can announce the available shortcut.
  • The visual hint uses pointer-events-none so it doesn't interfere with clicking the input field beneath it.
  • When a user clears the search using the "X" button, focus is now intentionally returned to the input field, improving the keyboard/screen reader workflow.

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

Summary by CodeRabbit

  • New Features
    • Added keyboard shortcut (Cmd+K on Mac, Ctrl+K on other platforms) to quickly focus the search input
    • Visual keyboard shortcut hints now display in the search interface when the search field is empty
    • Search input automatically refocuses after clearing previous searches

This commit implements a global keyboard shortcut (Cmd+K on Mac, Ctrl+K on Windows/Linux) to quickly focus the main search input field. It also displays a dynamic, OS-specific hint (`⌘K` or `Ctrl K`) within the search input when empty, improving discoverability.

Changes:
- Added `keydown` event listener in `src/app/page.tsx`
- Used `isMounted` state pattern to prevent SSR hydration mismatches for the OS-specific hint and `aria-keyshortcuts`
- Added dynamic `aria-keyshortcuts` attribute to the search input
- Styled the shortcut hint with `pointer-events-none` so it doesn't block clicks to the input
- Updated the "Clear search" button to return focus to the input after clearing
- Added learning regarding `aria-keyshortcuts`, `isMounted` and `pointer-events-none` to `.Jules/palette.md`

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.

@vercel

vercel Bot commented Mar 24, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
security-news-scraper Ready Ready Preview, Comment Mar 24, 2026 0:23am

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

A journal entry documents requirements for keyboard shortcut implementation, while the search UI adds global Ctrl+K/Cmd+K shortcut support with OS-specific display hints, dynamic aria-keyshortcuts attributes, and SSR-safe rendering guarded by an isMounted flag.

Changes

Cohort / File(s) Summary
Documentation
.Jules/palette.md
Added journal entry outlining implementation requirements for search keyboard shortcuts, including dynamic aria-keyshortcuts handling, SSR hydration safeguards with isMounted, and pointer-events management for overlay hints.
Keyboard Shortcut Feature
src/app/page.tsx
Implemented global keyboard shortcut (Ctrl+K/Cmd+K) to focus search input. Added searchInputRef, isMounted, and isMac state properties. Dynamic aria-keyshortcuts attribute set based on detected OS. Visual <kbd> hint renders conditionally when input is empty and mounted. Increased search input padding and refactored clear button to refocus input after clearing query.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 A shortcut to search, quick as a bound,
Cmd-K or Ctrl-K on any ground,
The input now listens, both sleek and aware,
With hints that respect where each system might care! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main feature: adding a Cmd+K keyboard shortcut to search. It is clear, specific, and accurately represents the primary change in the changeset.

✏️ 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-keyboard-shortcut-search-6607717908807149004

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.

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.Jules/palette.md:
- Around line 27-29: The journal entry header "## 2026-10-27 - Keyboard
Shortcuts for Search" is dated in the future; update that header to today's date
(e.g., "## 2026-03-24 - Keyboard Shortcuts for Search") so the timeline stays
accurate, locating the entry by the exact header text "Keyboard Shortcuts for
Search" and replacing only the date portion while keeping the rest of the
paragraph unchanged.

In `@src/app/page.tsx`:
- Line 365: The Input component does not forward refs so searchInputRef passed
from page.tsx never reaches the underlying <input>, breaking focus for the
Cmd/Ctrl+K handler and after clearing search; fix by converting the Input
component in src/components/ui/input.tsx to use React.forwardRef, accept a ref
parameter typed as HTMLInputElement (e.g., forwardRef<HTMLInputElement,
InputProps>), pass that ref to the actual <input> element inside the component,
and adjust the InputProps to extend React.InputHTMLAttributes<HTMLInputElement>
(or ComponentPropsWithoutRef<'input'>) so all native input props continue to
work. Ensure the exported Input remains the same name so existing usages (e.g.,
the ref={searchInputRef} in page.tsx) pick up the forwarded ref.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 26c66790-f113-48ca-8541-9bc6fa8f8d3a

📥 Commits

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

⛔ Files ignored due to path filters (3)
  • prisma/dev.db is excluded by !**/*.db
  • verification_cleared.png is excluded by !**/*.png
  • verification_with_text.png is excluded by !**/*.png
📒 Files selected for processing (2)
  • .Jules/palette.md
  • src/app/page.tsx

Comment thread .Jules/palette.md
Comment on lines +27 to +29
## 2026-10-27 - Keyboard Shortcuts for Search
**Learning:** Interactive elements with keyboard shortcuts must dynamically set the `aria-keyshortcuts` attribute based on the OS modifier (e.g., `Meta+K` vs `Control+K` using `navigator.platform`) instead of being hardcoded, to correctly announce the shortcut to assistive technology. Moreover, conditionally rendering OS-specific hints requires delaying rendering using an `isMounted` state pattern to avoid SSR hydration mismatches, and visual overlays should use `pointer-events-none` to allow clicking through the hint to focus the underlying input.
**Action:** Always dynamically detect OS with an `isMounted` guard for shortcut keys, use `aria-keyshortcuts`, and add `pointer-events-none` to any overlay hints inside input wrappers.

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 | 🟡 Minor

Future-dated journal entry can confuse change chronology.

The new section is dated 2026-10-27, which is in the future (current date is March 24, 2026). Please use the actual entry date to keep the journal timeline reliable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.Jules/palette.md around lines 27 - 29, The journal entry header "##
2026-10-27 - Keyboard Shortcuts for Search" is dated in the future; update that
header to today's date (e.g., "## 2026-03-24 - Keyboard Shortcuts for Search")
so the timeline stays accurate, locating the entry by the exact header text
"Keyboard Shortcuts for Search" and replacing only the date portion while
keeping the rest of the paragraph unchanged.

Comment thread src/app/page.tsx
<div className="relative group">
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-slate-400 group-focus-within:text-primary transition-colors pointer-events-none" />
<Input
ref={searchInputRef}

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether Input forwards refs and where ref is consumed.
set -euo pipefail

echo "== Input component definition (expect forwardRef for proper ref wiring) =="
fd 'input\.tsx$' | xargs -I{} rg -n -C3 'forwardRef|function Input|const Input' {}

echo
echo "== Input usages with ref prop (expect these to rely on forwarded ref) =="
rg -nP --type=tsx -C2 '<Input[^>]*\bref='

Repository: mkk2026/Security.News.Scraper

Length of output: 434


🏁 Script executed:

#!/bin/bash
# Verify Input component and ref usage more carefully
set -euo pipefail

echo "=== Current Input component (full file) ==="
find . -path "*/components/ui/input.tsx" -type f | head -1 | xargs cat

echo
echo "=== Ref usage in page.tsx around line 365 ==="
sed -n '360,370p' src/app/page.tsx

echo
echo "=== searchInputRef definition in page.tsx ==="
rg -n 'searchInputRef' src/app/page.tsx | head -20

echo
echo "=== Line 113 context in page.tsx ==="
sed -n '108,118p' src/app/page.tsx

echo
echo "=== Line 384 context in page.tsx ==="
sed -n '379,389p' src/app/page.tsx

Repository: mkk2026/Security.News.Scraper

Length of output: 3300


ref won't work because Input does not forward refs.

The Input component in src/components/ui/input.tsx is defined as a plain function component without React.forwardRef. When ref={searchInputRef} is passed at line 365, the ref never connects to the underlying <input> element, leaving searchInputRef.current as null. This breaks focus on Cmd/Ctrl+K (line 113) and after clearing search (line 384).

🔧 Proposed fix (in src/components/ui/input.tsx)
 import * as React from "react"
 
 import { cn } from "@/lib/utils"
 
-function Input({ className, type, ...props }: React.ComponentProps<"input">) {
-  return (
-    <input
-      type={type}
-      data-slot="input"
-      className={cn(
-        "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
-        "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
-        "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
-        className
-      )}
-      {...props}
-    />
-  )
-}
+const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
+  ({ className, type, ...props }, ref) => {
+    return (
+      <input
+        ref={ref}
+        type={type}
+        data-slot="input"
+        className={cn(
+          "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
+          "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
+          "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
+          className
+        )}
+        {...props}
+      />
+    )
+  }
+)
+Input.displayName = "Input"
 
 export { Input }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/page.tsx` at line 365, The Input component does not forward refs so
searchInputRef passed from page.tsx never reaches the underlying <input>,
breaking focus for the Cmd/Ctrl+K handler and after clearing search; fix by
converting the Input component in src/components/ui/input.tsx to use
React.forwardRef, accept a ref parameter typed as HTMLInputElement (e.g.,
forwardRef<HTMLInputElement, InputProps>), pass that ref to the actual <input>
element inside the component, and adjust the InputProps to extend
React.InputHTMLAttributes<HTMLInputElement> (or
ComponentPropsWithoutRef<'input'>) so all native input props continue to work.
Ensure the exported Input remains the same name so existing usages (e.g., the
ref={searchInputRef} in page.tsx) pick up the forwarded ref.

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