feat(B05): 구조물 목록을 사이드 하단 고정 영역으로 이동

선택한 구조물의 폼 길이에 밀려 「구조물 배치」 섹션 아래 목록이 화면 밖으로
나가던 문제. 목록(<ul>)을 섹션 본문에서 빼 StructuresSection.listRoot로 노출하고,
패널이 하단 고정 영역(b05-route__dock)에 배치한다.

배치 순서: 상단 구분선(dock border-top) → 구조물 목록 → 중간 구분선 →
[초기화][임시저장][횡단 이동].

- 공용 ui-sidebar-actions(sticky·배경·상단선)는 그대로 쓰고, 안쪽만 세로 배치로
  되돌리는 .b05-route__dock 규칙 추가(공용 규칙보다 좁은 선택자로 로드 순서 무관).
- 선택·폼 로드·스크롤 동작은 그대로 — DOM 부모만 바뀌었다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-18 17:06:06 +09:00
co-authored by Claude Opus 5
parent fdd9c77cb3
commit 7753c53522
3 changed files with 31 additions and 12 deletions
+11 -3
View File
@@ -387,10 +387,18 @@ export function createRoutePanel(callbacks: PanelCallbacks) {
const tempSaveButton = button(L("B05_Route_Btn_TempSave"), callbacks.onTempSave);
const goCrossButton = button(L("B05_Route_Btn_GoCross"), callbacks.onGoCross, "filled");
const actionRow = document.createElement("div");
// 사이드 최하단 고정(공용 ui-sidebar-actions) — 스크롤에서 제외(2026-08-05 사용자 지시).
actionRow.className = "b05-route__actions ui-sidebar-actions";
actionRow.className = "b05-route__actions";
actionRow.append(resetButton, tempSaveButton, goCrossButton);
// 사이드 최하단 고정 영역(2026-08-05 사용자 지시) — 위 구분선(dock 상단 테두리) →
// 구조물 목록 → 중간 구분선 → 액션 버튼 순. 목록을 「구조물 배치」 본문에 두면
// 고른 구조물의 폼 길이에 밀려 화면 밖으로 나갔다(2026-08-18 사용자 지시).
const dockDivider = document.createElement("hr");
dockDivider.className = "b05-structure__divider";
const actionDock = document.createElement("div");
actionDock.className = "b05-route__dock ui-sidebar-actions";
actionDock.append(structures.listRoot, dockDivider, actionRow);
const inputElements = [
algorithm,
gradeClass,
@@ -419,7 +427,7 @@ export function createRoutePanel(callbacks: PanelCallbacks) {
structures.root,
routeCalc.root,
selected.root,
actionRow,
actionDock,
);
// 컨테이너 제목 행 전체 클릭 시 본문을 접거나 편다(공용 collapsible). 내부 details 등 별도
@@ -60,6 +60,9 @@ export interface PipeFacilityItem {
export interface StructuresSection {
root: HTMLElement;
/** 배치된 구조물 목록(<ul>) — 섹션 본문이 아니라 사이드 하단 고정 영역에 붙인다
* (2026-08-18 사용자 지시: 폼 길이에 밀려 목록이 화면 밖으로 나가던 문제). */
listRoot: HTMLElement;
/** 서버에서 받은 타입 목록을 채운다(최초 1회). */
setTypes: (types: StructureType[]) => void;
/** 서버 정본으로 목록을 교체한다(진입·복원·저장 후). */
@@ -165,6 +168,8 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
actions.className = "b05-route__irregular-actions";
actions.append(primary, removeButton, resetButton);
// 목록은 이 섹션 본문에 붙이지 않는다 — 폼이 길어지면 스크롤 밖으로 밀려 안 보였다.
// 패널(B05_Profile_UI_Panel)이 하단 고정 영역에 배치한다(2026-08-18 사용자 지시).
const list = document.createElement("ul");
list.className = "b05-route__irregular-list";
// 사용법 설명 문단은 두지 않는다 — 공간 대비 의미 없음(2026-08-17 사용자 지시,
@@ -174,15 +179,7 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
const positionDivider = document.createElement("hr");
positionDivider.className = "b05-structure__divider";
body.append(
typeRow,
positionRow,
positionDivider,
optionRow,
facilityOptions.root,
actions,
list,
);
body.append(typeRow, positionRow, positionDivider, optionRow, facilityOptions.root, actions);
let types: StructureType[] = [];
let structures: StructureInstance[] = [];
@@ -529,6 +526,7 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
return {
root,
listRoot: list,
setTypes(next) {
types = next;
const groups = [...new Set(next.map((t) => t.group))];
+13
View File
@@ -413,6 +413,19 @@
color: var(--color-warning);
}
/* 사이드 최하단 고정 영역 — 공용 ui-sidebar-actions(sticky·배경·상단 구분선)를 그대로
쓰되, 안쪽은 [구조물 목록][중간 구분선][액션 버튼 행] 세로 배치로 되돌린다
(2026-08-18 사용자 지시). */
.b05-route__dock.ui-sidebar-actions {
flex-direction: column;
}
/* 공용 규칙(.ui-sidebar-actions > * { flex: 1 })이 목록·구분선까지 늘리지 않도록
같은 자리에서 되돌린다 — 로드 순서에 기대지 않게 선택자를 한 단계 더 좁혔다. */
.b05-route__dock.ui-sidebar-actions > * {
flex: none;
}
.b05-route__actions {
display: flex;
gap: var(--spacing-8);