mirror of
https://github.com/HeyPuter/puter.git
synced 2026-10-12 23:00:06 +00:00
fix: keep the recipient field focused when the picker is wired onto it
Both sharing dialogs focus the recipient field as they open, and the picker then moves that field into its wrapper. Moving an element takes it out of the document for an instant, which drops its focus, so every dialog opened with the caret in the field opened with the caret on <body> instead.
This commit is contained in:
1 parent
7795747dce
commit
7b9f0e4c3d
2 files changed
+17
-1
No files matched your search
@@ -76,8 +76,13 @@ export default function shareRecipientPicker ({
|
||||
const list_id = `share-suggest-list-${++picker_seq}`;
|
||||
|
||||
const $field = $('<div class="share-suggest-field"></div>');
|
||||
// Both dialogs focus this field as they open, and an element that leaves
|
||||
// the document — which is what moving it into the wrapper does — takes its
|
||||
// focus with it. Put it back rather than leaving the caller to notice.
|
||||
const had_focus = document.activeElement === $input.get(0);
|
||||
$input.before($field);
|
||||
$field.append($input);
|
||||
if ( had_focus ) $input.get(0)?.focus({ preventScroll: true });
|
||||
const $clear = $(`<button type="button" class="share-suggest-clear" hidden
|
||||
aria-label="${i18n('share_clear_recipient')}" title="${i18n('share_clear_recipient')}">${clearIcon}</button>`);
|
||||
$field.append($clear);
|
||||
|
||||
@@ -38,7 +38,7 @@ beforeAll(async () => {
|
||||
let mounted = [];
|
||||
|
||||
/** Renders the markup both dialogs share and attaches a picker to it. */
|
||||
const mount = (opts = {}) => {
|
||||
const mount = ({ focus_first = false, ...opts } = {}) => {
|
||||
document.body.innerHTML = `
|
||||
<div class="host">
|
||||
<div class="row">
|
||||
@@ -47,6 +47,8 @@ const mount = (opts = {}) => {
|
||||
</div>
|
||||
</div>`;
|
||||
const $input = $('.recipient');
|
||||
// Both dialogs focus the field before the picker is wired onto it.
|
||||
if ( focus_first ) $input.get(0).focus();
|
||||
const picker = shareRecipientPicker({
|
||||
$input,
|
||||
$row: $('.row'),
|
||||
@@ -94,6 +96,15 @@ afterEach(() => {
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
describe('wiring onto the field', () => {
|
||||
it('keeps the focus the dialog put there before wiring', () => {
|
||||
const { $input } = mount({ focus_first: true });
|
||||
// Moving the field into the wrapper takes it out of the document for
|
||||
// an instant, which is enough to drop focus if nobody puts it back.
|
||||
expect(document.activeElement).toBe($input.get(0));
|
||||
});
|
||||
});
|
||||
|
||||
describe('opening the list', () => {
|
||||
it('stays shut until the field is actually used', async () => {
|
||||
const { $input } = mount();
|
||||
|
||||
Reference in new issue
Block a user