컴포넌트/패널 외 영역 (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

참고

'컴포넌트 > 패널 외 영역 (Div, Span)' 카테고리의 다른 글

Title (타이틀)  (0) 2026.09.18
ActionBar (액션바)  (0) 2026.09.18
Page (페이지)  (0) 2026.09.18
Span (스팬)  (1) 2026.09.18
Div (디비젼)  (0) 2026.09.18