메인 메뉴 Main menu
메인 메뉴는 서비스 전체의 구조를 보여주고 주요 화면으로 이동할 수 있게 하는 메뉴이다. 일반적으로 헤더 영역에 위치하며, 데스크탑에서는 메가 메뉴 형태로, 모바일에서는 드로어 형태로 제공된다.
variant로 두 형태를 전환합니다(기본 pc). 같은 items를 PC와 모바일에 함께 쓸 수 있습니다. PC 메가 메뉴는 원본 KRDS처럼 패널을 열면 페이지 전체에 배경 딤(backdrop)을 깝니다. 메뉴가 딤 위에 보이려면 헤더(#krds-header, header[krdsHeader]) 안에 두어야 하며, 헤더 밖에서 쓰면 [backdrop]="false"로 끕니다.
메뉴 항목을 누르면 (itemClick)으로 항목과 클릭 이벤트를 보냅니다. 라우터로 이동하려면 event.preventDefault()로 기본 이동을 막고 라우터로 옮깁니다. PC 패널 안의 링크를 누르면 패널을 닫고 초점을 1단계 메뉴 버튼으로 돌려주므로, 페이지를 새로 읽지 않는 이동에서도 패널이 남지 않습니다.
PC 메가 메뉴
PC 메가 메뉴는 1024px 이상 화면에서만 표시됩니다. 미리보기는 헤더 밖에 두므로 [backdrop]="false"로 배경 딤을 끄고, PC 레이아웃 그대로 보이도록 1024px 폭으로 표시합니다(가로 스크롤). 헤더 안에서 쓰는 예는 헤더 문서를 참고하세요.
subItems가 있는 1단계는 패널을 여는 버튼이 되고, 패널은 링크가 아닌 첫 2단계를 연 채로 보입니다. 2단계의 items는 마지막 뎁스 링크 목록이고, description이 있으면 설명형 목록으로, layout: 'between'이면 배너를 오른쪽에 둡니다. banner: true인 패널에는 <ng-template krdsMainMenuBanner>로 넣은 배너를 그리며, 템플릿 컨텍스트로 1단계 항목(let-item)과 2단계 항목(let-subItem="subItem")을 받습니다. 패널이 열리거나 닫히면 (menuToggle)로 1단계 순서와 열림 상태를 보냅니다.
키보드로는 방향키로 같은 단계의 메뉴 버튼 사이를, Home·End로 처음·마지막 1단계 메뉴로 초점을 옮깁니다. Esc를 누르면 패널을 닫고 1단계 메뉴 버튼으로 초점을 돌려주며, 메뉴 밖을 누르거나 초점이 메뉴 밖으로 나가도 닫힙니다.
import { Component } from '@angular/core'
import { KrdsBadge, KrdsButton, KrdsMainMenu, KrdsMainMenuBanner, type KrdsMainMenuItem } from '@krds.ui/angular'
@Component({
selector: 'demo-main-menu-pc-mega-menu',
imports: [KrdsBadge, KrdsButton, KrdsMainMenu, KrdsMainMenuBanner],
template: `
<krds-main-menu [items]="items" [backdrop]="false">
<ng-template krdsMainMenuBanner>
<span krdsBadge type="bg" color="secondary">신규 서비스</span>
<button krdsButton size="medium" text>메뉴명 <i class="svg-icon ico-angle right" aria-hidden="true"></i></button>
</ng-template>
</krds-main-menu>
`
})
export default class MainMenuPcMegaMenu {
readonly items: KrdsMainMenuItem[] = [
{
text: '정보서비스',
subItems: [
{
text: '민원신청',
title: '민원신청',
titleLink: { href: '#', text: '바로가기' },
layout: 'between',
banner: true,
items: [
{ text: '증명서 발급', href: '#' },
{ text: '전입신고', href: '#' },
{ text: '여권 재발급', href: '#' },
{ text: '주민등록 등본', href: '#', selected: true }
]
},
{
text: '생활지원',
title: '생활지원',
items: [
{ text: '주거 지원', href: '#' },
{ text: '교육 지원', href: '#' },
{ text: '의료 지원', href: '#' }
]
},
{
text: '고용정보',
title: '고용정보',
items: [
{
text: '채용 공고',
href: '#',
description: '메뉴명과 메뉴에 관한 간략한 설명이 표시되는 스타일입니다.',
external: true
},
{
text: '직업 훈련',
href: '#',
description: '메뉴명과 메뉴에 관한 간략한 설명이 표시되는 스타일입니다.',
selected: true
}
]
},
{ text: '통합검색 바로가기', href: '#' },
{ text: '외부 서비스', href: 'https://www.krds.go.kr', external: true }
]
},
{
text: '정책정보',
subItems: [
{
text: '정책자료',
title: '정책자료',
layout: 'between',
items: [
{ text: '보도자료', href: '#' },
{ text: '입법예고', href: '#' },
{ text: '연구보고서', href: '#' }
]
},
{
text: '통계정보',
title: '통계정보',
items: [
{ text: '국가통계', href: '#' },
{ text: '지역통계', href: '#' }
]
}
]
},
{
text: '알림소식',
title: '알림소식',
layout: 'between',
items: [
{ text: '공지사항', href: '#' },
{ text: '보도자료', href: '#' },
{ text: '행사안내', href: '#' },
{ text: '채용정보', href: '#' },
{ text: '입찰공고', href: '#' },
{ text: '고시공고', href: '#' }
]
},
{ text: '기관소개', href: '#' }
]
}PC 2depth 없는 메뉴
2depth 목록 없이 마지막 뎁스 링크만 나열하는 경우 1단계에 subItems 대신 items만 지정하면 single-list 레이아웃으로 렌더링됩니다. 한 페이지에 메뉴가 여럿이면 label(기본 '메인 메뉴')로 이름을 구분합니다.
import { Component } from '@angular/core'
import { KrdsMainMenu, type KrdsMainMenuItem } from '@krds.ui/angular'
@Component({
selector: 'demo-main-menu-single-list',
imports: [KrdsMainMenu],
template: '<krds-main-menu label="주요 메뉴" [items]="items" [backdrop]="false" />'
})
export default class MainMenuSingleList {
readonly items: KrdsMainMenuItem[] = [
{
text: '알림소식',
title: '알림소식',
layout: 'between',
items: [
{ text: '공지사항', href: '#' },
{ text: '보도자료', href: '#' },
{ text: '행사안내', href: '#' },
{ text: '채용정보', href: '#' },
{ text: '입찰공고', href: '#' },
{ text: '고시공고', href: '#' }
]
},
{ text: '기관소개', href: '#' }
]
}모바일 드로어 메뉴
모바일 드로어는 [(open)]으로 제어합니다. 외부 트리거 버튼에 aria-controls로 mobileId(기본 mobile-nav)를 연결하고 aria-expanded를 함께 관리합니다. 1단계는 탭으로, 누르면 해당 패널 위치로 스크롤합니다. 2단계의 items는 펼침 3단계로(expanded로 처음 펼침), 3단계의 items는 전체 화면 4단계 패널로 렌더링됩니다. 드로어 위쪽 영역은 krdsMainMenuHeader 속성을, 아래쪽 영역은 krdsMainMenuBottom을 붙인 요소로 넣습니다.
드로어가 열리면 드로어로 초점을 옮기고 Tab 초점을 드로어 안에 가둡니다. 닫기 버튼이나 Esc로 닫으면 드로어를 연 요소로 초점을 돌려줍니다. 4단계 패널은 열면 이전화면 버튼으로 초점을 옮기고, 이전화면·닫기 버튼이나 Esc로 4단계만 닫으면 패널을 연 링크로 초점을 돌려줍니다.
드로어는 화면 전체를 덮는 고정 위치 요소이고 1024px 이상 화면에서는 표시되지 않으므로, 예제를 별도 화면(iframe)에 띄웁니다.
import { Component, signal } from '@angular/core'
import { KrdsButton, KrdsMainMenu, KrdsMainMenuBottom, type KrdsMainMenuItem } from '@krds.ui/angular'
@Component({
selector: 'demo-main-menu-mobile',
imports: [KrdsButton, KrdsMainMenu, KrdsMainMenuBottom],
template: `
<button krdsButton size="medium" aria-controls="mobile-nav" [attr.aria-expanded]="open()" (click)="open.set(true)">
전체메뉴 열기
</button>
<krds-main-menu variant="mobile" [items]="items" [(open)]="open">
<div krdsMainMenuHeader class="gnb-login">
<button krdsButton size="large" text>로그인을 해주세요</button>
</div>
<div krdsMainMenuBottom>
<a href="#" class="krds-btn small text">개인정보처리방침</a>
</div>
</krds-main-menu>
`
})
export default class MainMenuMobile {
readonly items: KrdsMainMenuItem[] = [
{
text: '정보서비스',
subItems: [
{ text: '민원신청', href: '#' },
{ text: '생활지원', href: '#', selected: true },
{
text: '고용정보',
items: [
{ text: '채용 공고', href: '#' },
{
text: '직업 훈련',
href: '#',
panelTitle: '직업 훈련',
items: [
{ text: '국비 지원 과정', href: '#' },
{ text: '재직자 과정', href: '#' },
{ text: '온라인 과정', href: '#' }
]
},
{ text: '고용 통계', href: '#' }
]
}
]
},
{
text: '정책정보',
subItems: [
{ text: '정책자료', href: '#' },
{ text: '통계정보', href: '#' }
]
},
{
text: '알림소식',
subItems: [
{ text: '공지사항', href: '#' },
{ text: '보도자료', href: '#' }
]
},
{
text: '기관소개',
subItems: [
{ text: '인사말', href: '#' },
{ text: '조직도', href: '#' }
]
}
]
readonly open = signal(false)
}KrdsMainMenu
선택자 krds-main-menu
Inputs
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
items | KrdsMainMenuItem[] | [] | 메뉴 항목 |
variant | 'pc' | 'mobile' | 'pc' | 렌더링 방식 |
label | string | '메인 메뉴' | 메뉴 이름 |
[(open)] | boolean | false | 모바일 드로어 열림 |
mobileId | string | 'mobile-nav' | 모바일 드로어 id (바깥 열기 버튼의 aria-controls 대상) |
backdrop | boolean | true | PC 패널이 열리면 배경을 어둡게 |
closeLabel | string | '전체메뉴 닫기' | 모바일 닫기 버튼 문구 |
Outputs
| 이름 | 값 | 설명 |
|---|---|---|
menuToggle | KrdsMainMenuToggle | PC 패널을 열거나 닫았을 때 |
itemClick | KrdsMainMenuClick | 메뉴 항목을 클릭했을 때 |
타입
/** 1단계 항목 (subItems가 있으면 2단계 목록이 있는 패널, items만 있으면 링크만 나열하는 single-list 패널, 둘 다 없으면 링크) */
export interface KrdsMainMenuItem {
text: string
href?: string
external?: boolean
subItems?: KrdsMainMenuSubItem[]
items?: KrdsMainMenuLinkItem[]
/** single-list 패널 제목 */
title?: string
banner?: boolean
layout?: KrdsMainMenuLayout
selected?: boolean
}
/** PC 패널 열림 이벤트 */
export interface KrdsMainMenuToggle {
index: number
expanded: boolean
}
/** 메뉴 항목 클릭 이벤트 (라우터로 이동하려면 event.preventDefault()) */
export interface KrdsMainMenuClick {
item: KrdsMainMenuItem | KrdsMainMenuSubItem | KrdsMainMenuLinkItem | KrdsMainMenuDepth4Item
event: MouseEvent
}
/** 2단계 항목 (items가 있으면 서브 패널을 여는 버튼, 없으면 바로가기 링크) */
export interface KrdsMainMenuSubItem {
text: string
href?: string
external?: boolean
/** 서브 패널 제목 (기본: text) */
title?: string
/** 서브 패널 제목 옆 바로가기 링크 (PC) */
titleLink?: { text?: string; href: string }
items?: KrdsMainMenuLinkItem[]
/** 배너 영역 표시 (krdsMainMenuBanner 템플릿, PC) */
banner?: boolean
layout?: KrdsMainMenuLayout
/** 모바일 3단계 처음 펼침 */
expanded?: boolean
selected?: boolean
}
/** 링크 항목 (PC 서브 패널의 마지막 단계, 모바일 3단계) */
export interface KrdsMainMenuLinkItem {
text: string
/** 링크 주소 (없으면 button) */
href?: string
external?: boolean
/** 메뉴 설명 (PC type-description) */
description?: string
selected?: boolean
/** 모바일 4단계 패널 제목 (기본: text) */
panelTitle?: string
/** 모바일 4단계 항목 */
items?: KrdsMainMenuDepth4Item[]
}
/** 모바일 4단계 항목 */
export interface KrdsMainMenuDepth4Item {
text: string
href?: string
/** 새 창 열림 */
external?: boolean
/** 현재 페이지 */
selected?: boolean
}
KrdsMainMenuBanner
선택자 ng-template[krdsMainMenuBanner]
Inputs
없음
KrdsMainMenuBottom
선택자 [krdsMainMenuBottom]
Inputs
없음