fix(M01): 로직 상세 오른쪽 두 패널 공용 접기 카드로 — 제목 행 누름 · 캐럿 · 하나만 열림
- 흐름도 · 원문 = ui-collapsible 카드(M02 면적산출 오른쪽 패널 꼴) · attachCollapsible 토글 위에 하나만 열림 규칙 - 따로 만든 원문 토글 단추 · 얇은 띠 제거 · 흐름도 패널 자체 접기 단추는 M01 에서 숨김 - 둘 다 접힘 = 제목 행 둘(칸 140px) · 취향 기억(m01-logic-panel) 그대로 - 44-4 화면 시험 카드 꼴로 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NPJGtfXo6GMbcpiboQC4uK
This commit is contained in:
@@ -1,22 +1,28 @@
|
||||
/* 로직 상세 오른쪽 두 패널 — 흐름도 · 원문 · 접힌 패널은 얇은 띠 */
|
||||
/* 로직 상세 오른쪽 두 패널 — 흐름도 · 원문 · 공용 접기 카드(접힌 카드 = 제목 행) */
|
||||
.m01lab-side {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.m01lab-side__card,
|
||||
.m01lab-side__slot {
|
||||
flex: 0 0 40px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.m01lab-side__slot.is-open {
|
||||
flex: 1 1 auto;
|
||||
/* 카드 제목 행이 접기 단추 — 흐름도 패널 자체 접기 단추 · 테두리는 뺌 */
|
||||
.m01lab-side .m02-dfp__toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 접힌 흐름도 자리 — 띠만(기다림 글 · 변환 알림은 숨김) */
|
||||
.m01lab-side__slot:not(.is-open) > :not(.m01lab-flow__panel, .m01lab-src) {
|
||||
display: none;
|
||||
.m01lab-side .m02-dfp {
|
||||
border-left: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.m01lab-src {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-8);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.m01lab-src__body {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/* =============================================================================
|
||||
* M01_MasterData_UI_LogicLab_Side.ts
|
||||
* 로직 상세 오른쪽 두 패널 — 「흐름도」(다이어그램 · 상세 내용 = M02_DF_Panel) · 「원문」(품셈 본문 절)
|
||||
* 둘 중 하나만 열림(하나 열면 다른 하나 접힘) · 둘 다 접기 됨 · 접힌 패널 = 얇은 띠(머리 단추 그대로)
|
||||
* 공용 접기 카드(`ui-collapsible` · 제목 행 누름 · 캐럿) 두 장 — attachCollapsible 토글 위에 하나만 열림 규칙
|
||||
* 둘 다 접기 됨 · 접힌 카드 = 제목 행만
|
||||
* 열린 패널은 계정 취향(`m01-logic-panel`)으로 기억 · 원문은 출처 글로 서버가 찾음(`GET /m01/logic/source`)
|
||||
* ========================================================================== */
|
||||
|
||||
import { currentLanguageIndex } from "@ui/ui_template_locale";
|
||||
import { createButton, el } from "@ui/ui_template_elements";
|
||||
import { attachCollapsible } from "@ui/ui_template_collapsible";
|
||||
import { el } from "@ui/ui_template_elements";
|
||||
import { API_BASE_URL } from "@config/config_frontend";
|
||||
import { readStateRaw, writeStateRaw } from "../A00_Common/b_page_state";
|
||||
import type { SplitHandle } from "./M01_MasterData_UI_LogicLab_Flow";
|
||||
@@ -14,9 +16,8 @@ import "../M02_MasterTemplete/DataFlow/M02_DF_Panel.css";
|
||||
import "./M01_MasterData_UI_LogicLab_Side.css";
|
||||
|
||||
const TEXT = {
|
||||
Toggle: ["원문", "Source"],
|
||||
Open: ["원문 펴기", "Open the source panel"],
|
||||
Close: ["원문 접기", "Collapse the source panel"],
|
||||
Flow: ["흐름도", "Flow"],
|
||||
Source: ["원문", "Source"],
|
||||
Loading: ["원문 찾는 중", "Looking up the source"],
|
||||
None: ["원문 연결 없음", "No linked source"],
|
||||
From: ["출처", "Source"],
|
||||
@@ -27,8 +28,8 @@ const TEXT = {
|
||||
const ts = (key: keyof typeof TEXT, v = ""): string =>
|
||||
TEXT[key][currentLanguageIndex === 1 ? 1 : 0].replace("{v}", v);
|
||||
|
||||
/** 접힌 띠 너비 — M02_DF_Panel 의 STRIP_WIDTH 와 같음(패널 모듈은 늦게 받으므로 따로 둠) */
|
||||
const STRIP = 40;
|
||||
/** 둘 다 접힘 — 제목 행 둘이 들어가는 칸 너비 */
|
||||
const FOLDED = 140;
|
||||
|
||||
export type PanelPick = "flow" | "source" | "none";
|
||||
|
||||
@@ -86,21 +87,28 @@ export function buildLogicSide(split: SplitHandle): LogicSide {
|
||||
const flowSlot = el("div", { className: "m01lab-side__slot" });
|
||||
const body = el("div", { className: "m01lab-src__body" });
|
||||
const title = el("strong", { className: "m02-dfp__title" });
|
||||
const toggle = createButton({
|
||||
label: ts("Toggle"),
|
||||
size: "sm",
|
||||
variant: "ghost",
|
||||
onClick: () => pick(now === "source" ? "none" : "source"),
|
||||
});
|
||||
toggle.classList.add("m02-dfp__toggle");
|
||||
const head = el("header", { className: "m02-dfp__head", children: [toggle, title] });
|
||||
const open = el("div", { className: "m02-dfp__open", children: [head, body] });
|
||||
const strip = el("div", { className: "m02-dfp__strip" });
|
||||
const source = el("aside", { className: "m02-dfp m01lab-src", children: [open, strip] });
|
||||
const sourceSlot = el("div", { className: "m01lab-side__slot", children: [source] });
|
||||
split.right.replaceChildren(
|
||||
el("div", { className: "m01lab-side", children: [flowSlot, sourceSlot] }),
|
||||
const card = (label: string, inner: HTMLElement): HTMLElement =>
|
||||
el("section", {
|
||||
className: "m01lab-side__card ui-collapsible ui-sidebar-section ui-sidebar-card",
|
||||
children: [el("h3", { className: "ui-collapsible__title", text: label }), inner],
|
||||
});
|
||||
const flowCard = card(ts("Flow"), flowSlot);
|
||||
const sourceCard = card(
|
||||
ts("Source"),
|
||||
el("div", { className: "m01lab-src", children: [title, body] }),
|
||||
);
|
||||
const side = el("div", {
|
||||
className: "m01lab-side ui-sidebar-panel",
|
||||
children: [flowCard, sourceCard],
|
||||
});
|
||||
attachCollapsible(side);
|
||||
// 공용 토글 뒤 — 연 카드만 남기고 다른 카드는 접음(접었으면 둘 다 닫힘)
|
||||
side.addEventListener("click", (ev) => {
|
||||
const at = (ev.target as HTMLElement).closest(".ui-collapsible__title")?.parentElement;
|
||||
if (at !== flowCard && at !== sourceCard) return;
|
||||
pick(at.classList.contains("is-collapsed") ? "none" : at === flowCard ? "flow" : "source");
|
||||
});
|
||||
split.right.replaceChildren(side);
|
||||
|
||||
let now = readPick();
|
||||
let flowPx: number | null = null;
|
||||
@@ -108,14 +116,22 @@ export function buildLogicSide(split: SplitHandle): LogicSide {
|
||||
let want = "";
|
||||
let shown: string | null = null;
|
||||
|
||||
/** 칸 너비 — 원문(또는 흐름도가 아직 안 뜸) = 두 칸 비율 · 흐름도 = 패널 너비 + 띠 · 둘 다 접힘 = 띠 둘 */
|
||||
/** 카드 안팎 여백(좌우 안쪽 + 테두리) — 흐름도 패널 너비에 더함 */
|
||||
const pad = (): number => {
|
||||
const s = getComputedStyle(flowCard);
|
||||
return ["paddingLeft", "paddingRight", "borderLeftWidth", "borderRightWidth"].reduce(
|
||||
(n, k) => n + (parseFloat(s[k as "paddingLeft"]) || 0),
|
||||
0,
|
||||
);
|
||||
};
|
||||
/** 칸 너비 — 원문(또는 흐름도가 아직 안 뜸) = 두 칸 비율 · 흐름도 = 패널 너비 + 카드 여백 · 둘 다 접힘 = 제목 행 */
|
||||
const width = (): void =>
|
||||
split.setRight(
|
||||
now === "source" || (now === "flow" && flowPx === null)
|
||||
? null
|
||||
: now === "flow"
|
||||
? (flowPx ?? 0) + STRIP
|
||||
: STRIP * 2,
|
||||
? (flowPx ?? 0) + pad()
|
||||
: FOLDED,
|
||||
);
|
||||
|
||||
const load = (): void => {
|
||||
@@ -149,21 +165,12 @@ export function buildLogicSide(split: SplitHandle): LogicSide {
|
||||
});
|
||||
};
|
||||
|
||||
const fold = (on: boolean): void => {
|
||||
open.hidden = on;
|
||||
strip.hidden = !on;
|
||||
(on ? strip : head).prepend(toggle);
|
||||
toggle.setAttribute("aria-expanded", String(!on));
|
||||
toggle.title = ts(on ? "Open" : "Close");
|
||||
};
|
||||
|
||||
const pick = (next: PanelPick): void => {
|
||||
if (next !== now) writeStateRaw("m01-logic-panel", next);
|
||||
now = next;
|
||||
flowFold?.(now !== "flow"); // 칸을 줄이기 전에 — 흐름도 패널이 접기 전 너비를 재어 둠
|
||||
flowSlot.classList.toggle("is-open", now === "flow");
|
||||
sourceSlot.classList.toggle("is-open", now === "source");
|
||||
fold(now !== "source");
|
||||
flowCard.classList.toggle("is-collapsed", now !== "flow");
|
||||
sourceCard.classList.toggle("is-collapsed", now !== "source");
|
||||
width();
|
||||
load();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user