Autofocus the "OK" button like Photoshop

Is there a way to create an “OK” button in a UXP dialog modal that behaves like the OK button in Photoshop so that when you hit return, the autofocus is on the “OK” button, such that hitting return is like clicking the “OK” button. I can set the “OK” button to autofocus in HTML, but if the user interacts with the modal, like typing text in an input box, than the focus moves off the “OK” button and the action associated with the “OK” button doesn’t execute when the user hits return. In fact, after typing in an input box, hitting return is like hitting the ESC key, and the modal close without doing what the user expected after typing new information into the input box. This is the behavior on Windows. Haven’t tried this on Mac yet.

In Photoshop dialogs, like Image Size, hitting the return key resizes the image based on user’s new inputs in the dialog window. In other words, the focus is retained on the “OK” button even if the user interacts with other elements in the dialog window. It would be nice to emulate this behavior in UXP plugins also.

I’m not fully sure, but maybe what you’re describing is the same as this issue, for which Kerry posted a solution

You’d have to use the attribute “autofocus” and that’s it :slight_smile:

if (idx === buttons.length - 1) btnEl.setAttribute("autofocus", "autofocus");

preventDefault() prevents the Dialog from closing when hitting return.

Not sure that the “autofocus” solution works, though, since the initial autofocused element would blur if you clicked on some other element, like an input field, within the dialog window. So at that point, clicking return would NOT trigger the intended “OK” button script since it’s no longer focused. At least that’s what seems to be happening for me when I try to get this to work.

Yes, that’s the expected behavior. As the default is to call close("") (without any parameter) as kerry described, you don’t want that to be executed.
Instead, you call close() yourself, in which u can then add the values you want your dialog to return, for example:

formElement.addEventListener("submit", e => {
  e.preventDefault();
  (dlgEl as HTMLDialogElement).close(someTextInput.value)
});

OK, that all worked. Thank you @simonhenke and @Pierre_G.

For anyone following this thread, the following URL has more info on handling the close() value: HTMLDialogElement.returnValue - Web APIs | MDN

This was all new to me.

One last question regarding the following:

document.getElementById("buttonOK").setAttribute("autofocus", "autofocus");

Should the “autofocus” attribute be undone/disabled/removed once the Dialog is closed if the plugin uses multiple Dialogs that autofocus the “OK” button? HTML documents are only supposed to have one autofocused element. So it would seem appropriate to remove the “autofocus” attribute once its Dialog is closed.

I’m guessing the following code might work

document.getElementById("buttonOK").removeAttribute("autofocus");

Just wondering what the right thing is to do.

This is frustrating. What I’m finding is that setting autofocus to the “OK” button and using a keyboard return for the “submit” event actually runs the submit event twice when I have the “OK” button set to type=“submit”. That sort of makes sense, I guess. However, if I remove remove the type=“submit” from the “OK” button’s HTML, and give the “OK” button its own eventListener, but still have the “OK” button autofocused, a keyboard return still runs the intended result twice: once for the “submit” event and again for the autofocused “OK” button. So autofocusing the OK button appears to be potentially problematic when it comes to executing the associated JS if the default close() method is set to produce the same results as the “OK” button.

I also tried shifting autofocus to the input field instead of the “OK” button since that would be a workable alternative. But I found the input field doesn’t focus.

HTML: <sp-textfield quiet type="number" id="inputBLUR"></sp-textfield>

JS:

document.getElementById(“inputBLUR”).setAttribute(“autofocus”, “autofocus”);

At least on Windows, nothing is focused when the Dialog opens. However, on Mac, the input element focuses by default since it’s the first focus-able element in the dialog.

Issue seems to be solved by creating a dummy button and setting the JS to autofocus on it.

<div style="width: 0px; overflow: hidden"><sp-button id="buttonHIDDEN" >Test</sp-button></div>