feat: [planning-design] 작업 영역 극대화 (패널 접기/펼치기)

- 좌측 메뉴트리 패널 접기/펼치기 토글 버튼 추가
- Description 패널 접기/펼치기 토글 바 추가
- 사이드바 접힘 시 스토리보드 페이지 폭 1100→1400px 자동 확장
- sb-editor padding 24→12px 축소
This commit is contained in:
김보곤
2026-03-08 09:19:18 +09:00
parent 5e0f1a6373
commit f120273160

View File

@@ -552,14 +552,22 @@
.sb-page-thumb:hover { border-color: #cbd5e1; }
.sb-page-thumb.active { border-color: var(--pc-indigo); background: #eef2ff; color: #4338ca; }
.sb-page-thumb-num { font-weight: 700; font-size: 11px; color: #374151; }
.sb-editor { flex: 1; overflow: auto; padding: 24px; display: flex; justify-content: center; }
.sb-editor { flex: 1; overflow: auto; padding: 12px; display: flex; justify-content: center; }
/* Storyboard Page (A4-like) */
.sb-page {
width: 1100px; min-height: 750px; background: #fff; border-radius: 4px;
width: 1100px; max-width: 100%; min-height: 750px; background: #fff; border-radius: 4px;
box-shadow: 0 2px 12px rgba(0,0,0,0.1); display: flex; flex-direction: column;
flex-shrink: 0;
flex-shrink: 0; transition: width 0.2s;
}
/* 메뉴트리 패널 접기 토글 */
.sb-menu-toggle {
width: 18px; flex-shrink: 0; cursor: pointer;
display: flex; align-items: center; justify-content: center;
background: #f1f5f9; border: none; color: #94a3b8;
transition: all 0.15s; border-left: 1px solid #e2e8f0;
}
.sb-menu-toggle:hover { background: #e2e8f0; color: #475569; }
.sb-page-header {
display: grid; grid-template-columns: 1fr auto auto auto auto auto;
border-bottom: 2px solid #1e293b; font-size: 10px;
@@ -616,8 +624,16 @@
}
.sb-wireframe-content:focus { border-color: var(--pc-indigo); }
.sb-wireframe-img { max-width: 100%; border-radius: 8px; }
.sb-desc-toggle-bar {
height: 24px; flex-shrink: 0; cursor: pointer;
display: flex; align-items: center; justify-content: center; gap: 6px;
background: #1e293b; color: #94a3b8; font-size: 9px; font-weight: 600;
text-transform: uppercase; letter-spacing: 0.5px; transition: background 0.15s;
}
.sb-desc-toggle-bar:hover { background: #334155; color: #e2e8f0; }
.sb-desc-toggle-label { color: inherit; }
.sb-desc-resizer {
height: 5px; flex-shrink: 0; cursor: row-resize; background: #1e293b;
height: 5px; flex-shrink: 0; cursor: row-resize; background: #334155;
transition: background .15s;
}
.sb-desc-resizer:hover, .sb-desc-resizer.active { background: #818cf8; }
@@ -625,10 +641,6 @@
padding: 12px 16px; background: #fafbfc;
overflow-y: auto; flex-shrink: 0;
}
.sb-desc-title {
font-size: 10px; font-weight: 700; color: #1e293b; margin-bottom: 8px;
text-transform: uppercase; letter-spacing: 0.5px;
}
.sb-desc-item {
display: flex; gap: 10px; padding: 6px 0; border-bottom: 1px solid #f1f5f9;
font-size: 12px; line-height: 1.6;
@@ -1625,7 +1637,7 @@
{{-- Page Editor --}}
<div class="sb-editor">
<template x-if="sbCurrentPage">
<div class="sb-page">
<div class="sb-page" :style="'width:' + (sidebarOpen ? '1100' : '1400') + 'px'">
{{-- Page Header --}}
<div class="sb-page-header">
<div>
@@ -1658,24 +1670,33 @@
@mousemove.window="if(_sbMenuResize){ sbMenuWidth = Math.max(80, Math.min(400, _sbMenuResize.startW + $event.clientX - _sbMenuResize.startX)); } if(_sbDescResize){ sbDescHeight = Math.max(60, Math.min(500, _sbDescResize.startH - ($event.clientY - _sbDescResize.startY))); }"
@mouseup.window="if(_sbMenuResize){ _sbMenuResize = null; document.querySelector('.sb-menu-resizer.active')?.classList.remove('active'); } if(_sbDescResize){ _sbDescResize = null; document.querySelector('.sb-desc-resizer.active')?.classList.remove('active'); }">
{{-- Left Menu --}}
<div class="sb-menu-panel" :style="'width:' + sbMenuWidth + 'px'">
<div class="sb-menu-logo" x-text="sb.docInfo.projectName || 'LOGO'"></div>
<div class="sb-menu-section">ERP 메뉴</div>
<template x-for="menu in sb.menuTree" :key="menu.name">
<div>
<div class="sb-menu-item" :class="{ active: sbCurrentPage.path && sbCurrentPage.path.startsWith(menu.name) }" x-text="menu.name"></div>
<template x-for="child in (menu.children || [])" :key="child.name">
<div class="sb-menu-item sb-menu-child"
:class="{ active: sbCurrentPage.path && sbCurrentPage.path.includes(child.name) }"
x-text="'- ' + child.name"></div>
</template>
</div>
</template>
</div>
<template x-if="sbMenuOpen">
<div class="sb-menu-panel" :style="'width:' + sbMenuWidth + 'px'">
<div class="sb-menu-logo" x-text="sb.docInfo.projectName || 'LOGO'"></div>
<div class="sb-menu-section">ERP 메뉴</div>
<template x-for="menu in sb.menuTree" :key="menu.name">
<div>
<div class="sb-menu-item" :class="{ active: sbCurrentPage.path && sbCurrentPage.path.startsWith(menu.name) }" x-text="menu.name"></div>
<template x-for="child in (menu.children || [])" :key="child.name">
<div class="sb-menu-item sb-menu-child"
:class="{ active: sbCurrentPage.path && sbCurrentPage.path.includes(child.name) }"
x-text="'- ' + child.name"></div>
</template>
</div>
</template>
</div>
</template>
{{-- Menu / Content Resizer --}}
<div class="sb-menu-resizer"
@mousedown.prevent="_sbMenuResize = { startX: $event.clientX, startW: sbMenuWidth }; $event.target.classList.add('active')"></div>
{{-- Menu Toggle + Resizer --}}
<button class="sb-menu-toggle" @click="sbMenuOpen = !sbMenuOpen" :title="sbMenuOpen ? '메뉴 접기' : '메뉴 펼치기'">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<polyline :points="sbMenuOpen ? '15 6 9 12 15 18' : '9 6 15 12 9 18'"/>
</svg>
</button>
<template x-if="sbMenuOpen">
<div class="sb-menu-resizer"
@mousedown.prevent="_sbMenuResize = { startX: $event.clientX, startW: sbMenuWidth }; $event.target.classList.add('active')"></div>
</template>
{{-- Content + Description --}}
<div class="sb-content-area">
@@ -2083,26 +2104,35 @@
</div>
</template>
{{-- Desc Resizer --}}
<div class="sb-desc-resizer"
@mousedown.prevent="_sbDescResize = { startY: $event.clientY, startH: sbDescHeight }; $event.target.classList.add('active')"></div>
{{-- Description Panel --}}
<div class="sb-desc-panel" :style="'height:' + sbDescHeight + 'px'">
<div class="sb-desc-title">Description</div>
<template x-for="(desc, idx) in (sbCurrentPage.descriptions || [])" :key="idx">
<div class="sb-desc-item">
<div class="sb-desc-num"
x-text="String(idx + 1).padStart(2, '0')"
draggable="true"
@dragstart="$event.dataTransfer.setData('text/plain', 'marker:' + String(idx + 1).padStart(2, '0')); $event.dataTransfer.effectAllowed = 'copy';"></div>
<div class="sb-desc-text">
<textarea x-model="desc.text" rows="2" placeholder="기능 설명을 입력하세요..." @input="autoSave()"></textarea>
</div>
<button class="sb-desc-remove" @click="sbCurrentPage.descriptions.splice(idx, 1); autoSave();">&times;</button>
</div>
</template>
<div class="sb-desc-add" @click="sbAddDescription()">+ Description 항목 추가</div>
{{-- Desc Toggle + Resizer --}}
<div class="sb-desc-toggle-bar" @click="sbDescOpen = !sbDescOpen">
<span class="sb-desc-toggle-label">Description</span>
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<polyline :points="sbDescOpen ? '18 15 12 9 6 15' : '6 9 12 15 18 9'"/>
</svg>
</div>
<template x-if="sbDescOpen">
<div class="sb-desc-resizer"
@mousedown.stop.prevent="_sbDescResize = { startY: $event.clientY, startH: sbDescHeight }; $event.target.classList.add('active')"></div>
</template>
{{-- Description Panel --}}
<template x-if="sbDescOpen">
<div class="sb-desc-panel" :style="'height:' + sbDescHeight + 'px'">
<template x-for="(desc, idx) in (sbCurrentPage.descriptions || [])" :key="idx">
<div class="sb-desc-item">
<div class="sb-desc-num"
x-text="String(idx + 1).padStart(2, '0')"
draggable="true"
@dragstart="$event.dataTransfer.setData('text/plain', 'marker:' + String(idx + 1).padStart(2, '0')); $event.dataTransfer.effectAllowed = 'copy';"></div>
<div class="sb-desc-text">
<textarea x-model="desc.text" rows="2" placeholder="기능 설명을 입력하세요..." @input="autoSave()"></textarea>
</div>
<button class="sb-desc-remove" @click="sbCurrentPage.descriptions.splice(idx, 1); autoSave();">&times;</button>
</div>
</template>
<div class="sb-desc-add" @click="sbAddDescription()">+ Description 항목 추가</div>
</div>
</template>
</div>
</div>
</div>
@@ -2341,6 +2371,8 @@ function planningCanvas() {
_sbResize: null, // { blk, dir, startX, startY, origW, origH }
_sbClipboard: null, // copied block data
sbMenuWidth: 160,
sbMenuOpen: true,
sbDescOpen: true,
sbDescHeight: 200,
sbMarkerNum: '01',
_sbMenuResize: null,