사이드 메뉴 Side navigation
사이드 메뉴는 서브 화면 내에서의 이동을 위해 사용하는 메뉴이다. 일반적으로 본문 영역의 좌측에 사이드바 형태로 제공된다. 메인 메뉴보다 훨씬 좁고 깊은 페이지 구조 탐색에 사용되기 때문에 링크의 개수가 많고 복잡하게 표현되기 쉽다.
기본
v-model로 메뉴 아이템 배열을 전달합니다. 2Depth의 subItems는 펼침 목록으로, 3Depth의 subItems는 4Depth 팝업으로 렌더링되며 expanded로 초기 펼침 상태를 지정합니다.
4Depth 팝업을 열면 팝업 제목으로 초점이 옮겨 가고, 제목을 눌러 닫으면 팝업을 연 버튼으로 초점이 돌아옵니다. Tab으로 팝업을 벗어나거나 팝업 밖을 누르면 팝업이 닫히고, 초점은 옮겨 간 곳에 그대로 둡니다.
vue
<script setup lang="ts">
import { ref } from 'vue'
import { KrdsSideNavigation, type SideNavItem } from '@krds.ui/vue'
const menuItems = ref<SideNavItem[]>([
{
text: '2Depth-menu',
expanded: true,
subItems: [
{
text: '3Depth-menu',
expanded: false,
popupTitle: '3Depth-title',
subItems: [
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' }
]
},
{ text: '3Depth-link', href: '#' },
{ text: '3Depth-link', href: '#' }
]
},
{
text: '2Depth-menu',
expanded: false,
subItems: [
{
text: '3Depth-menu',
expanded: false,
popupTitle: '3Depth-title',
subItems: [
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' }
]
},
{ text: '3Depth-link', href: '#' },
{ text: '3Depth-link', href: '#' }
]
},
{
text: '2Depth-menu',
expanded: false,
subItems: [
{
text: '3Depth-menu',
expanded: false,
popupTitle: '3Depth-title',
subItems: [
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' }
]
},
{ text: '3Depth-link', href: '#' },
{ text: '3Depth-link', href: '#' }
]
}
])
</script>
<template>
<KrdsSideNavigation v-model="menuItems" title="1Depth-title" />
</template>2Depth 링크
subItems가 없는 2Depth 항목은 링크로 렌더링되고, onClick으로 클릭 동작을 지정할 수 있습니다.
vue
<script setup lang="ts">
import { ref } from 'vue'
import { KrdsSideNavigation, type SideNavItem } from '@krds.ui/vue'
const menuItems = ref<SideNavItem[]>([
{ text: '2Depth-link', href: '#lnb-link' },
{ text: '2Depth-action', onClick: event => event.preventDefault() },
{
text: '2Depth-menu',
expanded: false,
subItems: [
{
text: '3Depth-menu',
expanded: false,
popupTitle: '3Depth-title',
subItems: [
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' }
]
},
{ text: '3Depth-link', href: '#' },
{ text: '3Depth-link', href: '#' }
]
}
])
</script>
<template>
<KrdsSideNavigation v-model="menuItems" title="1Depth-title" aria-label="사이드 메뉴" />
</template>여러 개 배치
한 페이지에 여러 개를 두어도 내부 id는 겹치지 않습니다. aria-label로 각 메뉴를 구분합니다.
vue
<script setup lang="ts">
import { ref } from 'vue'
import { KrdsSideNavigation, type SideNavItem } from '@krds.ui/vue'
const createItems = (): SideNavItem[] => [
{
text: '2Depth-menu',
expanded: true,
subItems: [
{
text: '3Depth-menu',
expanded: false,
popupTitle: '3Depth-title',
subItems: [
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' }
]
},
{ text: '3Depth-link', href: '#' },
{ text: '3Depth-link', href: '#' }
]
},
{
text: '2Depth-menu',
expanded: false,
subItems: [
{
text: '3Depth-menu',
expanded: false,
popupTitle: '3Depth-title',
subItems: [
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' }
]
},
{ text: '3Depth-link', href: '#' },
{ text: '3Depth-link', href: '#' }
]
},
{
text: '2Depth-menu',
expanded: false,
subItems: [
{
text: '3Depth-menu',
expanded: false,
popupTitle: '3Depth-title',
subItems: [
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' },
{ text: '4Depth', href: '#' }
]
},
{ text: '3Depth-link', href: '#' },
{ text: '3Depth-link', href: '#' }
]
}
]
const first = ref(createItems())
const second = ref(createItems())
</script>
<template>
<div style="display: flex; gap: 2rem">
<KrdsSideNavigation v-model="first" title="1Depth-title" aria-label="첫 번째 사이드 메뉴" style="flex: 1" />
<KrdsSideNavigation v-model="second" title="1Depth-title" aria-label="두 번째 사이드 메뉴" style="flex: 1" />
</div>
</template>KrdsSideNavigation
Props
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
modelValue | SideNavItem[] | [] | 메뉴 아이템 배열 |
title (필수) | string | - | 네비게이션 제목 |
Events
| 이름 | 인자 | 설명 |
|---|---|---|
update:modelValue | [value: SideNavItem[]] | 메뉴를 펼치거나 접어 항목 상태가 바뀔 때 (v-model) |