diff --git a/ui_template/ui_template_overlay.css b/ui_template/ui_template_overlay.css index f95397ff..236f5941 100644 --- a/ui_template/ui_template_overlay.css +++ b/ui_template/ui_template_overlay.css @@ -81,6 +81,16 @@ } } +/* ⚠ 아주 좁은 폭(≤560)에서는 **줄이지 않는다** — 본문 320 을 남기려다 패널이 180px + 까지 눌려 목록 이름이 잘렸다(2026-09-08 랩탑 보조 실측: 폭 500 에서 잘린 이름 2건). + 폭을 반씩 나누면 **둘 다 못 쓰는 화면**이 되므로, 패널은 쓸 만한 폭을 지키고 + **본문 위에 겹쳐** 뜬다(본문 밀기는 이미 ≤860 에서 꺼져 있다). 읽을 때는 손잡이로 접는다. */ +@media (max-width: 560px) { + .ui-workflow-overlay__panel--title { + width: min(var(--wf-left-panel-narrow-width), calc(100vw - var(--spacing-48))); + } +} + .ui-workflow-overlay__panel--progress .ui-workflow-overlay__header { cursor: move; touch-action: none; diff --git a/ui_template/ui_template_overlay.ts b/ui_template/ui_template_overlay.ts index 3fe0881b..9d1dfccc 100644 --- a/ui_template/ui_template_overlay.ts +++ b/ui_template/ui_template_overlay.ts @@ -84,8 +84,21 @@ export function createWorkflowPanelHandle( return { root, setOpen }; } -function readOpenState(key: string): boolean { - return readByKey(key) !== "false"; +/** 좌측 패널을 **접은 채로 시작**하는 폭 — `ui_template_overlay.css` 의 560 과 짝이다. */ +const NARROW_START_COLLAPSED_MAX_PX = 560; + +/** + * 처음 열 때 펼쳐 둘지. + * + * ⚠ **사용자가 정한 적이 있으면 그 뜻이 이긴다** — 저장값이 있으면 그대로 따른다. + * 정한 적이 없고 화면이 아주 좁으면 **접은 채로 시작**한다. 그 폭에서는 패널이 본문 + * 위에 겹쳐 떠서, 펼친 채로 열면 본문이 가려진 화면부터 보게 된다(2026-09-08). + */ +function readOpenState(key: string, collapseWhenNarrow = false): boolean { + const raw = readByKey(key); + if (raw !== null) return raw !== "false"; + if (!collapseWhenNarrow) return true; + return window.innerWidth > NARROW_START_COLLAPSED_MAX_PX; } /** @@ -183,7 +196,7 @@ function createPanel( let dragHandle: { refresh: () => void } | null = null; - function setOpen(isOpen: boolean): void { + function setOpen(isOpen: boolean, persist = true): void { root.classList.toggle("is-collapsed", !isOpen); if (panelHandle) panelHandle.setOpen(isOpen); else { @@ -192,7 +205,9 @@ function createPanel( toggle.setAttribute("aria-label", toggle.title); toggle.setAttribute("aria-expanded", String(isOpen)); } - writeByKey(storageKey, String(isOpen)); + // ⚠ 처음 앉힐 때는 저장하지 않는다 — 좁아서 접어 둔 것을 「사용자가 접었다」로 + // 적으면 넓은 화면으로 돌아와도 접힌 채로 남는다. + if (persist) writeByKey(storageKey, String(isOpen)); // 펼친 뒤에는 아래 공간이 모자랄 수 있다 — 열리는 방향을 다시 잡는다. if (dragHandle) requestAnimationFrame(() => dragHandle?.refresh()); onOpenChange?.(isOpen); @@ -212,7 +227,7 @@ function createPanel( } }); toggle.addEventListener("click", toggleOpen); - setOpen(readOpenState(storageKey)); + setOpen(readOpenState(storageKey, isSidebar), false); // 진행단계 패널만 사용자가 자리를 옮긴다(제목 패널은 좌측 도킹 사이드바). if (variant === "progress") { dragHandle = makePanelDraggable(root, header, PROGRESS_OVERLAY_POSITION_KEY);