컴포넌트/툴바

NavigationMenuBar (햄버거 메뉴 바)

VanillaFront 2026. 9. 29. 23:21

 

Va.NavigationMenuBar — 확장형 메뉴 내비게이션 바

햄버거 메뉴 버튼과 확장 가능한 메뉴 영역을 결합한 상단 내비게이션 컴포넌트입니다. 헤더 우측에 자동으로 메뉴 버튼(햄버거 아이콘)이 배치되고, 클릭하면 아래로 펼쳐지는 메뉴 팝 영역에 메뉴 항목들이 표시됩니다. 모바일 친화적인 접기/펼치기 UX가 필요한 애플리케이션이나, 메뉴 항목이 많아 상단 바에 다 배치하기 어려운 경우에 적합합니다.


클래스 정보

  • Va.NavigationMenuBar extends Va.Component
  • tagName: 'navigationMenuBar'
  • isContainer: true
  • 기본 HTML: <nav> 요소
  • 파일: va_component.js

기본 사용법

{
    tagName: 'navigationMenuBar',
    title: 'Title',
    menuAlign: 'right',
    tags: [
        { tagName: 'expandButton', shape: 'square', text: 'Menu1',
          tags: [
              { tagName: 'button', shape: 'square', text: 'Menu11' },
              { tagName: 'button', shape: 'square', text: 'Menu12' }
          ]
        },
        { tagName: 'expandButton', shape: 'square', text: 'Menu2',
          tags: [
              { tagName: 'button', shape: 'square', text: 'Menu21' },
              { tagName: 'button', shape: 'square', text: 'Menu22' }
          ]
        },
        { tagName: 'button', shape: 'square', text: 'Menu3' }
    ]
}

차이점 요약: NavigationBar와 달리, tags로 넣은 자식은 기본적으로 접혀 있는 메뉴 팝(menuPop) 영역에 들어갑니다. 화면 우측의 햄버거 버튼을 눌러야 펼쳐집니다.


내부 구조

NavigationMenuBar는 헤더 + 메뉴 팝(pop) 두 개의 층으로 구성됩니다.

영역위치역할

titleDiv 헤더 좌측 title 속성값 또는 tagPosition: 'title' 컴포넌트
menuDiv 헤더 가운데 tagPosition: 'menu'로 지정된 컴포넌트 (헤더에 상시 노출)
menuButton 헤더 우측 자동 생성되는 햄버거 버튼 (ico_navigation)
menuPop (기본 컨테이너) 헤더 아래 tags로 넣은 자식이 배치, expanded 시 표시

containerPosition은 {title: 0, menu: 1, menuPop: 2}로 정의되며, **기본 컨테이너는 menuPop**입니다.


핸들러는 반드시 문자열 참조 (JSON 원칙)

VanillaFront는 화면 정의를 JSON으로 유지하는 철학입니다. 모든 이벤트 핸들러는 문자열로 View 메서드 이름을 지정합니다.

{ onTitleClick: 'onTitleClick', onMenuClick: 'onMenuClick', onExpand: 'onExpand', onCollapse: 'onCollapse' }

인라인 function 사용 금지 — JSON 직렬화/에디터/저장 불가.


주요 속성

속성타입기본값설명

title String — 좌측에 표시할 타이틀 텍스트
appearance String — 시각 스타일 — 'primary', 'subtle', 'accent' 등
menuAlign String 'right' 헤더의 menuDiv 정렬 — 'left', 'center', 'right'
expanded Boolean false 메뉴 팝 열림 상태
border String — 테두리 스타일 — 'neutral' 등
menuButton Object — 자동 생성되는 햄버거 버튼 옵션 오버라이드 (icon, appearance 등)

주요 이벤트

이벤트콜백발생 시점

