Appearance
v-z-index 디렉티브
v-z-index는 오버레이 컴포넌트(모달, 다이얼로그, 툴팁 등)의 z-index 값을 일관되고 체계적으로 관리할 수 있도록 설계된 Vue 디렉티브입니다. 이 디렉티브는 미리 정의된 z-index 맵을 사용하여 엘리먼트의 z-index 값을 설정합니다.
기본 사용법
v-z-index 디렉티브는 z-index 맵에 정의된 키 값을 받아 해당하는 z-index 값을 엘리먼트에 적용합니다.
vue
<template>
<div v-z-index="BASE_Z_INDEX_KEY.MODAL">
<!-- 모달 내용 -->
</div>
</template>
<script setup lang="ts">
import { BASE_Z_INDEX_KEY } from '@jennifersoft/vue-components-v2';
</script>
z-index 맵 구성하기
애플리케이션에서 사용할 z-index 맵은 다음과 같이 구성할 수 있습니다:
typescript
// zIndex.config.ts
import {
createZIndexMap,
BASE_Z_INDEX_KEY,
} from '@jennifersoft/vue-components-v2';
export const Z_INDEX_KEY = {
LICENSE: 'license',
...BASE_Z_INDEX_KEY, // 기본 제공되는 키 값 (TOOLTIP, MENU, DIALOG, MODAL, DRAWER)
POPUP: 'popup',
NAVIGATION_BAR: 'navigationBar',
NAVIGATION_PANEL: 'navigationPanel',
} as const;
export type ZIndexMap = (typeof Z_INDEX_KEY)[keyof typeof Z_INDEX_KEY];
export const zIndexMap = createZIndexMap(Z_INDEX_KEY);
전역 등록
v-z-index 디렉티브를 애플리케이션 전역에서 사용하려면 다음과 같이 등록합니다:
typescript
// index.ts 또는 main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { createZIndexDirective } from '@jennifersoft/vue-components-v2';
import { zIndexMap } from '@container/layer/zIndex.config';
const app = createApp(App);
app.directive('z-index', createZIndexDirective(zIndexMap));
app.mount('#app');
API
디렉티브 값 (binding.value)
v-z-index 디렉티브는 다음과 같은 값을 받을 수 있습니다:
타입 | 설명 |
---|---|
string | z-index 맵에 정의된 키 값 |
createZIndexDirective 함수
매개변수 | 타입 | 설명 |
---|---|---|
zMap | BaseZIndexMap | z-index 값이 정의된 맵 객체 |
createZIndexMap 함수
매개변수 | 타입 | 설명 |
---|---|---|
keyMap | Record<string, string> | z-index 키가 정의된 객체 |
작동 방식
createZIndexMap
함수는 키 맵을 받아 각 키에 대한 z-index 값을 계산합니다.- 키 맵의 순서에 따라 z-index 값이 할당되며, 객체에서 위에 정의된 키일수록 더 높은 z-index 값을 가집니다.
- 기본 z-index 값은 10000부터 시작하여 각 키마다 1000씩 증가합니다.
createZIndexDirective
함수는 z-index 맵을 받아 Vue 디렉티브를 생성합니다.- 디렉티브가 적용된 엘리먼트는 마운트 및 업데이트 시 해당하는 z-index 값이 style 속성으로 설정됩니다.
실제 사용 예시
DRAWER
MODAL
DIALOG
MENU
TOOLTIP
vue
<template>
<!-- BASE_Z_INDEX_KEY의 각 키를 사용한 예시 -->
<div class="z-index-demo">
<div v-z-index="BASE_Z_INDEX_KEY.DRAWER" class="z-index-box drawer">
DRAWER
</div>
<div v-z-index="BASE_Z_INDEX_KEY.MODAL" class="z-index-box modal">
MODAL
</div>
<div v-z-index="BASE_Z_INDEX_KEY.DIALOG" class="z-index-box dialog">
DIALOG
</div>
<div v-z-index="BASE_Z_INDEX_KEY.MENU" class="z-index-box menu">
MENU
</div>
<div v-z-index="BASE_Z_INDEX_KEY.TOOLTIP" class="z-index-box tooltip">
TOOLTIP
</div>
</div>
</template>
<script setup lang="ts">
import { BASE_Z_INDEX_KEY } from '@jennifersoft/vue-components-v2';
</script>
<style>
.z-index-demo {
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 100%;
height: 300px;
margin: 20px 0;
}
.z-index-box {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
width: 120px;
height: 80px;
border: 2px solid #333;
font-weight: bold;
color: white;
}
.drawer {
background-color: var(--gray-600);
left: 80px;
top: 20px;
}
.modal {
background-color: var(--gray-500);
left: 160px;
top: 40px;
}
.dialog {
background-color: var(--gray-400);
left: 240px;
top: 60px;
}
.menu {
background-color: var(--gray-300);
left: 320px;
top: 80px;
}
.tooltip {
background-color: var(--gray-200);
left: 400px;
top: 100px;
}
</style>
디렉티브 중첩 사용
v-z-index가 이미 내부에 적용된 컴포넌트에 외부에서 다시 v-z-index를 적용하면 외부에서 적용한 값이 우선합니다. 이를 활용하면 기존 컴포넌트의 z-index 값을 재정의할 수 있습니다.
예를 들어, OverlayMask 컴포넌트는 내부적으로 이미 v-z-index="BASE_Z_INDEX_KEY.MASK"가 적용되어 있지만, 외부에서 다른 z-index 값을 적용하면 외부 값이 우선합니다.
기본 OverlayMask (MASK z-index)
재정의된 OverlayMask (DIALOG z-index)
vue
<template>
<div class="example-container">
<OverlayMask class="mask-default">
기본 OverlayMask (MASK z-index)
</OverlayMask>
<OverlayMask
v-z-index="BASE_Z_INDEX_KEY.DIALOG"
class="mask-overridden"
>
재정의된 OverlayMask (DIALOG z-index)
</OverlayMask>
</div>
</template>
<script setup lang="ts">
import { OverlayMask, BASE_Z_INDEX_KEY } from '@jennifersoft/vue-components-v2';
</script>
<style scoped>
.example-container {
position: relative;
height: 200px;
width: 100%;
}
.mask-default,
.mask-overridden {
position: absolute;
color: white;
font-weight: bold;
border: 2px solid #333;
white-space: nowrap;
}
.mask-default {
background-color: rgba(0, 0, 0, 0.7);
left: 50px;
top: 30px;
}
.mask-overridden {
background-color: rgba(46, 139, 87, 0.8);
left: 150px;
top: 70px;
}
</style>
이 예제에서:
- 첫 번째 OverlayMask는 내부적으로 적용된
BASE_Z_INDEX_KEY.MASK
값을 사용합니다 (z-index: 10000). - 두 번째 OverlayMask는 외부에서
BASE_Z_INDEX_KEY.DIALOG
값을 적용하여 내부 값을 재정의합니다 (z-index: 13000).
이런 방식은 다음과 같은 상황에서 유용합니다:
- 기존 컴포넌트 라이브러리의 컴포넌트를 사용하면서 z-index를 재정의해야 하는 경우
- 동적으로 컴포넌트의 중첩 순서를 변경해야 하는 경우
- 특정 화면에서만 컴포넌트의 z-index 값을 일시적으로 변경해야 하는 경우
유의사항
- v-z-index 디렉티브를 사용하기 전에 반드시 z-index 맵을 구성하고 디렉티브를 최상위 파일에 등록해야 합니다.
- 최상위 파일에 등록하더라도, 파일에서 직접 vZIndex.ts를 import 하면 기본 z-index 값만 적용됩니다.
- 존재하지 않는 키 값을 사용하면 콘솔에 경고 메시지가 출력되고 z-index가 적용되지 않습니다.
- z-index 맵의 키 순서는 중요합니다. 객체에서 위에 정의된 키일수록 더 높은 z-index 값을 가집니다.
- 컴포넌트에 이미 v-z-index가 적용되어 있는 경우, 외부에서 다시 v-z-index를 적용하면 외부 값이 우선합니다.