From bb6ae4faf5653daf00582676577e26b71cf5c5e5 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 12 Oct 2026 18:58:56 +0900 Subject: [PATCH] =?UTF-8?q?fix(b08,b09):=20=EB=B3=B4=EC=A1=B0=20=ED=83=AD?= =?UTF-8?q?=20=EB=8B=A8=EC=B6=94=20=EB=86=92=EC=9D=B4=20=ED=95=9C=20?= =?UTF-8?q?=EA=BC=B4=20=E2=80=94=20=EA=B3=B5=EC=9A=A9=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=2024px=20=C2=B7=20=EA=B3=B5=EC=9A=A9=20=EB=B3=B4=EC=A1=B0=20?= =?UTF-8?q?=ED=83=AD=20=EC=A4=84=20=EC=96=91=EC=8B=9D=20=C2=B7=20=EB=8F=84?= =?UTF-8?q?=EA=B5=AC=EB=8A=94=20=EC=A4=84=20=EB=86=92=EC=9D=B4=20=EC=95=88?= =?UTF-8?q?=20=EB=B0=94=EA=BF=88=20(279)?= 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_01Ji4nuyLVHcxrXWHTdb5nRD --- B08_Quantity/B08_Quantity_UI_Earthwork.ts | 2 +- B08_Quantity/B08_Quantity_UI_Hydro.ts | 2 +- B08_Quantity/B08_Quantity_UI_Milestone.ts | 2 +- B08_Quantity/B08_Quantity_UI_Page.ts | 4 +- B09_Estimation/B09_Estimation_UI_TabBar.ts | 4 +- resources/tester/test_170_b08_modal_head.py | 2 +- resources/tester/test_279_1_subtab_height.py | 62 ++++++++++++++++++++ ui_template/ui_template_general_layout.css | 15 +++++ ui_template/ui_template_theme.css | 2 + 9 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 resources/tester/test_279_1_subtab_height.py diff --git a/B08_Quantity/B08_Quantity_UI_Earthwork.ts b/B08_Quantity/B08_Quantity_UI_Earthwork.ts index ac64372d5..c29233cc3 100644 --- a/B08_Quantity/B08_Quantity_UI_Earthwork.ts +++ b/B08_Quantity/B08_Quantity_UI_Earthwork.ts @@ -287,7 +287,7 @@ export async function renderEarthwork(host: HTMLElement, projectId: string): Pro applyRock(); const tabs = document.createElement("div"); - tabs.className = "b08-quantity__tabs b08-earthwork__tabs"; + tabs.className = "b08-quantity__tabs ui-subtabs b08-earthwork__tabs"; tabs.setAttribute("role", "tablist"); const view = document.createElement("div"); let current: SheetId = "summary"; diff --git a/B08_Quantity/B08_Quantity_UI_Hydro.ts b/B08_Quantity/B08_Quantity_UI_Hydro.ts index 5056c993a..e33d2009b 100644 --- a/B08_Quantity/B08_Quantity_UI_Hydro.ts +++ b/B08_Quantity/B08_Quantity_UI_Hydro.ts @@ -110,7 +110,7 @@ export async function renderHydro(host: HTMLElement, projectId: string): Promise ) as unknown as HydroInputs; const tabs = document.createElement("div"); - tabs.className = "b08-quantity__tabs b08-hydro__tabs"; + tabs.className = "b08-quantity__tabs ui-subtabs b08-hydro__tabs"; tabs.setAttribute("role", "tablist"); const save = createButton({ label: "저장", diff --git a/B08_Quantity/B08_Quantity_UI_Milestone.ts b/B08_Quantity/B08_Quantity_UI_Milestone.ts index 817f0bd4c..09a8f979d 100644 --- a/B08_Quantity/B08_Quantity_UI_Milestone.ts +++ b/B08_Quantity/B08_Quantity_UI_Milestone.ts @@ -213,7 +213,7 @@ function tableView(projectId: string): MilestoneView { export function renderMilestone(host: HTMLElement, projectId: string): void { const tabs = el("div", { - className: "b08-quantity__tabs b08-structure__tabs", + className: "b08-quantity__tabs ui-subtabs b08-structure__tabs", attrs: { role: "tablist" }, }); const view = el("div"); diff --git a/B08_Quantity/B08_Quantity_UI_Page.ts b/B08_Quantity/B08_Quantity_UI_Page.ts index 385aebf8c..2a8ed9154 100644 --- a/B08_Quantity/B08_Quantity_UI_Page.ts +++ b/B08_Quantity/B08_Quantity_UI_Page.ts @@ -57,7 +57,7 @@ function pendingNote(): HTMLElement { /** 자재 탭 — 보조 탭 줄 + 몸통(보조 탭마다 새 몸통 · 늦은 응답이 다른 보조 탭을 덮지 않게). */ function renderMaterials(host: HTMLElement, projectId: string | null): void { const tabs = document.createElement("div"); - tabs.className = "b08-quantity__tabs b08-structure__tabs"; + tabs.className = "b08-quantity__tabs ui-subtabs b08-structure__tabs"; tabs.setAttribute("role", "tablist"); const view = document.createElement("div"); const select = (picked: SheetId): void => { @@ -92,7 +92,7 @@ function renderTab(host: HTMLElement, tab: TabId, projectId: string | null): voi if (tab === "summary" && projectId) { // 보조 탭 줄 자리(170-4) — 보이지 않는 sm 단추 한 줄 · 자재 탭과 같은 높이라 탭 바꿀 때 안 튐 const blank = document.createElement("div"); - blank.className = "b08-quantity__tabs b08-quantity__tabs--blank"; + blank.className = "b08-quantity__tabs ui-subtabs b08-quantity__tabs--blank"; blank.setAttribute("aria-hidden", "true"); const ghost = createButton({ label: L(SHEETS[0].label), variant: "ghost", size: "sm" }); ghost.tabIndex = -1; diff --git a/B09_Estimation/B09_Estimation_UI_TabBar.ts b/B09_Estimation/B09_Estimation_UI_TabBar.ts index 3ce0e2a2f..183fc5f76 100644 --- a/B09_Estimation/B09_Estimation_UI_TabBar.ts +++ b/B09_Estimation/B09_Estimation_UI_TabBar.ts @@ -37,9 +37,9 @@ export function createTabBars(onPick: (tab: TabId) => void): TabBars { top.className = "b09-estimation__tabs"; top.setAttribute("role", "tablist"); const sub = document.createElement("div"); - sub.className = "b09-estimation__tabs"; + sub.className = "b09-estimation__tabs ui-subtabs"; const tools = document.createElement("div"); - tools.className = "b09-estimation__tools"; + tools.className = "b09-estimation__tools ui-subtabs__tools"; const lastSeen = new Map(); const draw = (tab: TabId): void => { diff --git a/resources/tester/test_170_b08_modal_head.py b/resources/tester/test_170_b08_modal_head.py index df73e7398..ddde235dc 100644 --- a/resources/tester/test_170_b08_modal_head.py +++ b/resources/tester/test_170_b08_modal_head.py @@ -14,7 +14,7 @@ PAGE_CSS = (ROOT / "B08_Quantity/B08_Quantity_UI_Page.css").read_text(encoding=" def test_170_4_집계표_보조_탭_줄_자리(): branch = PAGE.split('if (tab === "summary" && projectId) {', 1)[1].split("\n }", 1)[0] # 자재 탭 보조 탭 줄과 같은 클래스 · sm 단추 하나(보이지 않음 · 초점 안 감) - assert '"b08-quantity__tabs b08-quantity__tabs--blank"' in branch + assert '"b08-quantity__tabs ui-subtabs b08-quantity__tabs--blank"' in branch # 279 공용 양식 assert 'size: "sm"' in branch and "ghost.tabIndex = -1" in branch assert 'setAttribute("aria-hidden", "true")' in branch # 집계표는 줄 아래 몸통에 그림(replaceChildren 이 빈 줄을 지우지 않게) diff --git a/resources/tester/test_279_1_subtab_height.py b/resources/tester/test_279_1_subtab_height.py new file mode 100644 index 000000000..b336ee1b9 --- /dev/null +++ b/resources/tester/test_279_1_subtab_height.py @@ -0,0 +1,62 @@ +"""279 B08 · B09 보조 탭 단추 높이 한 꼴. + +- 테마 토큰 `--subtab-height` = 24px(B09 단가산출근거 박스보기 때 잰 값) +- 공용 양식 `.ui-subtabs`(가운데 맞춤 · 단추 높이 = 토큰) · `.ui-subtabs__tools`(높이 = 토큰 · 줄 높이 안 바꿈) +- B09 아래 줄 · 도구 · B08 보조 탭 줄 모두(빈 줄 자리 포함)가 씀 · 위 탭 줄은 안 씀 +- `ui-btn--sm` 전체는 그대로 +""" + +import re +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] + + +def _read(rel: str) -> str: + return (ROOT / rel).read_text(encoding="utf-8") + + +def _block(css: str, selector: str) -> str: + m = re.search(re.escape(selector) + r"\s*\{([^}]*)\}", css) + assert m, selector + return m.group(1) + + +def test_token_is_box_view_height(): + theme = _read("ui_template/ui_template_theme.css") + assert re.search(r"--subtab-height:\s*24px;", theme) + + +def test_shared_class_centers_and_fixes_height(): + css = _read("ui_template/ui_template_general_layout.css") + assert "align-items: center" in _block(css, ".ui-subtabs") + assert "height: var(--subtab-height)" in _block(css, ".ui-subtabs > .ui-btn") + tools = _block(css, ".ui-subtabs__tools") + assert "align-items: center" in tools + assert "height: var(--subtab-height)" in tools + + +def test_sm_button_untouched(): + styles = _read("ui_template/ui_template_elements_styles.ts") + assert "height" not in _block(styles, ".ui-btn--sm") + + +def test_b09_sub_row_and_tools_use_shared_class(): + bar = _read("B09_Estimation/B09_Estimation_UI_TabBar.ts") + assert 'sub.className = "b09-estimation__tabs ui-subtabs"' in bar + assert 'tools.className = "b09-estimation__tools ui-subtabs__tools"' in bar + assert 'top.className = "b09-estimation__tabs"' in bar # 위 탭은 그대로 + + +def test_b08_sub_rows_use_shared_class(): + sub_rows = { + "B08_Quantity/B08_Quantity_UI_Page.ts": 2, # 자재 보조 탭 · 구조물 집계표 빈 줄 자리 + "B08_Quantity/B08_Quantity_UI_Earthwork.ts": 1, + "B08_Quantity/B08_Quantity_UI_Hydro.ts": 1, + "B08_Quantity/B08_Quantity_UI_Milestone.ts": 1, + } + for rel, n in sub_rows.items(): + src = _read(rel) + assert src.count('"b08-quantity__tabs ui-subtabs') == n, rel + page = _read("B08_Quantity/B08_Quantity_UI_Page.ts") + assert 'tabBar.className = "b08-quantity__tabs";' in page # 위 탭은 그대로 diff --git a/ui_template/ui_template_general_layout.css b/ui_template/ui_template_general_layout.css index cc8b2cd0c..cf4605f71 100644 --- a/ui_template/ui_template_general_layout.css +++ b/ui_template/ui_template_general_layout.css @@ -55,6 +55,21 @@ gap: var(--btn-group-gap); } +/* 보조 탭 줄(B08 · B09) — 단추 높이 = `--subtab-height` · 줄 안 도구는 가운데 맞춤 · 줄 높이를 바꾸지 않음 */ +.ui-subtabs { + align-items: center; +} + +.ui-subtabs > .ui-btn { + height: var(--subtab-height); +} + +.ui-subtabs__tools { + display: flex; + align-items: center; + height: var(--subtab-height); +} + .ui-general-block__table-wrap { overflow-x: auto; } diff --git a/ui_template/ui_template_theme.css b/ui_template/ui_template_theme.css index 83ad0782c..3e4bc4590 100644 --- a/ui_template/ui_template_theme.css +++ b/ui_template/ui_template_theme.css @@ -168,6 +168,8 @@ /* 줄 위 작은 단추 한 규격 — 종단 머리 줄 [초기화]~▼ · [배수유역도] · [새 창] 이 함께 씀(높이 = 글자 12 + 여백 2 + 테두리 2) */ --btn-bar-padding: 1px var(--spacing-8); --btn-bar-font-size: var(--text-caption); + /* 보조 탭 단추 높이 — B08 · B09 보조 탭 줄(.ui-subtabs) 한 꼴 */ + --subtab-height: 24px; /* --------------------------------------------------------------------------- * 6. 그림자 (Shadows) — 블루틴트, 서브틀 (최대 32px blur / 6% opacity)