컴포넌트/패널 외 영역 (Div, Span)
Panel (패널)
VanillaFront
2026. 9. 18. 19:08
Va.Panel — Page의 짝을 이루는 섹션 컨테이너
Page 안에서 화면을 논리적으로 분할하는 표준 섹션 컨테이너입니다. 내부적으로 <section> 태그로 렌더링되며, Va.Page > Va.Panel 구조는 VanillaFront 화면의 표준 스캐폴드입니다. 접기/펼치기, 드래그로 크기 조절, 리사이즈 감지 등 실무에서 자주 필요한 기능들을 내장합니다.

클래스 정보
Va.Panel extends Va.Semantic extends Va.Component
tagName: 'panel' (실제 렌더링은 <section>)
isContainer: true
기본 사용법
{
tagName: 'page',
tags: [{
tagName: 'panel',
tags: [
{ tagName: 'inputField', label: '이름' },
{ tagName: 'button', text: '저장' }
]
}]
}
왜 Panel인가 — Page와의 짝
VanillaFront 화면 표준 구조는 Page > Panel입니다:
- Page: 화면 최상위 컨테이너 — 자체 padding/gap
- Panel: 화면 내부 섹션 분할 — 자체 padding, 접기 버튼 슬롯
이 두 컴포넌트만 조합해도 각 영역이 일정한 공백으로 자연스럽게 나뉩니다. Panel 사이에 별도의 margin/padding/gap을 강제로 넣으면 오히려 룩이 어긋납니다.
속성
속성타입기본값설명
| collapseButtonPosition | String | 'none' | 접기 버튼 위치: 'top', 'bottom', 'left', 'right', 'none' |
| buttonSidePosition | String | 'center' | 접기 버튼의 축상 위치: 'top', 'start', 'center', 'end', 'bottom' |
| expanded | Boolean | true | 펼침/접힘 상태 |
| collapsedSize | Number | 20 | 접혔을 때 크기 (px) |
| expandedSize | Number | 자동 | 펼쳐졌을 때 크기 (드래그로 조정 시 저장) |
| shape | String | — | 형태 스타일 지정 |
| lineDivision | String | — | 'row' 또는 'column' — 자식 사이 구분선 |
| innerHTML / text | String | — | 내용 |
이벤트
이벤트발생 시점콜백 인자
| expand | 펼쳐질 때 | (sender, element, evt) |
| collapse | 접힐 때 | (sender, element, evt) |
| resize | 크기 변경 시 | (sender, element, width, height, null) |
resize는 ResizeObserver로 감지되며 200ms 디바운스가 적용됩니다.
메서드
- Va.Component / Va.Semantic 공통 메서드
- expanded 속성 변경 후 update()로 접기/펼치기
내부 구조
<section class="va-panel">
<div class="panel-inner" elname="inner">
<div class="panel-content" elname="content">
<!-- containerElement — 자식 컴포넌트 위치 -->
</div>
</div>
<div class="panel-collapse-button-div" elname="collapseButtonDiv">
<div class="panel-collapse-button" elname="collapseButton">
<i class="panel-collapse-button-icon icon" elname="collapseButtonIcon"></i>
</div>
</div>
</section>
collapseButtonPosition에 따라 버튼 div의 위치가 top/bottom/left/right로 재배치됩니다.
접기 버튼 상호작용
- 더블클릭 — 접기/펼치기 토글
- 드래그 — 크기 조절 (collapseButtonPosition이 top/bottom이면 세로, left/right면 가로)
- 아이콘 자동 전환 — 방향에 맞는 caret 아이콘 자동 표시
사용 시점 — 언제 쓰나
- Page 안의 섹션 분할 — 표준 화면 스캐폴드
- 접을 수 있는 사이드바 — collapseButtonPosition: 'right'
- 크기 조절 가능한 콘솔 — collapseButtonPosition: 'top'으로 상단 드래그 바 제공
- 폼 그룹 / 그리드 컨테이너 — 각 논리 단위를 Panel로 감싸기
사용하지 말아야 할 때
- 화면 최상위 → Va.Page
- 의미 있는 게시글 블록 → Va.Article
- 단순 그루핑 → Va.Div
- 모달 → Va.Dialog
자주 쓰는 조합 예시
표준 Page > Panel 구조
{
tagName: 'page',
tags: [{
tagName: 'panel',
tags: [ /* 검색 조건 */ ]
},{
tagName: 'panel',
tags: [ /* 그리드 */ ]
}]
}
접기 가능한 사이드 패널
{
tagName: 'page',
layout: 'ds-flex fd-row',
tags: [{
tagName: 'panel',
collapseButtonPosition: 'right',
style: { width: '250px' },
tags: [ /* 사이드바 메뉴 */ ]
},{
tagName: 'panel',
style: { flex: 1 },
tags: [ /* 메인 콘텐츠 */ ]
}]
}
크기 조절 가능한 하단 콘솔
{
tagName: 'page',
layout: 'ds-flex fd-column',
tags: [{
tagName: 'panel',
style: { flex: 1 },
tags: [ /* 에디터 */ ]
},{
tagName: 'panel',
collapseButtonPosition: 'top',
style: { height: '200px' },
tags: [ /* 콘솔 로그 */ ]
}]
}
resize 이벤트 활용
{
tagName: 'panel',
onResize: 'onResizePanel',
tags: [
{ ref: 'refGrid', tagName: 'grid' /* ... */ }
]
}
// View 안:
onResizePanel(sender, element, width, height){
this.getRef('refGrid').resize();
}
line-division으로 자식 사이 구분선
{
tagName: 'panel',
lineDivision: 'row',
tags: [
{ tagName: 'div', text: '항목1' },
{ tagName: 'div', text: '항목2' },
{ tagName: 'div', text: '항목3' }
]
}
실전 예시 — CRUD 화면
config(){
return {
tagName: 'page',
tags: [{
tagName: 'panel',
tags: [{
tagName: 'div',
layout: 'ds-flex fd-row gap-s',
tags: [
{ tagName: 'inputField', label: '이름', ref: 'refName' },
{ tagName: 'inputField', label: '부서', ref: 'refDept' },
{ tagName: 'div', style: { flex: 1 } },
{ tagName: 'button', text: '조회', onClick: 'onClickSearch' }
]
}]
},{
tagName: 'panel',
style: { flex: 1 },
tags: [{
ref: 'refGrid',
tagName: 'grid',
columns: [ /* ... */ ],
onRowClick: 'onRowClick'
}]
},{
tagName: 'panel',
collapseButtonPosition: 'top',
style: { height: '300px' },
tags: [ /* 상세 편집 폼 */ ]
}]
};
}
주의사항
- Page/Panel은 자체 gap을 가짐 — 사이에 별도 margin/padding/gap 강제 금지
- 접기 버튼 없을 때(none)는 순수 컨테이너로 동작 — 이 상태가 가장 흔한 사용 형태
- 드래그 크기 조절은 마우스로만 — 터치 이벤트는 별도 처리 없음
- collapsedSize 기본 20px — 접혔을 때 남는 크기. 필요에 따라 조정
- ResizeObserver 자동 부착 — 크기 변경 시 200ms 디바운스로 resize 이벤트 발생. 그리드/차트 재계산 트리거로 활용
- isContainer: true지만 <section>으로 렌더링됨 — HTML 마크업 검사 시 <panel>이 아니라 <section class="va-panel">
대안 비교
상황추천
| 화면 최상위 | Va.Page |
| 페이지 내부 섹션 | Va.Panel |
| 접기/펼치기 disclosure | Va.Details |
| 독립된 게시글 | Va.Article |
| 순수 그루핑 | Va.Div |
| 탭 인터페이스 | Va.Tab |
| 모달 다이얼로그 | Va.Dialog |
참고
- API 문서 페이지: https://vanillafront.com/docs.html?theme=light#main#apipanel
- 연관: Va.Semantic(부모), Va.Page(짝을 이루는 상위 컨테이너)