From ef5a7e9771d0596d2302dc46e66c2ead0ca7a4aa Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 27 Sep 2026 18:24:34 +0900 Subject: [PATCH] =?UTF-8?q?fix(M02):=20=EC=A2=8C=EC=B8=A1=20=ED=8C=A8?= =?UTF-8?q?=EB=84=90=20=EA=B3=B5=EC=9A=A9=20=ED=8B=80=20M01=20=EA=B3=BC=20?= =?UTF-8?q?=EB=A7=9E=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ui_template_overlay.css 에 ui-sidebar-panel · ui-sidebar-card · ui-sidebar-list · ui-sidebar-row 공용 클래스 추가 - M01·M02 좌측 코드가 공용 클래스를 씀 — 카드 여백·둥글기·바탕 · 목록 간격 · 줄 선택 표시 한 벌 - M02 좌측 전용 CSS 중복 규칙 제거(없는 토큰 --radius-md 로 둥글기 안 먹던 것도 해소) - M02 표/도면/구조물 카드 처음 접힘으로 M01 과 맞춤 · 새로·본떠·지우기 단추 줄 카드 안으로 Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr --- M01_MasterData/M01_MasterData_UI_Side.ts | 17 ++++-- M01_MasterData/M01_MasterData_UI_Style.css | 54 +---------------- .../M02_MasterTemplete_UI_Side.ts | 15 +++-- .../M02_MasterTemplete_UI_Style.css | 39 +----------- ui_template/ui_template_overlay.css | 59 +++++++++++++++++++ 5 files changed, 83 insertions(+), 101 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_Side.ts b/M01_MasterData/M01_MasterData_UI_Side.ts index 4a98abae..2e31508d 100644 --- a/M01_MasterData/M01_MasterData_UI_Side.ts +++ b/M01_MasterData/M01_MasterData_UI_Side.ts @@ -173,7 +173,7 @@ export function buildSide( /** 트리 줄 — 부모는 접기/펴기 · 누를 일이 있는 줄만 밝게 */ const make: MakeRow = (node, caret, depth, onClick) => { const button = el("button", { - className: "m01-side__item", + className: "m01-side__item ui-sidebar-row", attrs: { type: "button" }, children: [ el("span", { @@ -407,7 +407,7 @@ ${first.file}` const section = (title: string, body: HTMLElement | null): HTMLElement => el("section", { - className: "m01-side__group ui-collapsible ui-sidebar-section is-collapsed", + className: "m01-side__group ui-collapsible ui-sidebar-section ui-sidebar-card is-collapsed", children: [ el("h3", { className: "ui-collapsible__title", text: title }), ...(body ? [body] : []), @@ -415,7 +415,9 @@ ${first.file}` }); const groups = GROUPS.map((group) => { - const body = LEAF.includes(group) ? null : el("div", { className: "m01-side__items" }); + const body = LEAF.includes(group) + ? null + : el("div", { className: "m01-side__items ui-sidebar-list" }); if (body) bodies.set(group, body); const root = section(L(GROUP_TITLE[group]), body); if (!body) { @@ -442,7 +444,7 @@ ${first.file}` return root; }); - const logicHost = el("div", { className: "m01-side__items" }); + const logicHost = el("div", { className: "m01-side__items ui-sidebar-list" }); const logic = section(tx("Lab_Title"), logicHost); logic.querySelector(".ui-collapsible__title")?.addEventListener("click", () => { if (!logic.classList.contains("is-collapsed")) return; // 닫을 때는 그대로 둠 @@ -450,7 +452,7 @@ ${first.file}` onLogic(); }); - const comboHost = el("div", { className: "m01-side__items" }); + const comboHost = el("div", { className: "m01-side__items ui-sidebar-list" }); const combo = section(tc("Title"), comboHost); combo.querySelector(".ui-collapsible__title")?.addEventListener("click", () => { if (!combo.classList.contains("is-collapsed")) return; @@ -458,7 +460,10 @@ ${first.file}` onCombo(); }); - const root = el("div", { className: "m01-side", children: [...groups, logic, combo] }); + const root = el("div", { + className: "m01-side ui-sidebar-panel", + children: [...groups, logic, combo], + }); attachCollapsible(root); void Promise.all(GROUPS.map(refresh)).catch((error) => showToast(error instanceof Error ? error.message : L("M01_LoadFailed"), "error"), diff --git a/M01_MasterData/M01_MasterData_UI_Style.css b/M01_MasterData/M01_MasterData_UI_Style.css index 2df3b62e..6d2983e3 100644 --- a/M01_MasterData/M01_MasterData_UI_Style.css +++ b/M01_MasterData/M01_MasterData_UI_Style.css @@ -7,25 +7,8 @@ padding-top: var(--spacing-8); } -/* 왼쪽 패널 — 공용 접기 컨테이너 여덟 */ -.m01-side { - display: flex; - flex-direction: column; - gap: var(--spacing-8); -} - -.m01-side__group { - padding: calc(var(--spacing-8) + var(--spacing-4)); - border-radius: var(--radius-cards); - background: var(--color-surface-raised); -} - -.m01-side__group > h3 { - margin: 0; - color: var(--color-text); - font-size: var(--text-body-sm); -} - +/* 왼쪽 패널 카드·목록·줄 모양은 공용 ui-sidebar-*(ui_template_overlay.css) — 여기는 + M01 전용(환율·요율처럼 하위 목록 없는 leaf 그룹) 만. */ .m01-side__leaf > h3::after { display: none; } @@ -34,39 +17,6 @@ color: var(--color-accent); } -.m01-side__items { - display: flex; - flex-direction: column; - gap: 2px; - max-height: 50vh; - margin-top: var(--spacing-8); - overflow: auto; -} - -.m01-side__item { - display: flex; - justify-content: space-between; - gap: var(--spacing-8); - padding: var(--spacing-4) var(--spacing-8); - border: 0; - border-radius: var(--radius-buttons); - background: transparent; - color: var(--color-text-body); - font: inherit; - font-size: var(--text-body-sm); - text-align: left; - cursor: pointer; -} - -.m01-side__item:hover { - background: var(--color-paper); -} - -.m01-side__item.is-active { - background: var(--color-mist-violet); - color: var(--color-accent); -} - .m01-tree__kids { display: flex; flex-direction: column; diff --git a/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts b/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts index 4150ba47..da78df92 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts @@ -79,17 +79,17 @@ export function buildSide(opt: SideOptions): SideHandle { const section = (title: string, body: HTMLElement, ...more: HTMLElement[]): HTMLElement => el("section", { - className: "m02-side__group ui-collapsible ui-sidebar-section", + className: "m02-side__group ui-collapsible ui-sidebar-section ui-sidebar-card is-collapsed", children: [el("h3", { className: "ui-collapsible__title", text: title }), body, ...more], }); const bodies = new Map( [...KINDS.map((k) => k.kind), STRUCTURE].map((k) => [ k, - el("div", { className: "m02-side__items" }), + el("div", { className: "m02-side__items ui-sidebar-list" }), ]), ); const listHost = el("div", { - className: "m02-side__lists", + className: "m02-side__lists ui-sidebar-panel", children: [ section(L("M02_KindTable"), bodies.get("table")!), section( @@ -104,9 +104,12 @@ export function buildSide(opt: SideOptions): SideHandle { const btnNew = createButton({ label: L("M02_New"), variant: "filled" }); const btnCopy = createButton({ label: L("M02_Copy"), variant: "ghost" }); const btnDel = createButton({ label: L("M02_Delete"), variant: "danger" }); - const editRow = el("div", { className: "m02-side__row", children: [btnNew, btnCopy, btnDel] }); + const editRow = el("div", { + className: "m02-side__row ui-sidebar-card", + children: [btnNew, btnCopy, btnDel], + }); - const root = el("div", { className: "m02-side", children: [listHost, editRow] }); + const root = el("div", { className: "m02-side ui-sidebar-panel", children: [listHost, editRow] }); const isOpen = (info: TemplateInfo): boolean => { if (picked) return picked.kind === info.종류 && picked.name === info.이름; @@ -126,7 +129,7 @@ export function buildSide(opt: SideOptions): SideHandle { ...(mine.length ? mine.map((info) => { const b = el("button", { - className: `m02-side__item${isOpen(info) ? " is-active" : ""}`, + className: `m02-side__item ui-sidebar-row${isOpen(info) ? " is-active" : ""}`, text: info.이름, attrs: { type: "button", title: info.수정일 }, }); diff --git a/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css b/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css index b3c80cb2..cfaaab1f 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css +++ b/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css @@ -1,44 +1,9 @@ -/* M02 마스터 템플릿 — 좌측 패널 + 메인. 색·간격은 공용 토큰. */ +/* M02 마스터 템플릿 — 좌측 패널 + 메인. 카드·목록·줄 모양은 공용 ui-sidebar-* + (ui_template_overlay.css, M01 과 한 벌) — 여기는 패널 위 여백만. */ .m02-side { - display: flex; - flex-direction: column; - gap: var(--spacing-12); padding-top: var(--spacing-8); } -.m02-side__group { - display: flex; - flex-direction: column; - gap: var(--spacing-4); -} - -.m02-side__items { - display: flex; - flex-direction: column; - gap: var(--spacing-4); -} - -.m02-side__item { - width: 100%; - padding: var(--spacing-4) var(--spacing-8); - border: 0; - border-radius: var(--radius-md); - background: none; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; -} - -.m02-side__item:hover { - background: var(--color-paper); -} - -.m02-side__item.is-active { - background: color-mix(in srgb, var(--color-accent) 14%, transparent); - font-weight: var(--font-weight-bold); -} - .m02-side__empty { margin: 0; color: var(--color-text-muted); diff --git a/ui_template/ui_template_overlay.css b/ui_template/ui_template_overlay.css index 236f5941..f7e5c05b 100644 --- a/ui_template/ui_template_overlay.css +++ b/ui_template/ui_template_overlay.css @@ -364,3 +364,62 @@ border-style: solid; border-color: color-mix(in srgb, var(--color-border) 25%, var(--color-text-secondary)); } + +/* 좌측 패널 공용 틀(M01·M02 공용) — 접기 카드 모양 · 목록 · 줄 · 고름 표시. + 전체를 감싸는 패널 간격은 .ui-sidebar-panel, 카드 하나는 .ui-sidebar-card, + 그 안 목록은 .ui-sidebar-list, 줄은 .ui-sidebar-row(선택 시 is-active). */ +.ui-sidebar-panel { + display: flex; + flex-direction: column; + gap: var(--spacing-8); +} + +.ui-sidebar-card { + padding: calc(var(--spacing-8) + var(--spacing-4)); + border-radius: var(--radius-cards); + background: var(--color-surface-raised); +} + +.ui-sidebar-card > .ui-collapsible__title { + margin: 0; + color: var(--color-text); + font-size: var(--text-body-sm); +} + +/* 카드 안에 다시 카드(M02 도면 안 구조물 도면 묶음) — 앞 목록과 간격 */ +.ui-sidebar-card .ui-sidebar-card { + margin-top: var(--spacing-8); +} + +.ui-sidebar-list { + display: flex; + flex-direction: column; + gap: 2px; + max-height: 50vh; + margin-top: var(--spacing-8); + overflow: auto; +} + +.ui-sidebar-row { + display: flex; + justify-content: space-between; + gap: var(--spacing-8); + padding: var(--spacing-4) var(--spacing-8); + border: 0; + border-radius: var(--radius-buttons); + background: transparent; + color: var(--color-text-body); + font: inherit; + font-size: var(--text-body-sm); + text-align: left; + cursor: pointer; +} + +.ui-sidebar-row:hover { + background: var(--color-paper); +} + +.ui-sidebar-row.is-active { + background: var(--color-mist-violet); + color: var(--color-accent); +}