From ec498dd20066cb6bdf0b77c104357b44f28f3f53 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Fri, 16 Oct 2026 20:33:43 +0900 Subject: [PATCH] =?UTF-8?q?feat(B05):=20352-1=20=ED=8F=89=EB=A9=B4=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=B9=B8=20=C2=B7=20=EB=A8=B8=EB=A6=AC=20?= =?UTF-8?q?=EC=A4=84=20=C2=B7=20=ED=85=8C=EB=91=90=EB=A6=AC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=C2=B7=20=EB=8F=84=EA=B5=AC=20=EB=96=A0=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EC=9C=A0=EB=A6=AC=20=EB=8B=A8=EC=B6=94=20=C2=B7=20?= =?UTF-8?q?=ED=9A=A1=EB=8B=A8=20=EC=9A=B0=EC=B8=A1=20=EB=8D=AE=EB=8A=94=20?= =?UTF-8?q?=ED=8C=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 머리 줄(제목 · 테두리)과 상자 삭제 · 도구줄 = 3D 와 같은 떠 있는 단추(☰ 비킴) - [?] 도구줄 아래 · 분석 지형 글에 유리 바탕 - 횡단 판 = 오른쪽 덮는 판(z 2 · 아래 종단 판 z 3 이 위) · 회전 단추 · 잰 값 창이 판을 비킴 - 시험 chrome_modal · initial 고쳐 씀 Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn --- .../B05_Profile_UI_RouteEdit_Chrome.ts | 44 ++++--- .../B05_Profile_UI_Style_RouteEdit.css | 117 ++++++++---------- .../tester/test_b05_routeedit_chrome_modal.py | 30 +++++ .../tester/test_b05_routeedit_initial.py | 4 +- 4 files changed, 104 insertions(+), 91 deletions(-) diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts index bac5493ed..875da3db4 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts @@ -8,9 +8,9 @@ import { bindFootprintToggle } from "./B05_Profile_UI_RouteEdit_Footprint"; * `B05_Profile_UI_RouteEdit.ts` 가 700줄을 넘겨 떼어낸 조각이다(2026-09-12). 생김새만 있고 * 동작은 없다 — 배선은 본체와 각 조각(`_Apply`·`_Rotate`·`_History`…)이 한다. * - * **배치**(2026-09-12 사용자 지시 ⑩~⑬·⑱) — 아래 정보행을 없애고 지도 위 오버레이로 옮겼다. - * 단추는 제목행 오른쪽, 조작 설명은 지도 왼쪽 위 2열, 상태·범례는 왼쪽 아래, 잰 값은 오른쪽 - * 아래. 메인 창은 왼쪽으로 밀고 오른쪽 세로 칸에 횡단 두 판이 앉는다. + * **배치**(352-1) — 지도가 칸 전체 · 머리 줄 · 테두리 없음. 도구는 3D 와 같은 떠 있는 유리 단추 + * (지도 왼쪽 위 · ☰ 비킴), [?] 조작 설명은 도구줄 아래 2열, 상태·범례는 왼쪽 아래, 잰 값은 오른쪽 + * 아래. 횡단 두 판은 지도 오른쪽을 덮는 판(아래 종단 판이 그 위). * * 자리(345-3) — 모달이 아니라 종단 보기 가운데 위 본문(옛 3D 자리)에 붙는다. 덮개 · 전체 화면 · * 닫기 단추는 걷었다 · [취소] · [확인] · [노선 반영] · [저장 전으로]는 없앰(346-3 · 352-2 — 노선은 페이지 @@ -57,12 +57,11 @@ export function createRouteEditChrome( const overlay = document.createElement("div"); overlay.className = "b05-routeedit"; overlay.innerHTML = ` -
-
-

계획노선

- +
+ +
- + - - - - - - - - - -
-
- +
@@ -121,15 +117,16 @@ 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); // 횡단 미리보기 = 접는 칸 — 좁은 화면은 접힌 채 시작(지도가 먼저다). @@ -137,6 +134,7 @@ export function createRouteEditChrome( 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); diff --git a/B05_Profile/B05_Profile_UI_Style_RouteEdit.css b/B05_Profile/B05_Profile_UI_Style_RouteEdit.css index a9cc78586..00e97dd68 100644 --- a/B05_Profile/B05_Profile_UI_Style_RouteEdit.css +++ b/B05_Profile/B05_Profile_UI_Style_RouteEdit.css @@ -1,59 +1,37 @@ /* 계획노선 편집(평면) — 종단 보기 가운데 위 본문(옛 3D 자리 · 345-3). 덮개 · 전체 화면은 걷음 — 재계산 대기 막만 화면을 덮는다(노선 재탐색 · CLAUDE.md 5장). 색은 전부 테마 토큰을 쓴다. */ +/* 평면 = 가운데 칸 전체(352-1) — 머리 줄 · 테두리 없음. 도구줄은 3D 와 같은 떠 있는 유리 단추 + (`.b05-route__view-controls` · ☰ 비킴 `--wf-burger-pad`) · 횡단 판은 오른쪽을 덮는 판. */ .b05-routeedit { + --b05-side-open: 0px; /* 횡단 판이 펴져 지도를 덮는 폭 */ + --b05-side-top: 64px; /* 접힌 [횡단] 단추가 위 오른쪽을 덮는 폭 */ position: relative; display: flex; flex: 1 1 auto; - gap: var(--spacing-8); min-height: 0; - padding: var(--spacing-8); } -/* 메인 창은 **왼쪽**, 횡단 두 판은 오른쪽 세로 칸(2026-09-12 사용자 지시 ⑱). - 좁은 화면에서는 오른쪽 칸이 접히고 메인이 폭을 다 가진다. */ -.b05-routeedit__box { - position: relative; - display: flex; - flex: 1 1 auto; - flex-direction: column; - min-width: 0; - height: 100%; - overflow: hidden; - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - background: var(--color-surface-raised); +.b05-routeedit.is-side-open { + --b05-side-open: 460px; + --b05-side-top: 460px; } -/* 머리 = 도구줄 — 왼쪽 이름 · 오른쪽 단추 묶음. */ -.b05-routeedit__head { - display: flex; - flex: none; - align-items: center; - gap: var(--spacing-12); - padding: var(--spacing-8) var(--spacing-12); - border-bottom: 1px solid var(--color-border); -} - -.b05-routeedit__head > h3 { - margin: 0; - font-size: var(--text-body); -} - -/* 제목행 — 왼쪽에 이름, **오른쪽 끝에 단추 묶음**(2026-09-12 사용자 지시 ⑪). - 단추는 공용 규격(`.ui-btn`)을 그대로 쓴다 — 모달이 따로 만든 크기를 걷어냈다. */ -.b05-routeedit__actions { - display: flex; - flex: 1 1 auto; +/* 도구줄 — 3D 도구줄 규격 그대로 · 오른쪽 회전 단추 · 횡단 판을 비켜 줄바꿈. */ +.b05-routeedit__tools { + right: calc(var(--spacing-12) + var(--b05-side-top) + 104px); flex-wrap: wrap; - align-items: center; - justify-content: flex-end; - gap: var(--spacing-8); + pointer-events: none; /* 빈 자리는 지도 조작을 통과 */ +} + +.b05-routeedit__tools > * { + pointer-events: auto; } .b05-routeedit__canvas-wrap { position: relative; flex: 1 1 auto; + min-width: 0; min-height: 0; overflow: hidden; background: var(--color-surface); @@ -86,10 +64,10 @@ z-index: 1; } -/* 조작 설명 — 지도 왼쪽 위 · 기본 접힘 · [?] 로 펼침(345-5 덧 3) · 펼치면 **2열**(사용자 지시 ⑩). */ +/* 조작 설명 — 도구줄 아래 왼쪽 · 기본 접힘 · [?] 로 펼침(345-5 덧 3 · 352-1) · 펼치면 **2열**(사용자 지시 ⑩). */ .b05-routeedit__hint { - top: var(--spacing-12); - left: var(--spacing-12); + top: calc(var(--spacing-16) + 34px + var(--spacing-8)); + left: var(--spacing-16); display: flex; align-items: flex-start; gap: var(--spacing-8); @@ -173,11 +151,11 @@ color: var(--color-text-body); } -/* 회전 단추 — 지도 오른쪽 위(사용자 지시 ⑯). 여기만 클릭을 받는다. */ +/* 회전 단추 — 지도 오른쪽 위(사용자 지시 ⑯) · 횡단 판 왼쪽에 앉음(352-1). 여기만 클릭을 받는다. */ .b05-routeedit__spin { position: absolute; - top: var(--spacing-12); - right: var(--spacing-12); + top: var(--spacing-16); + right: calc(var(--spacing-12) + var(--b05-side-top)); z-index: 1; display: flex; gap: var(--spacing-8); @@ -211,18 +189,34 @@ border-top: 2px solid var(--map-route, #f97316); } -/* 오른쪽 세로 칸 — 위아래 반씩 나눠 **지금 횡단**과 **이전 횡단**이 앉는다. 접는 칸(345-3) — - 좁은 화면은 접힌 채 시작(`_Chrome`) · [횡단] 단추로 펴고 접는다. */ +/* 오른쪽 덮는 판 — 위아래 반씩 나눠 **지금 횡단**과 **이전 횡단**이 앉는다(352-1). 지도 위에 얹고 + 아래 종단 판(z 3)이 그 위를 덮는다. 접는 칸(345-3) — 좁은 화면은 접힌 채 시작(`_Chrome`) · + [횡단] 단추로 펴고 접는다. 빈 자리는 지도 조작을 통과. */ .b05-routeedit__side-wrap { + position: absolute; + z-index: 2; + top: var(--spacing-16); + right: var(--spacing-12); + bottom: var(--spacing-12); display: flex; - flex: none; 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 { @@ -323,21 +317,20 @@ line-height: 1.5; } -/* ㉓ 거리 재기와 되돌리기 사이 구분선. */ -.b05-routeedit__divider { - width: 1px; - height: 20px; - margin: 0 var(--spacing-4, 4px); - background: var(--color-border); -} - -/* 분석 지형 고르기(PLAN 133-1) — 라이다 있는 프로젝트만 보임. */ +/* 분석 지형 고르기(PLAN 133-1) — 라이다 있는 프로젝트만 보임 · 글에 유리 바탕(352-1). */ .b05-routeedit__terrain { display: inline-flex; align-items: center; gap: var(--spacing-4, 4px); + height: 34px; + padding: 0 var(--spacing-8); + border: 1px solid color-mix(in srgb, var(--color-border) 65%, transparent); + border-radius: var(--radius-8, 6px); + background: color-mix(in srgb, var(--color-surface-raised) 72%, transparent); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); font-size: 12px; - color: var(--color-text-muted, inherit); + color: var(--color-text-body); } .b05-routeedit__terrain[hidden] { @@ -347,7 +340,7 @@ /* ㉔ 잰 값 — 지도 오른쪽 아래 작은 창(뜬 종단 판이 덮으면 가려진 채 · 349-0). 닫으면 잰 것이 지워진다. */ .b05-routeedit__measure { position: absolute; - right: var(--spacing-12); + right: calc(var(--spacing-12) + var(--b05-side-open)); bottom: var(--spacing-12); z-index: 1; display: flex; @@ -461,11 +454,3 @@ color: var(--color-text-secondary); line-height: 1.35; } - -/* 「거리 재기」가 켜진 동안 — 단추가 눌린 꼴로 남는다(2026-09-12 사용자 지시 ⑥). - `is-active` 는 예전에도 붙고 있었으나 꼴이 없어 겉모습이 그대로였다. */ -.b05-routeedit__actions .ui-btn.is-active { - border-color: transparent; - background: var(--color-primary, #7c3aed); - color: #fff; -} diff --git a/resources/tester/test_b05_routeedit_chrome_modal.py b/resources/tester/test_b05_routeedit_chrome_modal.py index 4d1234e5d..3f16fd9ef 100644 --- a/resources/tester/test_b05_routeedit_chrome_modal.py +++ b/resources/tester/test_b05_routeedit_chrome_modal.py @@ -61,6 +61,36 @@ def test_CSS_덮개_걷음_대기막은_전체(): assert "@media (width < 1500px)" not in css # 접기는 단추로(처음만 폭으로) +def test_352_1_머리줄_상자_없음_도구는_뜬_단추_횡단은_우측_덮개(): + chrome = _read("B05_Profile_UI_RouteEdit_Chrome.ts") + for gone in ("b05-routeedit__box", "b05-routeedit__head", "b05-routeedit__actions", "

"): + assert gone not in chrome + # 도구줄 = 3D 와 같은 떠 있는 유리 단추 · 구분선도 3D 것 + assert 'class="b05-route__view-controls b05-routeedit__tools"' in chrome + assert "ui-btn--ghost" not in chrome.split(" chrome.index("b05-routeedit__busy") + css = _read("B05_Profile_UI_Style_RouteEdit.css") + for gone in (".b05-routeedit__box", ".b05-routeedit__head", ".b05-routeedit__actions"): + assert gone not in css + root = _block(css, ".b05-routeedit") + assert "padding" not in root and "gap" not in root + side = _block(css, ".b05-routeedit__side-wrap") + assert "position: absolute;" in side and "right: var(--spacing-12);" in side + z = int(re.search(r"z-index: (\d+);", side).group(1)) + assert z < 3 # 아래 종단 판(z 3)이 위 + style = _read("B05_Profile_UI_Style.css") + assert "z-index: 3;" in _block(style, ".b05-route-profile") + # 회전 단추 · 잰 값 창은 펴진 횡단 판을 비킴 + assert "var(--b05-side-top)" in _block(css, ".b05-routeedit__spin") + assert "var(--b05-side-open)" in _block(css, ".b05-routeedit__measure") + assert "is-side-open" in chrome + glass = _block(css, ".b05-routeedit__terrain") + assert "backdrop-filter: blur(6px);" in glass and "background:" in glass + + def test_페이지_수명_닫기_없음(): main = _read("B05_Profile_UI_RouteEdit.ts") assert "openModal" not in main and "Escape" not in main diff --git a/resources/tester/test_b05_routeedit_initial.py b/resources/tester/test_b05_routeedit_initial.py index ae7d1c855..7cce14368 100644 --- a/resources/tester/test_b05_routeedit_initial.py +++ b/resources/tester/test_b05_routeedit_initial.py @@ -210,9 +210,9 @@ def test_노선_추천_다듬기_23_3(): chrome = read("B05_Profile_UI_RouteEdit_Chrome.ts") # 345-4 — [노선 추천]은 좌측 칸 · 머리 구분선은 [3D](tools) 뒤 · 되돌리기 앞 둘 그대로 tools = chrome.index('data-slot="tools"') - divider = chrome.index("b05-routeedit__divider", tools) + divider = chrome.index("b05-route__view-separator", tools) # 352-1 — 3D 도구줄 구분선 그대로 assert tools < divider < chrome.index('data-act="contour-minor"') - assert chrome.count("b05-routeedit__divider") == 2 + assert chrome.count("b05-route__view-separator") == 2 shared = read("B05_Profile_UI_RouteEdit_Recommend_Map.ts") for name in ("bindRouteEditNavigation", "createMapRotation", "fitCanvas", "metricToScreen"): assert f"{name}(" in shared