solid-primitives icon indicating copy to clipboard operation
solid-primitives copied to clipboard

[keyboard] provide option to ignore shortcuts in input elements

Open AerisG222 opened this issue 2 years ago • 2 comments

Describe The Problem To Be Solved

There should be a way to ignore / opt out of shortcuts while typing in an input / select / textarea element.

For the scenario below, let's assume we have a button with a shortcut of 'S' and a textarea on the same page.

With the current default (preventDefault = true), when the letter is pressed while the textarea has focus, the shortcut gets triggered and the letter does not get added to the value of the input element. This is a problem as we should be able to type 'S' in the input.

If we then configure preventDefault = false - we get the desired behavior of the letter being added to the input, however the shortcut is also triggered, which may be undesirable.

Suggest A Solution

To address the issue with minimal impact to existing users, adding a new boolean option called something like 'ignoreInInputs' could be used to alter behavior in the shortcut logic. By default, this can be set to false to keep same behavior as today.

Finally, the documentation should be updated to describe these scenarios and add examples to make this as easy to use as possible.

Thanks for your consideration!

AerisG222 avatar Jul 19 '23 11:07 AerisG222

Yes please! In the meantime, there should be a workaround for this by wrapping each shortcut in a function checking the event target

mrlubos avatar Feb 23 '25 00:02 mrlubos

For anyone else finding this issue, I implemented my own drop in replacement for createShortcut().

import { createShortcut as createSolidShortcut } from "@solid-primitives/keyboard";
import type { KbdKey } from "@solid-primitives/keyboard";

export const createShortcut = (
  keys: KbdKey[],
  callback: (event: KeyboardEvent | null) => void,
  options?: {
    preventDefault?: boolean;
    requireReset?: boolean;
  }
): void => {
  createSolidShortcut(
    keys,
    (event) => {
      if (
        event &&
        (event.target as HTMLElement).matches(
          "input, textarea, select, [contenteditable=true]"
        )
      ) {
        return;
      }

      callback(event);
    },
    {
      preventDefault: false,
      requireReset: true,
      ...options,
    }
  );
};

mrlubos avatar Feb 23 '25 01:02 mrlubos