From 6d90e09a587e000fb780f64dae4a1d249568dbc3 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Wed, 16 Apr 2025 10:35:05 +0900
Subject: [PATCH] =?UTF-8?q?enhance(frontend):=20=E3=82=BF=E3=82=A4?=
=?UTF-8?q?=E3=83=A0=E3=83=A9=E3=82=A4=E3=83=B3=E4=BB=A5=E5=A4=96=E3=81=A7?=
=?UTF-8?q?=E3=82=82=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC=E3=83=AB=E4=BD=8D?=
=?UTF-8?q?=E7=BD=AE=E3=81=AE=E4=BF=9D=E6=8C=81=E3=82=92=E8=A9=A6=E3=81=BF?=
=?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/components/MkNotifications.vue | 4 +-
.../src/components/global/PageWithHeader.vue | 3 ++
.../src/use/use-scroll-position-keeper.ts | 39 +++++++++++++------
3 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue
index 99eca35eb7..b8fada1020 100644
--- a/packages/frontend/src/components/MkNotifications.vue
+++ b/packages/frontend/src/components/MkNotifications.vue
@@ -24,8 +24,8 @@ SPDX-License-Identifier: AGPL-3.0-only
tag="div"
>
-
-
+
+
diff --git a/packages/frontend/src/components/global/PageWithHeader.vue b/packages/frontend/src/components/global/PageWithHeader.vue
index 7ea0b5c97f..99f8df0780 100644
--- a/packages/frontend/src/components/global/PageWithHeader.vue
+++ b/packages/frontend/src/components/global/PageWithHeader.vue
@@ -20,6 +20,7 @@ import { useTemplateRef } from 'vue';
import { scrollInContainer } from '@@/js/scroll.js';
import type { PageHeaderItem } from '@/types/page-header.js';
import type { Tab } from './MkPageHeader.tabs.vue';
+import { useScrollPositionKeeper } from '@/use/use-scroll-position-keeper.js';
const props = withDefaults(defineProps<{
tabs?: Tab[];
@@ -35,6 +36,8 @@ const props = withDefaults(defineProps<{
const tab = defineModel('tab');
const rootEl = useTemplateRef('rootEl');
+useScrollPositionKeeper(rootEl);
+
defineExpose({
scrollToTop: () => {
if (rootEl.value) scrollInContainer(rootEl.value, { top: 0, behavior: 'smooth' });
diff --git a/packages/frontend/src/use/use-scroll-position-keeper.ts b/packages/frontend/src/use/use-scroll-position-keeper.ts
index 00cc51a459..f7b3015cc9 100644
--- a/packages/frontend/src/use/use-scroll-position-keeper.ts
+++ b/packages/frontend/src/use/use-scroll-position-keeper.ts
@@ -4,19 +4,22 @@
*/
import { throttle } from 'throttle-debounce';
-import { nextTick, onActivated, onUnmounted, watch } from 'vue';
+import { nextTick, onActivated, onDeactivated, onUnmounted, watch } from 'vue';
import type { Ref } from 'vue';
// note render skippingがオンだとズレるため、遷移直前にスクロール範囲に表示されているdata-scroll-anchor要素を特定して、復元時に当該要素までスクロールするようにする
export function useScrollPositionKeeper(scrollContainerRef: Ref): void {
let anchorId: string | null = null;
+ let ready = true;
watch(scrollContainerRef, (el) => {
if (!el) return;
const onScroll = () => {
if (!el) return;
+ if (!ready) return;
+
const scrollContainerRect = el.getBoundingClientRect();
const viewPosition = scrollContainerRect.height / 2;
@@ -41,18 +44,32 @@ export function useScrollPositionKeeper(scrollContainerRef: Ref {
+ if (!anchorId) return;
+ const scrollContainer = scrollContainerRef.value;
+ if (!scrollContainer) return;
+ const scrollAnchorEl = scrollContainer.querySelector(`[data-scroll-anchor="${anchorId}"]`);
+ if (!scrollAnchorEl) return;
+ scrollAnchorEl.scrollIntoView({
+ behavior: 'instant',
+ block: 'center',
+ inline: 'center',
+ });
+ };
+
+ onDeactivated(() => {
+ ready = false;
+ });
+
onActivated(() => {
+ restore();
nextTick(() => {
- if (!anchorId) return;
- const scrollContainer = scrollContainerRef.value;
- if (!scrollContainer) return;
- const scrollAnchorEl = scrollContainer.querySelector(`[data-scroll-anchor="${anchorId}"]`);
- if (!scrollAnchorEl) return;
- scrollAnchorEl.scrollIntoView({
- behavior: 'instant',
- block: 'center',
- inline: 'center',
- });
+ restore();
+ window.setTimeout(() => {
+ restore();
+
+ ready = true;
+ }, 100);
});
});
}