diff options
| author | かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> | 2024-07-12 16:25:44 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-12 16:25:44 +0900 |
| commit | 385969e9f56a39a1e5547b94901d155e1e811263 (patch) | |
| tree | c5c4082d99d97f3220efd4dfd0926b4e809cfd3b /packages/frontend/src/components/MkNoteDetailed.vue | |
| parent | enhance(frontend): 未使用のサウンド設定を削除 (#14116) (diff) | |
| download | misskey-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.vue | 62 |
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 { |