summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkNoteDetailed.vue
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2024-07-12 16:25:44 +0900
committerGitHub <noreply@github.com>2024-07-12 16:25:44 +0900
commit385969e9f56a39a1e5547b94901d155e1e811263 (patch)
treec5c4082d99d97f3220efd4dfd0926b4e809cfd3b /packages/frontend/src/components/MkNoteDetailed.vue
parentenhance(frontend): 未使用のサウンド設定を削除 (#14116) (diff)
downloadmisskey-385969e9f56a39a1e5547b94901d155e1e811263.tar.gz
misskey-385969e9f56a39a1e5547b94901d155e1e811263.tar.bz2
misskey-385969e9f56a39a1e5547b94901d155e1e811263.zip
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 commit 40a7509286a87911ad4cc06d9482e8a2e5d0e7e8. * Revert "fix(frontend): 直前のパターンを記録するように" This reverts commit 5372b2594023952cff34aa62253ed4efef15b5dd. * Revert "Revert "fix(frontend): 直前のパターンを記録するように"" This reverts commit a9bb52e799e110927ad92cd8f26af980819334e1. * Revert "Revert "記録するホットキーはレートリミット式にする"" This reverts commit bdac34273e0bc5f13604c7e2f9fa6b1321a0df3d. * 試験的にCypressでのFocustrapを無効化 * fix * fix focus-trap * Update Changelog * :v: * fix focustrap invocation logic * スクロールがsticky headerを考慮するように * :art: * スタイルの微調整 * :art: * 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>
Diffstat (limited to 'packages/frontend/src/components/MkNoteDetailed.vue')
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue62
1 files changed, 40 insertions, 22 deletions
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 8f65e3b60a..a8fed56c39 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -10,6 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
ref="rootEl"
v-hotkey="keymap"
:class="$style.root"
+ :tabindex="isDeleted ? '-1' : '0'"
>
<div v-if="appearNote.reply && appearNote.reply.replyId">
<div v-if="!conversationLoaded" style="padding: 16px">
@@ -31,7 +32,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</I18n>
</span>
<div :class="$style.renoteInfo">
- <button ref="renoteTime" class="_button" :class="$style.renoteTime" @click="showRenoteMenu()">
+ <button ref="renoteTime" class="_button" :class="$style.renoteTime" @mousedown.prevent="showRenoteMenu()">
<i v-if="isMyRenote" class="ti ti-dots" style="margin-right: 4px;"></i>
<MkTime :time="note.createdAt"/>
</button>
@@ -92,7 +93,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<div v-if="appearNote.files && appearNote.files.length > 0">
- <MkMediaList :mediaList="appearNote.files"/>
+ <MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
</div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/>
<div v-if="isEnabledUrlPreview">
@@ -118,7 +119,7 @@ SPDX-License-Identifier: AGPL-3.0-only
ref="renoteButton"
class="_button"
:class="$style.noteFooterButton"
- @mousedown="renote()"
+ @mousedown.prevent="renote()"
>
<i class="ti ti-repeat"></i>
<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
@@ -133,10 +134,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<i v-else class="ti ti-plus"></i>
<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || defaultStore.state.showReactionsCount) && appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.reactionCount) }}</p>
</button>
- <button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown="clip()">
+ <button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="clip()">
<i class="ti ti-paperclip"></i>
</button>
- <button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown="showMenu()">
+ <button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="showMenu()">
<i class="ti ti-dots"></i>
</button>
</footer>
@@ -281,6 +282,7 @@ const renoteTime = shallowRef<HTMLElement>();
const reactButton = shallowRef<HTMLElement>();
const clipButton = shallowRef<HTMLElement>();
const appearNote = computed(() => isRenote ? note.value.renote as Misskey.entities.Note : note.value);
+const galleryEl = shallowRef<InstanceType<typeof MkMediaList>>();
const isMyRenote = $i && ($i.id === note.value.userId);
const showContent = ref(false);
const isDeleted = ref(false);
@@ -303,6 +305,7 @@ const keymap = {
if (!defaultStore.state.showClipButtonInNoteFooter) return;
clip();
},
+ 'o': () => galleryEl.value?.openGallery(),
'v|enter': () => {
if (appearNote.value.cw != null) {
showContent.value = !showContent.value;
@@ -392,29 +395,26 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') {
});
}
-function renote(viaKeyboard = false) {
+function renote() {
pleaseLogin();
showMovedDialog();
const { menu } = getRenoteMenu({ note: note.value, renoteButton });
- os.popupMenu(menu, renoteButton.value, {
- viaKeyboard,
- });
+ os.popupMenu(menu, renoteButton.value);
}
-function reply(viaKeyboard = false): void {
+function reply(): void {
pleaseLogin();
showMovedDialog();
os.post({
reply: appearNote.value,
channel: appearNote.value.channel,
- animation: !viaKeyboard,
}).then(() => {
focus();
});
}
-function react(viaKeyboard = false): void {
+function react(): void {
pleaseLogin();
showMovedDialog();
if (appearNote.value.reactionAcceptance === 'likeOnly') {
@@ -424,7 +424,7 @@ function react(viaKeyboard = false): void {
noteId: appearNote.value.id,
reaction: '❤️',
});
- const el = reactButton.value as HTMLElement | null | undefined;
+ const el = reactButton.value;
if (el) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
@@ -488,18 +488,16 @@ function onContextmenu(ev: MouseEvent): void {
}
}
-function showMenu(viaKeyboard = false): void {
+function showMenu(): void {
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
- os.popupMenu(menu, menuButton.value, {
- viaKeyboard,
- }).then(focus).finally(cleanup);
+ os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup);
}
-async function clip() {
+async function clip(): Promise<void> {
os.popupMenu(await getNoteClipMenu({ note: note.value, isDeleted }), clipButton.value).then(focus);
}
-function showRenoteMenu(viaKeyboard = false): void {
+function showRenoteMenu(): void {
if (!isMyRenote) return;
pleaseLogin();
os.popupMenu([{
@@ -512,9 +510,7 @@ function showRenoteMenu(viaKeyboard = false): void {
});
isDeleted.value = true;
},
- }], renoteTime.value, {
- viaKeyboard: viaKeyboard,
- });
+ }], renoteTime.value);
}
function focus() {
@@ -556,6 +552,28 @@ function loadConversation() {
transition: box-shadow 0.1s ease;
overflow: clip;
contain: content;
+
+ &:focus-visible {
+ outline: none;
+
+ &::after {
+ content: "";
+ pointer-events: none;
+ display: block;
+ position: absolute;
+ z-index: 10;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ width: calc(100% - 8px);
+ height: calc(100% - 8px);
+ border: dashed 2px var(--focus);
+ border-radius: var(--radius);
+ box-sizing: border-box;
+ }
+ }
}
.replyTo {