Skip to content

Conversation

@HarshMN2345
Copy link
Member

@HarshMN2345 HarshMN2345 commented Nov 11, 2025

What does this PR do?

(Provide a description of what this PR does.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

Summary by CodeRabbit

  • Bug Fixes
    • Global keyboard shortcuts now ignore a wider range of input-like elements (inputs, textareas, contenteditable areas and specific ARIA roles), reducing accidental shortcut activation while typing.
  • New Features
    • Form select controls now include a marker so they are excluded from global command handling, preventing unintended shortcut triggers.

@appwrite
Copy link

appwrite bot commented Nov 11, 2025

Console (appwrite/console)

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Git integration provides automatic deployments with optional PR comments

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

The PR removes a local input-detection helper in commandCenter.svelte and imports isTargetInputLike from src/lib/commandCenter/commands.ts. isTargetInputLike checks an event target and its ancestors for input-like elements (input, textarea, select), contenteditable, specific ARIA input roles, and a data-command-center-ignore marker. The command-center keydown handler now calls isTargetInputLike(event.target) to decide whether to skip handling. Input.Select was annotated with data-command-center-ignore.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review focus areas:
    • src/lib/commandCenter/commands.ts: selector and ARIA role coverage in isTargetInputLike
    • src/lib/commandCenter/commandCenter.svelte: correct use of isTargetInputLike(event.target) and preserved wizard-state checks
    • src/lib/elements/forms/inputSelect.svelte: presence and propagation of data-command-center-ignore
    • Ensure behavior matches previous input-detection semantics for nested/contenteditable cases

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 accurately describes the main change: preventing command center shortcuts from triggering while typing in select inputs.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-SER-493-prevent-global-shortcuts-when-typing-in-select

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc69034 and ac02658.

📒 Files selected for processing (2)
  • src/lib/commandCenter/commandCenter.svelte (2 hunks)
  • src/lib/commandCenter/commands.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/commandCenter/commands.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2567
File: src/lib/elements/forms/inputSelect.svelte:26-36
Timestamp: 2025-11-06T06:47:24.645Z
Learning: In the appwrite.io/pink-svelte library, the Input.Select component internally uses an `input` element (not a `select` element) that triggers the `on:input` event, so event.target should be cast as HTMLInputElement in event handlers.
📚 Learning: 2025-11-06T06:47:24.645Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2567
File: src/lib/elements/forms/inputSelect.svelte:26-36
Timestamp: 2025-11-06T06:47:24.645Z
Learning: In the appwrite.io/pink-svelte library, the Input.Select component internally uses an `input` element (not a `select` element) that triggers the `on:input` event, so event.target should be cast as HTMLInputElement in event handlers.

Applied to files:

  • src/lib/commandCenter/commandCenter.svelte
🔇 Additional comments (2)
src/lib/commandCenter/commandCenter.svelte (2)

33-38: LGTM: Clean refactoring to shared utility.

Moving input detection to a shared utility function improves maintainability and reusability.


105-105: No issues found — implementation is correct.

The isTargetInputLike function properly handles all requirements:

  • Type narrowing: Correctly checks instanceof HTMLElement before accessing DOM APIs
  • Input-like detection: Covers input, textarea, select, and contenteditable elements
  • ARIA roles: Includes combobox, textbox, and searchbox roles (handles pink-svelte's Input.Select via [role="combobox"])
  • Ancestor traversal: Uses .closest() to traverse up the DOM tree
  • Escape hatch: Supports [data-command-center-ignore] attribute for custom exclusions

The implementation properly prevents keyboard shortcuts from triggering while users interact with form inputs and selects.


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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/lib/commandCenter/commands.ts (2)

106-125: Consider simplifying by relying on closest alone.

The function performs redundant checks: lines 110-114 test the element directly, but closest (lines 116-122) already checks the element itself before traversing ancestors. The entire function could be streamlined to just the closest call with appropriate selectors.

Additionally, line 107's cast (element as Element) ?? null is misleading—the cast executes regardless of whether element is null, making the ?? null ineffective.

Consider this simplified approach:

 function isTargetInputLike(element: EventTarget | null) {
-    const el = (element as Element) ?? null;
-    if (!(el instanceof HTMLElement)) return false;
-
-    if (INPUT_TAGS.includes(el.tagName)) return true;
-    if (el.isContentEditable) return true;
-
-    const role = el.getAttribute('role');
-    if (role && INPUT_ROLES.includes(role.toLowerCase())) return true;
-
-    if (
-        el.closest(
-            'input,textarea,select,[contenteditable],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
-        )
-    ) {
-        return true;
-    }
-
-    return false;
+    if (!(element instanceof HTMLElement)) return false;
+    
+    return !!element.closest(
+        'input,textarea,select,[contenteditable],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
+    );
 }

116-122: CSS selector case-sensitivity is theoretically valid but not an issue in practice.

Verification found zero uppercase or mixed-case role attributes (e.g., role="Combobox", role="TextBox") anywhere in the codebase. All role attributes are lowercase. The code at line 114 already handles case-insensitive role matching via .toLowerCase() for direct attribute checks, and all closest() selectors safely use lowercase values matching the actual attributes present.

The suggestion to add the case-insensitive flag i to the CSS selectors is a valid defensive measure for future-proofing, but it addresses a theoretical concern rather than an actual bug. The current implementation works correctly.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73552e5 and a030a29.

📒 Files selected for processing (3)
  • src/lib/commandCenter/commandCenter.svelte (2 hunks)
  • src/lib/commandCenter/commands.ts (2 hunks)
  • src/lib/elements/forms/inputSelect.svelte (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2567
File: src/lib/elements/forms/inputSelect.svelte:26-36
Timestamp: 2025-11-06T06:47:24.645Z
Learning: In the appwrite.io/pink-svelte library, the Input.Select component internally uses an `input` element (not a `select` element) that triggers the `on:input` event, so event.target should be cast as HTMLInputElement in event handlers.
📚 Learning: 2025-11-06T06:47:24.645Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2567
File: src/lib/elements/forms/inputSelect.svelte:26-36
Timestamp: 2025-11-06T06:47:24.645Z
Learning: In the appwrite.io/pink-svelte library, the Input.Select component internally uses an `input` element (not a `select` element) that triggers the `on:input` event, so event.target should be cast as HTMLInputElement in event handlers.

Applied to files:

  • src/lib/commandCenter/commands.ts
  • src/lib/elements/forms/inputSelect.svelte
  • src/lib/commandCenter/commandCenter.svelte
📚 Learning: 2025-09-25T04:23:14.025Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2373
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/input.svelte:20-24
Timestamp: 2025-09-25T04:23:14.025Z
Learning: The Selector.Switch component from appwrite.io/pink-svelte doesn't accept `aria-describedby` or rest props (`...restProps`), limiting accessibility customization options.

Applied to files:

  • src/lib/elements/forms/inputSelect.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: e2e
  • GitHub Check: build
🔇 Additional comments (6)
src/lib/elements/forms/inputSelect.svelte (1)

59-59: LGTM! The attribute integrates correctly with the detection logic.

The data-command-center-ignore attribute will be detected by the closest selector in isTargetInputLike (line 118 of commands.ts), ensuring keyboard shortcuts are suppressed when typing in this select component.

src/lib/commandCenter/commands.ts (3)

103-104: LGTM! Constants are well-defined.

The INPUT_TAGS and INPUT_ROLES constants provide a clear, maintainable list of elements and ARIA roles that should be treated as input-like.


127-129: LGTM! Clean public API for input detection.

The exported function provides a clear interface for checking whether keyboard events originate from input-like elements.


231-239: LGTM! Correctly integrated into the command handler.

The isKeyboardEventFromInput(event) check is properly placed in the conditional to skip command processing when typing in input fields.

src/lib/commandCenter/commandCenter.svelte (2)

33-38: LGTM! Import correctly updated.

The isKeyboardEventFromInput function is properly imported from the centralized commands module.


103-110: LGTM! Correctly prevents shortcuts during input.

The guard clause at line 105 properly uses isKeyboardEventFromInput(e) to skip keyboard event processing when typing in input-like elements, preventing command center shortcuts from interfering.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/lib/commandCenter/commands.ts (1)

214-219: Integration looks correct.

The isKeyboardEventFromInput(event) check is properly integrated into the condition chain and will effectively prevent command shortcuts when typing in input-like elements.

Optional performance consideration: The isKeyboardEventFromInput function calls closest() on every keydown event, which traverses the DOM tree. While this is a reasonable trade-off for correctness, if performance becomes a concern under heavy keyboard input, consider memoizing results based on event.target or exploring event delegation patterns.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a030a29 and dc69034.

📒 Files selected for processing (1)
  • src/lib/commandCenter/commands.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2567
File: src/lib/elements/forms/inputSelect.svelte:26-36
Timestamp: 2025-11-06T06:47:24.645Z
Learning: In the appwrite.io/pink-svelte library, the Input.Select component internally uses an `input` element (not a `select` element) that triggers the `on:input` event, so event.target should be cast as HTMLInputElement in event handlers.
🔇 Additional comments (1)
src/lib/commandCenter/commands.ts (1)

110-112: LGTM! Clean abstraction.

The function provides a clean public API for keyboard event input detection with clear naming and proper delegation.

Comment on lines 103 to 108
function isTargetInputLike(element: EventTarget | null) {
if (!(element instanceof HTMLElement)) return false;
return !!element.closest(
'input,textarea,select,[contenteditable],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix contenteditable selector to exclude false values.

The selector [contenteditable] matches any element with the contenteditable attribute, including contenteditable="false", which explicitly marks an element as non-editable. This could incorrectly suppress shortcuts for non-editable elements.

Apply this diff to match only editable elements:

-    return !!element.closest(
-        'input,textarea,select,[contenteditable],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
-    );
+    return !!element.closest(
+        'input,textarea,select,[contenteditable="true"],[contenteditable=""],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
+    );

Or alternatively, check the attribute value programmatically:

 function isTargetInputLike(element: EventTarget | null) {
     if (!(element instanceof HTMLElement)) return false;
-    return !!element.closest(
-        'input,textarea,select,[contenteditable],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
-    );
+    const match = element.closest(
+        'input,textarea,select,[contenteditable],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
+    );
+    if (!match) return false;
+    if (match.hasAttribute('contenteditable') && match.getAttribute('contenteditable') === 'false') {
+        return false;
+    }
+    return true;
 }
📝 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
function isTargetInputLike(element: EventTarget | null) {
if (!(element instanceof HTMLElement)) return false;
return !!element.closest(
'input,textarea,select,[contenteditable],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
);
}
function isTargetInputLike(element: EventTarget | null) {
if (!(element instanceof HTMLElement)) return false;
return !!element.closest(
'input,textarea,select,[contenteditable="true"],[contenteditable=""],[role="combobox"],[role="textbox"],[role="searchbox"],[data-command-center-ignore]'
);
}
🤖 Prompt for AI Agents
In src/lib/commandCenter/commands.ts around lines 103 to 108, the CSS selector
'[contenteditable]' incorrectly matches elements with contenteditable="false";
update the check so only truly editable elements are treated as inputs. Replace
the selector to explicitly match editable values (e.g. use
'[contenteditable=""],[contenteditable="true"]' in the selector list) or modify
the function to programmatically inspect element.getAttribute('contenteditable')
and return false when the attribute value === 'false' and true for '', 'true' or
when attribute is absent but element is actually editable; ensure the final
logic still returns true for inputs, textareas, selects,
contenteditable=true/empty, role=textbox/combobox/searchbox and elements with
data-command-center-ignore.

}

export function isKeyboardEventFromInput(event: KeyboardEvent) {
return isTargetInputLike(event.target);
Copy link
Member

Choose a reason for hiding this comment

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

why not just export isTargetInputLike?

Copy link
Member

Choose a reason for hiding this comment

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

would this not affect every page with input selects and not just wizards?

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.

3 participants