Possible to map "mod" to "meta" on Mac and "ctrl" on Windows?

I’m trying to learn more about how Stimulus works, and I thought I would try adding a Cmd+Enter trigger so that a user can submit a form while typing in a <textarea>. This is a pretty common practice on the web. Except, Cmd is a Mac-only key. What I would love to do is create a Mod+Enter mapping where Mod maps to Cmd (Meta) on a Mac browser and Mod maps to Ctrl (Control) on a Windows browser:

<form data-controller="demo">
    <textarea data-action="keydown.mod+enter->demo#submit"></textarea>
</form>

I thought I might be able to do something like this in my bootstrapping:

var macOsPattern = /Mac|iPod|iPhone|iPad/;

// Map the "mod" filter pattern to the OS-specific key.
defaultSchema.keyMappings[ "mod" ] = macOsPattern.test( window.navigator.platform )
	? "meta"
	: "ctrl"
;

window.Stimulus = Application.start( document.documentElement, defaultSchema );

This, however, does not seem to work. Maybe I am doing it wrong; but, upon looking at the GitHub commit that added key filtering, it looks like the modifier keys are handled differently than other keys:

As such, I am not sure that there is a way to alias modifier keys like this. Does anyone have any pointers?

To illustrate this a different way, I could do this:

<form data-controller="demo">
    <textarea data-action="
        keydown.meta+enter->demo#submit
        keydown.ctrl+enter->demo#submit
    "></textarea>
</form>

And then, Mac users could do Cmd+Enter and Windows users could do Ctrl+Enter. But, obviously, this is quite verbose. I’d like to avoid if possible.

I have a problem with something similar and I suspect the issue might be the same. Have you tried using mod+enter on something else in your app?
I am trying to submit the form associated with a textarea, when a user presses Shift+Enter. However setting an action with a keyboard event filter on a textarea does not work:

// demo_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {

  submit(event) {
    console.log(event)
  }
}
<form data-controller="demo">
  <!-- this never calls the submit method on the controller above -->
  <textarea data-action="keydown.shift+enter->demo#submit"></textarea>
</form>

If I remove the filtering from the action declaration in the DOM, it works as expected:

<form data-controller="demo">
  <!-- this calls the submit method on the controller -->
  <textarea data-action="keydown->demo#submit"></textarea>
</form>

So I can make it work without filtering, but I expected that the filtering worked on a textarea too. I am on stimulus 3.1.0 and use the filters in other places in the app, so I know it works. The question is if this is a bug or intended (undocumented?) behavior?

My only thought is that perhaps the version of Stimulus that you’re using is a bit older? Based on the GitHub PR above, the keydown filtering wasn’t merged-in until Nov 21, 2022; and then, who knows how long before it was actually deployed to the published assets? So, I would say maybe try upgrading the version?

Well, this is embarrassing. I checked the latest release on GitHub and somehow read it as 3.1.0. You are absolutely right: I was on an old version. Thank you for your help.

1 Like

Ha, well at least we got one problem solved in this thread :raised_hands:

meta, ctrl, alt and shift are modifier keys. Modifier keys cannot currently be customized.

I like the idea and suggest submitting it to hotwire/turbo issues.

1 Like

Thanks for the suggestion, I just opened a ticket on the Stimulus repo – Feature Request - Cross-platform "modify" for keydown filter. · Issue #654 · hotwired/stimulus · GitHub