From 0800796998b3a802107efbe11df05756e0a35024 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 17 Oct 2026 14:44:23 +0900 Subject: [PATCH] =?UTF-8?q?feat(382-1):=20B05=20=EC=9A=B0=EC=B8=A1=20?= =?UTF-8?q?=ED=9A=A1=EB=8B=A8=20=ED=8C=90=20=3D=20=ED=8C=A8=EB=84=90=20?= =?UTF-8?q?=EC=96=91=EC=8B=9D(=EC=86=90=EC=9E=A1=EC=9D=B4=20=C2=B7=20?= =?UTF-8?q?=EB=A8=B8=EB=A6=AC=20=C2=B7=20=ED=8F=AD=20=EB=81=8C=EA=B8=B0=20?= =?UTF-8?q?=C2=B7=20=EC=97=B4=EB=A6=BC=20=C2=B7=20=ED=8F=AD=20=EA=B8=B0?= =?UTF-8?q?=EC=96=B5=20=C2=B7=20=EC=A7=80=EB=8F=84=20=EC=9C=84=20=EB=8D=AE?= =?UTF-8?q?=EA=B0=9C=20=EA=B7=B8=EB=8C=80=EB=A1=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01TteK8mfYZetk5P3bEZkyVZ --- .../B05_Profile_UI_RouteEdit_Chrome.ts | 44 ++++++++++++------- .../B05_Profile_UI_Style_RouteEdit.css | 34 +++++--------- .../tester/test_b05_routeedit_chrome_modal.py | 11 ++--- 3 files changed, 45 insertions(+), 44 deletions(-) diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts index 13021c9e8..388c3061c 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts @@ -1,4 +1,5 @@ import { createButton } from "@ui/ui_template_elements"; +import { createSidePanels, type SidePanels } from "@ui/ui_template_side_panels"; import { bindFootprintToggle } from "./B05_Profile_UI_RouteEdit_Footprint"; /* ============================================================================= @@ -46,6 +47,12 @@ export interface RouteEditChrome { terrainSelect: HTMLSelectElement; } +/** 손잡이 자리(24) + 틈(8) — 접혀도 남는 폭(`.ui-side-panels` margin-left). */ +const SIDE_HANDLE_PX = 32; + +/** 횡단 판 몸 → 패널 묶음 — 고른 측점 횡단을 띄울 때 접힌 판을 폄(382-2 · `_Cross`). */ +export const sidePanelsOf = new WeakMap(); + // 글판 접기 기억(345-5 덧 3) — 페이지 동안만(모듈 값) · 다시 열어도 그대로. let hintOpen = false; let infoCollapsed = false; @@ -118,26 +125,33 @@ export function createRouteEditChrome( - `; + `; parent.append(overlay); // 부른 쪽 단추([3D])도 같은 유리 단추로 — 지도 위에 떠 있는 도구줄. tools.forEach((tool) => tool.classList.replace("ui-btn--ghost", "ui-btn--glass")); overlay.querySelector('[data-slot="tools"]')!.replaceWith(...tools); - // 횡단 미리보기 = 접는 칸 — 좁은 화면은 접힌 채 시작(지도가 먼저다). - const sideWrap = overlay.querySelector(".b05-routeedit__side-wrap")!; - const sideToggle = overlay.querySelector('[data-act="side-toggle"]')!; - const setSide = (open: boolean): void => { - sideWrap.classList.toggle("is-collapsed", !open); - overlay.classList.toggle("is-side-open", open); // 회전 단추 · 잰 값 창이 판을 비킴 - sideToggle.setAttribute("aria-expanded", String(open)); - }; - setSide(window.innerWidth >= 1500); - sideToggle.addEventListener("click", () => setSide(sideWrap.classList.contains("is-collapsed"))); + // 횡단 미리보기 = 패널 양식(382-1 · 손잡이 · 머리 · 폭 끌기 · 열림 · 폭 기억) · 자리는 지도 위 덮개 그대로 · + // 기억이 없으면 좁은 화면은 접힌 채 시작(지도가 먼저다) · 잰 값 창이 판을 비킴(--b05-side-open). + const side = document.createElement("div"); + side.className = "b05-routeedit__side"; + const setSideOpen = (): void => + overlay.style.setProperty( + "--b05-side-open", + `${(panels.current() ? panels.width() : 0) + SIDE_HANDLE_PX}px`, + ); + const panels = createSidePanels({ + prefKey: "b05-routeedit-cross", + panels: [{ id: "cross", title: "횡단", body: side }], + defaultOpen: window.innerWidth >= 1500 ? "cross" : null, + defaultWidth: 460, + follow: false, + onChange: setSideOpen, + onResize: setSideOpen, + }); + sidePanelsOf.set(side, panels); + overlay.querySelector(".b05-routeedit__side-wrap")!.append(panels.root); + setSideOpen(); // 도움말 = 기본 접힘 · [?] 한 번에 펼침(345-5 덧 3). const hint = overlay.querySelector(".b05-routeedit__hint")!; diff --git a/B05_Profile/B05_Profile_UI_Style_RouteEdit.css b/B05_Profile/B05_Profile_UI_Style_RouteEdit.css index 2698017ad..9a436bcc2 100644 --- a/B05_Profile/B05_Profile_UI_Style_RouteEdit.css +++ b/B05_Profile/B05_Profile_UI_Style_RouteEdit.css @@ -4,17 +4,13 @@ /* 평면 = 가운데 칸 전체(352-1) — 머리 줄 · 테두리 없음. 도구줄은 3D 와 같은 떠 있는 유리 단추 (`.b05-route__view-controls` · ☰ 비킴 `--wf-burger-pad`) · 횡단 판은 오른쪽을 덮는 판. */ .b05-routeedit { - --b05-side-open: 0px; /* 횡단 판이 펴져 지도를 덮는 폭 */ + --b05-side-open: 0px; /* 횡단 판이 지도를 덮는 폭(손잡이 포함 · `_Chrome` 이 적음) */ position: relative; display: flex; flex: 1 1 auto; min-height: 0; } -.b05-routeedit.is-side-open { - --b05-side-open: 460px; -} - /* 도구줄 — 3D 도구줄 규격 그대로 · 회전 단추도 이 줄(366-2) · 넘치면 줄바꿈. */ .b05-routeedit__tools { right: var(--spacing-12); @@ -187,9 +183,8 @@ border-top: 2px solid var(--map-route, #f97316); } -/* 오른쪽 덮는 판 — 위아래 반씩 나눠 **지금 횡단**과 **이전 횡단**이 앉는다(352-1). 지도 위에 얹고 - 아래 종단 판(z 3)이 그 위를 덮는다. 접는 칸(345-3) — 좁은 화면은 접힌 채 시작(`_Chrome`) · - [횡단] 단추로 펴고 접는다. 빈 자리는 지도 조작을 통과. */ +/* 오른쪽 덮는 판 — 패널 양식(382-1 · `ui_template_side_panels` · 손잡이 · 머리 · 폭 끌기) 을 지도 위에 얹음 · + 위아래 반씩 **지금 횡단** · **이전 횡단**(352-1) · 아래 종단 판(z 3)이 그 위를 덮음 · 빈 자리는 지도 조작을 통과. */ .b05-routeedit__side-wrap { position: absolute; z-index: 2; @@ -197,24 +192,20 @@ right: var(--spacing-12); bottom: var(--spacing-12); display: flex; - flex-direction: column; - gap: var(--spacing-8); min-height: 0; pointer-events: none; } -.b05-routeedit__side-wrap.is-collapsed { - bottom: auto; -} - .b05-routeedit__side-wrap > * { pointer-events: auto; } -.b05-routeedit__side-toggle { - align-self: flex-end; - min-width: 56px; - height: 34px; +.b05-routeedit__side-wrap .ui-side-panels__panel { + box-shadow: 0 12px 40px rgb(0 0 0 / 45%); +} + +.b05-routeedit__side-wrap .ui-side-panels__body { + display: flex; } .b05-routeedit__side { @@ -222,14 +213,10 @@ flex: 1 1 auto; flex-direction: column; gap: var(--spacing-12); - width: 452px; + min-width: 0; min-height: 0; } -.b05-routeedit__side-wrap.is-collapsed > .b05-routeedit__side { - display: none; -} - .b05-routeedit__cross { display: flex; flex: 1 1 0; @@ -241,7 +228,6 @@ border: 1px solid var(--color-border); border-radius: var(--radius-16, 12px); background: var(--color-surface-raised); - box-shadow: 0 12px 40px rgb(0 0 0 / 45%); } .b05-routeedit__cross-head { diff --git a/resources/tester/test_b05_routeedit_chrome_modal.py b/resources/tester/test_b05_routeedit_chrome_modal.py index 0214f08ef..edc64cac1 100644 --- a/resources/tester/test_b05_routeedit_chrome_modal.py +++ b/resources/tester/test_b05_routeedit_chrome_modal.py @@ -43,7 +43,9 @@ def test_겉틀은_본문_칸(): assert 'title="되돌리기 (Ctrl+Z)"' in chrome and 'title="다시하기 (Ctrl+Y)"' in chrome # 시험 · 배선이 집는 자리는 남김 assert "b05-routeedit__measure-close" in chrome - assert 'data-act="side-toggle"' in chrome and "is-collapsed" in chrome + # 382-1 — 오른쪽 횡단 판 = 패널 양식(손잡이 · 머리 · 폭 끌기 · 열림 · 폭 기억) · 칸 높이를 채움 + assert "createSidePanels({" in chrome and 'prefKey: "b05-routeedit-cross"' in chrome + assert "follow: false" in chrome and 'data-act="side-toggle"' not in chrome def test_CSS_덮개_걷음_대기막은_전체(): @@ -55,9 +57,8 @@ def test_CSS_덮개_걷음_대기막은_전체(): assert "position: fixed;" in busy and "z-index: var(--z-modal, 1000);" in busy label = _block(css, ".b05-routeedit__label") assert "position: absolute;" in label and "position: fixed" not in label - assert "display: none;" in _block( - css, ".b05-routeedit__side-wrap.is-collapsed > .b05-routeedit__side" - ) + # 382-1 — 자체 [횡단] 단추 · 접기 걷음(접기는 양식 손잡이) + assert "b05-routeedit__side-toggle" not in css and "is-side-open" not in css assert "@media (width < 1500px)" not in css # 접기는 단추로(처음만 폭으로) @@ -87,7 +88,7 @@ def test_352_1_머리줄_상자_없음_도구는_뜬_단추_횡단은_우측_덮 assert "right: var(--spacing-12);" in _block(css, ".b05-routeedit__spin") # 도구줄 줄 오른쪽 assert "34px" in side # 횡단 판은 도구줄 줄 아래에서 시작 assert "var(--b05-side-open)" in _block(css, ".b05-routeedit__measure") - assert "is-side-open" in chrome + assert '"--b05-side-open"' in chrome # 판 폭(손잡이 포함)을 적음 glass = _block(css, ".b05-routeedit__terrain") assert "backdrop-filter: blur(6px);" in glass and "background:" in glass