[Report] $edit-text with focus="yes" does not takes keyboard focus when inside a modal
Problem description
An <$edit-text> field with focus="yes" inside a modal opened with tm-modal never receives focus, regardless of how the modal is opened (whether by clicking a button or using a keyboard shortcut).
The same attribute works when the tiddler is opened in the story river, so modals are a specific context where focus silently does nothing.
tm-focus-selector does work for this use case as a workaround but it is naturally more obscure. I would not have thought to do it without AI assistance.
To reproduce
Import this 6-tiddler JSON and then:
- Open the Open modal tiddler and click Open modal. The modal opens, but the field does not receive focus.
- Close the modal and click Open modal (focused).
This is identical to the first button except that a
tm-focus-selectormessage is sent immediately aftertm-modal. The field is focused. - Press Alt+R. The modal with a simple
focus="yes"opens, and the field again does not receive focus. - Press Alt+F. This is the same trigger but with the explicit
tm-focus-selectorstep. The field is focused. So the step works from the keyboard too.
For contrast, you can transclude {{Focus modal}} into any regular tiddler. The field will receive focus from focus="yes" alone.
Expected behaviour
As a user,
I would expect focus="yes" to focus the field inside a modal exactly as it does in the story river,
Without having to know that an extra tm-focus-selector message must be sent after every tm-modal.
Environment
TiddlyWiki configuration
- Version: v5.4.1
- Saving mechanism: Not relevant
- Plugins installed: Not relevant
Desktop
- OS: Fedora Linux 44 KDE Edition
- Browser: Ungoogled Chromium 152.0.7977.82
Additional context
I use keyboard shortcuts to open modals for a to-do list application (a new tiddler creation form, the first field of which is the title). I need to reach for the mouse to focus the first field, and I would prefer to be able to start typing my new tiddler title right away.
A keyboard shortcut is where it is most problematic, because the user is already at the keyboard.
Workaround
May give you some ideas for the solution.
You can work around this by sending an explicit tm-focus-selector message after every tm-modal, as the second button (Alt+F) does in the wiki.
focus is implemented at render time. $:/core/modules/editor/factory.js, in EditTextWidget.render():
// Focus if required
if($tw.browser && (this.editFocus === "true" || this.editFocus === "yes") && !$tw.utils.hasClass(this.parentDomNode.ownerDocument.activeElement,"tc-keep-focus")) {
this.engine.focus();
}The engines focus synchronously — e.g. SimpleEngine.focus() in $:/core/modules/editor/engines/simple.js just calls this.domNode.focus().
tm-modal is handled by $tw.modal.display() in $:/core/modules/utils/dom/modal.js, whose ordering is the problem:
bodyWidgetNode.render(modalBody,null); // modal body rendered here — wrapper not yet in the document
...
// Put the message into the document
this.srcDocument.body.appendChild(wrapper); // append happens only afterwardsAll four widget trees of the modal (navigator, header, body, footer) are rendered while wrapper is detached from the document; the single appendChild(wrapper) comes later in the same function. So at the moment engine.focus() runs, the field has no connection to the document, and per browser behaviour .focus() on such an element is a no-op — document.activeElement is unchanged, and nothing re-focuses the field after the append. (The activeElement guard in the focus block passes because ownerDocument is still the real document during detached rendering.)
Steps 2 and 4 of the reproduction confirm both halves of that diagnosis: an explicit tm-focus-selector sent after the modal has attached works from either trigger, and the identical widget focuses from focus="yes" alone when rendered attached. The only thing at fault is the timing of the render-time focus attempt relative to the append.
Source: TiddlyWiki/TiddlyWiki5