Skip to content

fix(cmdk): clean up search modal input handling#3147

Open
waleedlatif1 wants to merge 2 commits intostagingfrom
fix/cmdk
Open

fix(cmdk): clean up search modal input handling#3147
waleedlatif1 wants to merge 2 commits intostagingfrom
fix/cmdk

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Replace nativeInputValueSetter DOM hack with controlled input value prop
  • Replace requestAnimationFrame + querySelector scroll reset with a ref
  • Replace global document keydown listener for Escape with scoped onKeyDown
  • Remove imperceptible backdrop-blur-[0.75px] from overlay

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Feb 5, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Feb 6, 2026 2:01am

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 5, 2026

Greptile Overview

Greptile Summary

This PR refactors the workspace sidebar SearchModal (cmdk) to remove a native input value setter hack, replace a querySelector+RAF scroll reset with a ref, and scope Escape-to-close to a component onKeyDown handler.

Main issue to address before merge: the new Escape handling is attached to a non-focusable dialog wrapper div, which won’t reliably receive key events. The prior implementation listened on document while open, so Escape worked regardless of focus. As-is, keyboard users can end up unable to close the modal with Escape depending on where focus lives inside cmdk.

Confidence Score: 3/5

  • This PR is close to safe to merge but has a user-facing keyboard regression to fix.
  • Changes are localized to a single component and mostly simplify DOM interactions, but the Escape-to-close behavior likely regresses because the key handler is attached to a non-focusable wrapper that may not receive events when cmdk input is focused.
  • apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx Refactors cmdk SearchModal input handling to be controlled, uses refs for list scroll reset, and scopes Escape handling to onKeyDown; Escape handling likely no longer triggers because the dialog wrapper isn’t reliably receiving key events.

Sequence Diagram

sequenceDiagram
  participant U as User
  participant SM as SearchModal
  participant I as Input(ref)
  participant L as List(ref)
  U->>SM: Open modal
  SM->>I: Render controlled value
  U->>I: Type query
  I-->>SM: onValueChange(query)
  SM->>SM: setSearchQuery(query)
  SM->>L: scrollTop = 0 via ref
  U->>SM: Press Escape
  SM-->>SM: onKeyDown(Escape)
  SM-->>U: Close modal
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 5, 2026

Additional Comments (1)

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx
Escape key no longer works

onKeyDown is attached to the outer <div role="dialog">, but that element isn’t focusable and won’t reliably receive keyboard events. Previously, Escape was handled via a document keydown listener when open was true, so Escape would close the modal regardless of focus. With the current change, pressing Escape while focus is inside Command.Input/cmdk internals may not bubble to this div, leaving the modal stuck open for keyboard users. Consider handling Escape on the focused element (e.g., Command root / Command.Input) or make the dialog focusable and ensure it’s focused on open.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx
Line: 254:268

Comment:
**Escape key no longer works**

`onKeyDown` is attached to the outer `<div role="dialog">`, but that element isn’t focusable and won’t reliably receive keyboard events. Previously, Escape was handled via a `document` keydown listener when `open` was true, so Escape would close the modal regardless of focus. With the current change, pressing Escape while focus is inside `Command.Input`/cmdk internals may not bubble to this `div`, leaving the modal stuck open for keyboard users. Consider handling Escape on the focused element (e.g., `Command` root / `Command.Input`) or make the dialog focusable and ensure it’s focused on open.


How can I resolve this? If you propose a fix, please make it concise.

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

document.addEventListener('keydown', handleKeyDown)
return () => document.removeEventListener('keydown', handleKeyDown)
}, [open, onOpenChange])
}, [])
Copy link

Choose a reason for hiding this comment

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

Synchronous scroll reset occurs before DOM update

Low Severity

In handleSearchChange, listRef.current.scrollTop = 0 runs synchronously before React commits the re-render triggered by setSearch(value). The old code intentionally used requestAnimationFrame to delay the scroll reset until after the DOM updated with filtered results. Because cmdk internally calls scrollIntoView on the newly selected item after re-rendering, the synchronous reset gets overridden, making it effectively a no-op in cases where the list needs scrolling back to the top.

Fix in Cursor Fix in Web

e.preventDefault()
onOpenChange(false)
}
}}
Copy link

Choose a reason for hiding this comment

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

Duplicate Escape key handlers cause redundant calls

Low Severity

The onKeyDown Escape handler on Command.Input is redundant with the identical handler on the parent dialog div. Since the input is a child of the div, the keydown event bubbles up naturally, so the parent handler already covers all Escape presses from within the dialog. Having both means onOpenChange(false) gets called twice per Escape press when the input is focused.

Additional Locations (1)

Fix in Cursor Fix in Web

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