onExpand 'onExpand' 햄버거 버튼 클릭으로 메뉴 팝이 열릴 때
onCollapse 'onCollapse' 햄버거 버튼 재클릭으로 메뉴 팝이 닫힐 때
onMenuClick 'onMenuClick' 햄버거 버튼 클릭 시마다 (expand/collapse와 함께)
onTitleClick 'onTitleClick' 타이틀 클릭

주요 메서드

  • expand() — 메뉴 팝 열기
  • collapse() — 메뉴 팝 닫기

menuAlign — 헤더의 menuDiv 정렬

헤더 가운데 배치되는 menuDiv 영역의 정렬을 지정합니다. NavigationBar와 동일하게 'left', 'center', 'right' 3가지를 지원합니다.

{ tagName: 'navigationMenuBar', title: 'Title', menuAlign: 'center', tags: [ ... ] }

주의: menuAlign은 헤더의 menuDiv 정렬을 결정할 뿐, 메뉴 팝 안 항목들의 배치와는 관계없습니다.


expandButton — 접었다 펼치는 아코디언 메뉴

NavigationMenuBar 안에서는 서브메뉴를 표현할 때 expandButton을 씁니다. 클릭 시 하위 항목들이 드롭다운이 아닌 인라인 아코디언 방식으로 펼쳐지므로 좁은 폭에서도 자연스럽게 동작합니다.

{
    tagName: 'expandButton',
    shape: 'square',
    text: '제품',
    tags: [
        { tagName: 'button', shape: 'square', text: 'Grid' },
        { tagName: 'button', shape: 'square', text: 'Chart' },
        { tagName: 'button', shape: 'square', text: 'Diagram' }
    ]
}

contentFlex: 1, textAlign: 'left' 스타일을 적용하면 좌측 정렬된 메뉴 리스트 형태가 됩니다.


타이틀·상시 노출 메뉴를 헤더에 배치 — tagPosition

기본은 자식이 menuPop(햄버거로 열리는 영역)에 들어가지만, 헤더에 항상 보여야 하는 요소는 tagPosition으로 위치를 옮깁니다.

{
    tagName: 'navigationMenuBar',
    menuAlign: 'left',
    style: { titleDiv_width: '200px' },
    tags: [
        // 헤더 좌측 (titleDiv)
        {
            tagName: 'button',
            text: 'Title',
            appearance: 'accent',
            style: 'width:180px',
            tagPosition: 'title'
        },
        // 헤더 가운데 (menuDiv) — 항상 노출
        {
            tagName: 'button',
            text: 'Another Menu',
            appearance: 'primary',
            tagPosition: 'menu'
        },
        // 이하 tagPosition 없음 → menuPop(햄버거 안)
        { tagName: 'expandButton', shape: 'square', text: 'Menu1',
          tags: [ ... ] },
        { tagName: 'expandButton', shape: 'square', text: 'Menu2',
          tags: [ ... ] }
    ]
}

tagPosition배치 영역표시 조건

'title' titleDiv 항상
'menu' menuDiv 항상
(없음) menuPop 햄버거 버튼으로 열었을 때만

햄버거 버튼 커스터마이징 — menuButton

기본 아이콘은 ico_navigation(햄버거)이지만, menuButton 옵션으로 오버라이드할 수 있습니다.

{
    tagName: 'navigationMenuBar',
    title: 'Title',
    menuButton: {
        icon: 'ico_more',       // 다른 아이콘
        appearance: 'primary',
        size: 'large'
    },
    tags: [ ... ]
}

종합 예시 — 로고 + 상시 메뉴 + 햄버거 확장

