fix(frontend): フォーカスの挙動を修正 (#14158)
* fix(frontend): 直前のパターンを記録するように * fix(frontend): フォーカス/タブ移動に関する挙動を調整 (#226) Cherry-pick commit e8c030673326871edf3623cf2b8675d68f9e1b13 Co-authored-by: taiyme <53635909+taiyme@users.noreply.github.com> * focusのデザイン修正 * move scripts * Modalにfocus trapを追加 * 記録するホットキーはレートリミット式にする * escキーのハンドリングをMkModalに統一 * fix * enterで子メニューを開けるように * lint * fix focus trap * improve switch accessibility * 一部のmodalのフォーカストラップが外れない問題を修正 * fix * fix * Revert "記録するホットキーはレートリミット式にする" This reverts commit40a7509286
. * Revert "fix(frontend): 直前のパターンを記録するように" This reverts commit5372b25940
. * Revert "Revert "fix(frontend): 直前のパターンを記録するように"" This reverts commita9bb52e799
. * Revert "Revert "記録するホットキーはレートリミット式にする"" This reverts commitbdac34273e
. * 試験的にCypressでのFocustrapを無効化 * fix * fix focus-trap * Update Changelog * ✌️ * fix focustrap invocation logic * スクロールがsticky headerを考慮するように * 🎨 * スタイルの微調整 * 🎨 * remove deprecated key aliases * focusElementが足りなかったので修正 * preview系にfocus時スタイルが足りなかったので修正 * `returnFocusElement` -> `returnFocusTo` * lint * Update packages/frontend/src/components/MkModalWindow.vue * Apply suggestions from code review Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com> * keydownイベントをまとめる * use correct pesudo-element selector * fix * rename --------- Co-authored-by: taiyme <53635909+taiyme@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
// TODO: なんでもかんでもos.tsに突っ込むのやめたいのでよしなに分割する
|
||||
|
||||
import { Component, markRaw, Ref, ref, defineAsyncComponent } from 'vue';
|
||||
import { Component, markRaw, Ref, ref, defineAsyncComponent, nextTick } from 'vue';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import type { ComponentProps as CP } from 'vue-component-type-helpers';
|
||||
@@ -24,6 +24,8 @@ import MkContextMenu from '@/components/MkContextMenu.vue';
|
||||
import { MenuItem } from '@/types/menu.js';
|
||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||
import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
|
||||
import { getHTMLElementOrNull } from '@/scripts/get-dom-node-or-null.js';
|
||||
import { focusParent } from './scripts/focus.js';
|
||||
|
||||
export const openingWindowsCount = ref(0);
|
||||
|
||||
@@ -622,31 +624,33 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
|
||||
export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | null, options?: {
|
||||
align?: string;
|
||||
width?: number;
|
||||
viaKeyboard?: boolean;
|
||||
onClosing?: () => void;
|
||||
}): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
let returnFocusTo = getHTMLElementOrNull(src) ?? getHTMLElementOrNull(document.activeElement);
|
||||
return new Promise(resolve => nextTick(() => {
|
||||
const { dispose } = popup(MkPopupMenu, {
|
||||
items,
|
||||
src,
|
||||
width: options?.width,
|
||||
align: options?.align,
|
||||
viaKeyboard: options?.viaKeyboard,
|
||||
returnFocusTo,
|
||||
}, {
|
||||
closed: () => {
|
||||
resolve();
|
||||
dispose();
|
||||
returnFocusTo = null;
|
||||
},
|
||||
closing: () => {
|
||||
if (options?.onClosing) options.onClosing();
|
||||
options?.onClosing?.();
|
||||
},
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
|
||||
let returnFocusTo = getHTMLElementOrNull(ev.currentTarget ?? ev.target) ?? getHTMLElementOrNull(document.activeElement);
|
||||
ev.preventDefault();
|
||||
return new Promise(resolve => {
|
||||
return new Promise(resolve => nextTick(() => {
|
||||
const { dispose } = popup(MkContextMenu, {
|
||||
items,
|
||||
ev,
|
||||
@@ -654,14 +658,19 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
|
||||
closed: () => {
|
||||
resolve();
|
||||
dispose();
|
||||
|
||||
// MkModalを通していないのでここでフォーカスを戻す処理を行う
|
||||
if (returnFocusTo != null) {
|
||||
focusParent(returnFocusTo, true, false);
|
||||
returnFocusTo = null;
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
export function post(props: Record<string, any> = {}): Promise<void> {
|
||||
showMovedDialog();
|
||||
|
||||
return new Promise(resolve => {
|
||||
// NOTE: MkPostFormDialogをdynamic importするとiOSでテキストエリアに自動フォーカスできない
|
||||
// NOTE: ただ、dynamic importしない場合、MkPostFormDialogインスタンスが使いまわされ、
|
||||
|
Reference in New Issue
Block a user