From c6d930b3f1bd92742a8b7574f3f6436fda7feda3 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Tue, 4 Aug 2026 16:50:07 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06):=20=EC=B8=A1=EC=A0=90=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EC=8B=9C=20=ED=9A=A1=EB=8B=A8=EB=8F=84=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EC=83=81=EB=8B=A8=EC=9D=84=20=ED=8C=A8=EB=84=90=20?= =?UTF-8?q?=EC=86=90=EC=9E=A1=EC=9D=B4=20=EC=95=84=EB=9E=98=20=EC=A0=95?= =?UTF-8?q?=EC=A7=80=EC=84=A0=EC=97=90=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - revealCard: scrollIntoView block nearest -> start (카드 하단이 브라우저 바닥에 걸리던 문제 수정, 카드 상단이 sticky 패널 아래에 붙음) - syncScrollMargin 신설: 스크롤 직전 패널 높이 실측 + 손잡이 24px + 여유 8px (접기 시 drawPanel 미실행이어도 정지선 최신 유지) - PLAN.md: A~D 항목 완료·취소 정리(2026-08-04 사용자 확정), 아카이빙 대기 표기 Co-Authored-By: Claude Opus 5 (1M context) --- .../B06_wf3_ProfileCross_UI_Section_View.ts | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts index b543e27c..741f892a 100644 --- a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts +++ b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts @@ -340,13 +340,27 @@ export function createSectionView( }; /** - * 선택 카드를 화면에 남긴다. 상단 패널이 sticky라 `center`로 보내면 패널이 커졌을 때 - * 그 아래로 숨는다 — `nearest` + `scroll-margin-top`(패널 높이)이면 가려질 때만, - * 가려지지 않을 만큼만 움직인다. + * 상단 패널이 sticky라 카드 스크롤 정지선은 `scroll-margin-top`(패널 높이 + 손잡이 몫)이다. + * 패널은 리사이저·접기 손잡이로 수시로 높이가 변하고, 접을 때는 drawPanel이 돌지 않으므로 + * **스크롤 직전에 실측**해야 정지선이 현재 패널과 맞는다. + */ + const syncScrollMargin = (): void => { + // 접기 손잡이가 패널 아래 24px 밖으로 나와 있고, 선택 강조(빨간 테두리 + 2px ring)가 + // 잘리지 않도록 8px 여유를 더한다. + const panelPx = panel.getBoundingClientRect().height || panelHeight(); + root.style.setProperty("--b06-cross-scroll-margin", `${Math.round(panelPx + 32)}px`); + }; + + /** + * 선택 카드를 화면에 남긴다. `nearest`는 카드가 아래에 있을 때 카드 **하단**을 브라우저 + * 바닥에 맞춰 멈추는데, 그러면 카드 상단(측점 라벨)이 화면 밖이다(2026-08-04 사용자 지적). + * `start`로 카드 **상단**을 접기 손잡이 바로 아래 정지선에 붙인다. 목록 맨 끝 카드는 + * 스크롤이 바닥에 걸려 그 자리까지 못 올라오며, 그대로 둔다(브라우저가 알아서 멈춘다). */ const revealCard = (stationId: string | null, behavior: ScrollBehavior): void => { if (!stationId) return; - document.getElementById(`cross-${stationId}`)?.scrollIntoView({ behavior, block: "nearest" }); + syncScrollMargin(); + document.getElementById(`cross-${stationId}`)?.scrollIntoView({ behavior, block: "start" }); }; /** 카드 하나의 선택 표시를 갱신한다 — **다시 만들지 않는다**(줌·팬이 살아남아야 한다). */ @@ -537,9 +551,7 @@ export function createSectionView( } chartWrap.scrollLeft = keepScrollLeft; // 상단 패널이 sticky라 선택 카드가 그 아래로 숨는다 — 패널 높이만큼 스크롤 여백을 잡아 준다. - // 접기 손잡이가 패널 아래 24px 밖으로 나와 있으므로 그 몫까지 더한다. - const panelPx = panel.getBoundingClientRect().height || panelHeight(); - root.style.setProperty("--b06-cross-scroll-margin", `${Math.round(panelPx + 32)}px`); + syncScrollMargin(); // 첫 렌더(detached)나 패널 높이 변경 직후에는 위에서 잰 값이 아직 옛 레이아웃일 수 있다. // 다음 프레임에 한 번만 다시 재서 어긋나면 고쳐 그린다. `chartWrap` 높이는 내용과 무관하니