config() {
    return {
        tagName: 'page',
        tags: [{
            tagName: 'navigationMenuBar',
            appearance: 'primary',
            menuAlign: 'left',
            border: 'neutral',
            style: { titleDiv_width: '220px' },
            tags: [
                // 로고 (헤더 좌측 상시)
                {
                    tagName: 'button',
                    text: 'VanillaFront',
                    appearance: 'accent',
                    style: 'width:200px',
                    tagPosition: 'title',
                    onClick: 'onLogoClick'
                },
                // 헤더 가운데 상시 메뉴
                { tagName: 'button', appearance: 'primary', text: '가격',
                  tagPosition: 'menu' },
                { tagName: 'button', appearance: 'primary', text: '문서',
                  tagPosition: 'menu' },
                
                // 햄버거 안에 접혀 있는 메뉴들
                {
                    tagName: 'expandButton', shape: 'square', appearance: 'primary',
                    text: '제품',
                    tags: [
                        { tagName: 'button', appearance: 'primary', shape: 'square',
                          text: 'Grid',    style: { contentFlex: 1, textAlign: 'left' } },
                        { tagName: 'button', appearance: 'primary', shape: 'square',
                          text: 'Chart',   style: { contentFlex: 1, textAlign: 'left' } },
                        { tagName: 'button', appearance: 'primary', shape: 'square',
                          text: 'Diagram', style: { contentFlex: 1, textAlign: 'left' } }
                    ]
                },
                {
                    tagName: 'expandButton', shape: 'square', appearance: 'primary',
                    text: '학습',
                    tags: [
                        { tagName: 'button', appearance: 'primary', shape: 'square',
                          text: '튜토리얼', style: { contentFlex: 1, textAlign: 'left' } },
                        { tagName: 'button', appearance: 'primary', shape: 'square',
                          text: 'API',      style: { contentFlex: 1, textAlign: 'left' } }
                    ]
                },
                { tagName: 'button', appearance: 'primary', shape: 'square',
                  text: '커뮤니티' }
            ],
            onTitleClick: 'onLogoClick',
            onMenuClick:  'onMenuClick',
            onExpand:     'onExpand',
            onCollapse:   'onCollapse'
        }, {
            // 페이지 본문
            tagName: 'panel',
            style: { flex: 1 },
            tags: [ ... ]
        }]
    };
}

NavigationBar vs NavigationMenuBar — 차이점

항목NavigationBarNavigationMenuBar

자식 배치 기본 위치 헤더 menuDiv (상시 노출) menuPop (햄버거 안, 접혀 있음)
서브메뉴 표현 menuButton + menuItem (드롭다운) expandButton + button (아코디언)
우측 자동 요소 없음 햄버거 버튼 (자동 생성)
expand/collapse 이벤트 지원 지원 (실제 팝 개폐 동작)
우측 유틸 영역 tagPosition: 'right' 사용 별도 rightDiv 없음
적합한 상황 데스크톱 웹, 항상 메뉴 노출 모바일 친화, 메뉴 많은 경우

주의사항

  • 기본 컨테이너는 menuPop — tags 자식은 햄버거 안에 들어감. 헤더에 상시 노출하려면 tagPosition: 'menu' 지정 필수
  • 햄버거 버튼은 자동 생성 — 별도로 만들지 않아도 우측에 나타남
  • 서브메뉴는 expandButton 권장 — menuButton(드롭다운)은 팝 영역 안에서 어색할 수 있음
  • menuAlign은 헤더의 menuDiv 전용 — menuPop 안 항목 정렬과는 무관
  • title 텍스트는 순수 텍스트(textContent) — NavigationBar와 달리 HTML 삽입 불가
  • 핸들러는 문자열 참조만 — 인라인 function은 JSON 원칙 위반
  • 모바일 미디어쿼리와 조합 권장 — 데스크톱에선 NavigationBar, 모바일에선 NavigationMenuBar로 교체하는 반응형 패턴이 유용

대안 비교

상황추천

모바일/좁은 화면, 접히는 메뉴 필요 Va.NavigationMenuBar
데스크톱 상단, 메뉴 상시 노출 Va.NavigationBar
좌측 세로 아이콘 메뉴 Va.NavigationRail
좌측 트리형 메뉴 (프로젝트 표준 사이드 메뉴 컴포넌트)
페이지 내부 액션 툴바 Va.ActionBar / Va.TitleBar

참고