Dialog 대화상자
중요한 정보를 표시하거나 조작을 확인하는 데 사용하는 모달 대화상자 컴포넌트입니다.
기본 사용법
기본 사용법
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'
const dialogVisible1 = ref(false)
</script>
<template>
<!-- 기본 사용법 -->
<LhButton @click="dialogVisible1 = true">대화상자 열기</LhButton>
<LhDialog v-model="dialogVisible1" title="알림">
<p>대화상자 내용입니다</p>
<template #footer>
<LhButton @click="dialogVisible1 = false">취소</LhButton>
<LhButton type="primary" @click="dialogVisible1 = false">확인</LhButton>
</template>
</LhDialog>
</template>vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'
export default {
components: { LhButton, LhDialog },
data() {
return {
dialogVisible1: false
}
}
}
</script>
<template>
<!-- 기본 사용법 -->
<LhButton @click="dialogVisible1 = true">대화상자 열기</LhButton>
<LhDialog v-model="dialogVisible1" title="알림">
<p>대화상자 내용입니다</p>
<template #footer>
<LhButton @click="dialogVisible1 = false">취소</LhButton>
<LhButton type="primary" @click="dialogVisible1 = false">확인</LhButton>
</template>
</LhDialog>
</template>너비와 높이 커스터마이징
너비 커스터마이징
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'
const dialogVisible2 = ref(false)
</script>
<template>
<!-- 너비와 높이 커스터마이징 -->
<LhButton @click="dialogVisible2 = true">큰 대화상자 열기</LhButton>
<LhDialog v-model="dialogVisible2" title="큰 대화상자" width="600px">
<p>크기를 커스터마이징한 대화상자</p>
<template #footer>
<LhButton @click="dialogVisible2 = false">닫기</LhButton>
</template>
</LhDialog>
</template>vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'
export default {
components: { LhButton, LhDialog },
data() {
return {
dialogVisible2: false
}
}
}
</script>
<template>
<!-- 너비와 높이 커스터마이징 -->
<LhButton @click="dialogVisible2 = true">큰 대화상자 열기</LhButton>
<LhDialog v-model="dialogVisible2" title="큰 대화상자" width="600px">
<p>크기를 커스터마이징한 대화상자</p>
<template #footer>
<LhButton @click="dialogVisible2 = false">닫기</LhButton>
</template>
</LhDialog>
</template>드래그
드래그
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'
const dialogVisible3 = ref(false)
</script>
<template>
<!-- 드래그 -->
<LhButton @click="dialogVisible3 = true">드래그 가능한 대화상자 열기</LhButton>
<LhDialog v-model="dialogVisible3" title="드래그 가능한 대화상자" draggable>
<p>제목 표시줄을 드래그하면 이 대화상자를 이동할 수 있습니다.</p>
<template #footer>
<LhButton @click="dialogVisible3 = false">닫기</LhButton>
</template>
</LhDialog>
</template>vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'
export default {
components: { LhButton, LhDialog },
data() {
return {
dialogVisible3: false
}
}
}
</script>
<template>
<!-- 드래그 -->
<LhButton @click="dialogVisible3 = true">드래그 가능한 대화상자 열기</LhButton>
<LhDialog v-model="dialogVisible3" title="드래그 가능한 대화상자" draggable>
<p>제목 표시줄을 드래그하면 이 대화상자를 이동할 수 있습니다.</p>
<template #footer>
<LhButton @click="dialogVisible3 = false">닫기</LhButton>
</template>
</LhDialog>
</template>커스텀 테마
대화상자에 커스텀 테마 색상을 적용합니다.
青花瓷(청화백자) 테마 대화상자
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhConfigProvider, LhButton, LhDialog } from '@lh-ui/vue3'
const dialogThemeVisible = ref(false)
const cerblueTheme = {
'primary-color': '#2B4C7C',
'primary-color-hover': '#3D649E',
'primary-color-bg': '#E8EDF3',
}
</script>
<template>
<LhConfigProvider :theme-vars="cerblueTheme">
<!-- 청화백자 테마 -->
<LhButton @click="dialogThemeVisible = true" type="primary">테마 대화상자 열기</LhButton>
<LhDialog v-model="dialogThemeVisible" title="청화백자 테마">
<p>이 대화상자는 청화백자 테마 색상을 사용합니다</p>
<template #footer>
<LhButton @click="dialogThemeVisible = false">닫기</LhButton>
</template>
</LhDialog>
</LhConfigProvider>
</template>vue
<script>
import { LhConfigProvider, LhButton, LhDialog } from '@lh-ui/vue3'
export default {
components: { LhConfigProvider, LhButton, LhDialog },
data() {
return {
dialogThemeVisible: false,
cerblueTheme: {
'primary-color': '#2B4C7C',
'primary-color-hover': '#3D649E',
'primary-color-bg': '#E8EDF3',
},
}
},
}
</script>
<template>
<LhConfigProvider :theme-vars="cerblueTheme">
<!-- 청화백자 테마 -->
<LhButton @click="dialogThemeVisible = true" type="primary">테마 대화상자 열기</LhButton>
<LhDialog v-model="dialogThemeVisible" title="청화백자 테마">
<p>이 대화상자는 청화백자 테마 색상을 사용합니다</p>
<template #footer>
<LhButton @click="dialogThemeVisible = false">닫기</LhButton>
</template>
</LhDialog>
</LhConfigProvider>
</template>테마에 대한 자세한 내용은 테마 커스터마이징을 참고하세요.
sx 빠른 레이아웃
sx 속성으로 Dialog의 크기와 간격을 빠르게 설정합니다.
sx 빠른 레이아웃
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'
const visible = ref(false)
</script>
<template>
<!-- 대화상자 열기 -->
<LhButton @click="visible = true">대화상자 열기</LhButton>
<!-- sx 레이아웃 대화상자 -->
<LhDialog v-model="visible" title="sx 레이아웃" :sx="{ maxWidth: 400 }">
<p>최대 너비를 설정했습니다</p>
<template #footer>
<LhButton @click="visible = false">취소</LhButton>
</template>
</LhDialog>
</template>vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'
export default {
components: { LhButton, LhDialog },
data() {
return { visible: false }
},
}
</script>
<template>
<!-- 대화상자 열기 -->
<LhButton @click="visible = true">대화상자 열기</LhButton>
<!-- sx 레이아웃 대화상자 -->
<LhDialog v-model="visible" title="sx 레이아웃" :sx="{ maxWidth: 400 }">
<p>최대 너비를 설정했습니다</p>
<template #footer>
<LhButton @click="visible = false">취소</LhButton>
</template>
</LhDialog>
</template>국제화
대화상자 글자는 LhConfigProvider와 언어 팩으로 국제화 전환을 구현할 수 있습니다.
국제화
vue
<script setup lang="ts">
import { ref, computed } from 'vue'
import { LhConfigProvider, LhButton, LhDialog, zhCN, enUS } from '@lh-ui/vue3'
const locale = ref('zh-CN')
const i18nVisible = ref(false)
const messages = computed(() => (locale.value === 'zh-CN' ? zhCN : enUS))
</script>
<template>
<LhConfigProvider :locale="messages">
<!-- 대화상자 열기 -->
<LhButton @click="i18nVisible = true">
{{ locale === 'zh-CN' ? '打开对话框' : 'Open Dialog' }}
</LhButton>
<!-- 국제화 대화상자 -->
<LhDialog v-model="i18nVisible" :title="locale === 'zh-CN' ? '提示' : 'Notice'">
<p>{{ locale === 'zh-CN' ? '对话框内容' : 'Dialog content' }}</p>
<template #footer>
<LhButton @click="i18nVisible = false">
{{ locale === 'zh-CN' ? '取消' : 'Cancel' }}
</LhButton>
</template>
</LhDialog>
</LhConfigProvider>
</template>vue
<script>
import { LhConfigProvider, LhButton, LhDialog, zhCN, enUS } from '@lh-ui/vue3'
export default {
components: { LhConfigProvider, LhButton, LhDialog },
data() {
return {
locale: 'zh-CN',
i18nVisible: false,
}
},
computed: {
messages() {
return this.locale === 'zh-CN' ? zhCN : enUS
},
},
}
</script>
<template>
<LhConfigProvider :locale="messages">
<!-- 대화상자 열기 -->
<LhButton @click="i18nVisible = true">
{{ locale === 'zh-CN' ? '打开对话框' : 'Open Dialog' }}
</LhButton>
<!-- 국제화 대화상자 -->
<LhDialog v-model="i18nVisible" :title="locale === 'zh-CN' ? '提示' : 'Notice'">
<p>{{ locale === 'zh-CN' ? '对话框内容' : 'Dialog content' }}</p>
<template #footer>
<LhButton @click="i18nVisible = false">
{{ locale === 'zh-CN' ? '取消' : 'Cancel' }}
</LhButton>
</template>
</LhDialog>
</LhConfigProvider>
</template>동작 스위치
닫기 방식 / 스크롤 잠금 / beforeClose
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'
const dialogAdv1 = ref(false)
const dialogAdv2 = ref(false)
const dialogAdv3 = ref(false)
function handleAdvBeforeClose(done: () => void) {
setTimeout(done, 500)
}
</script>
<template>
<!-- 버튼으로만 닫기 -->
<LhButton @click="dialogAdv1 = true">버튼으로만 닫기</LhButton>
<LhDialog
v-model="dialogAdv1"
title="버튼으로만 닫기"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
>
<p>오른쪽 위 닫기 버튼을 숨기고,오버레이를 클릭하거나 ESC를 눌러도 닫히지 않으며 하단 버튼으로만 닫을 수 있습니다.</p>
<template #footer>
<LhButton type="primary" @click="dialogAdv1 = false">확인했습니다</LhButton>
</template>
</LhDialog>
<!-- 스크롤 잠금 안 함 -->
<LhButton @click="dialogAdv2 = true">스크롤 잠금 안 함</LhButton>
<LhDialog v-model="dialogAdv2" title="스크롤 잠금 안 함" :lock-scroll="false">
<p>대화상자가 열려 있을 때도 페이지를 스크롤할 수 있어, 내용이 짧은 가벼운 알림에 적합합니다.</p>
</LhDialog>
<!-- 비동기 닫기 -->
<LhButton @click="dialogAdv3 = true">비동기 닫기</LhButton>
<LhDialog v-model="dialogAdv3" title="비동기 닫기" :before-close="handleAdvBeforeClose">
<p>오른쪽 위 닫기 버튼,오버레이 클릭 또는 ESC 누름 후 500ms 지연하고 실제로 닫힙니다(닫기 전 검증 시뮬레이션).</p>
</LhDialog>
</template>vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'
export default {
components: { LhButton, LhDialog },
data() {
return {
dialogAdv1: false,
dialogAdv2: false,
dialogAdv3: false,
}
},
methods: {
handleAdvBeforeClose(done) {
setTimeout(done, 500)
},
},
}
</script>
<template>
<!-- 버튼으로만 닫기 -->
<LhButton @click="dialogAdv1 = true">버튼으로만 닫기</LhButton>
<LhDialog
v-model="dialogAdv1"
title="버튼으로만 닫기"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
>
<p>오른쪽 위 닫기 버튼을 숨기고,오버레이를 클릭하거나 ESC를 눌러도 닫히지 않으며 하단 버튼으로만 닫을 수 있습니다.</p>
<template #footer>
<LhButton type="primary" @click="dialogAdv1 = false">확인했습니다</LhButton>
</template>
</LhDialog>
<!-- 스크롤 잠금 안 함 -->
<LhButton @click="dialogAdv2 = true">스크롤 잠금 안 함</LhButton>
<LhDialog v-model="dialogAdv2" title="스크롤 잠금 안 함" :lock-scroll="false">
<p>대화상자가 열려 있을 때도 페이지를 스크롤할 수 있어, 내용이 짧은 가벼운 알림에 적합합니다.</p>
</LhDialog>
<!-- 비동기 닫기 -->
<LhButton @click="dialogAdv3 = true">비동기 닫기</LhButton>
<LhDialog v-model="dialogAdv3" title="비동기 닫기" :before-close="handleAdvBeforeClose">
<p>오른쪽 위 닫기 버튼,오버레이 클릭 또는 ESC 누름 후 500ms 지연하고 실제로 닫힙니다(닫기 전 검증 시뮬레이션).</p>
</LhDialog>
</template>위치와 z-index
fullscreen / position / top / zIndex / center
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'
const dialogAdv4 = ref(false)
const dialogAdv5 = ref(false)
const dialogAdv6 = ref(false)
const dialogAdv7 = ref(false)
</script>
<template>
<!-- 전체 화면 -->
<LhButton @click="dialogAdv4 = true">전체 화면</LhButton>
<LhDialog v-model="dialogAdv4" title="전체 화면 대화상자" fullscreen>
<p>fullscreen일 때 대화상자가 뷰포트 전체를 채웁니다.</p>
</LhDialog>
<!-- 하단 위치 -->
<LhButton @click="dialogAdv5 = true">하단 위치</LhButton>
<LhDialog v-model="dialogAdv5" title="하단 위치" position="bottom">
<p>position이 bottom이면 대화상자가 뷰포트 하단에 가깝게 표시됩니다.</p>
</LhDialog>
<!-- 상단 오프셋 + z-index -->
<LhButton @click="dialogAdv6 = true">상단 오프셋 + z-index</LhButton>
<LhDialog v-model="dialogAdv6" title="상단 오프셋 + z-index" position="top" top="10vh" :z-index="3000">
<p>top으로 뷰포트 상단까지의 거리를 조정하고, z-index로 쌓임 순서를 제어합니다.</p>
</LhDialog>
<!-- 내용 가운데 정렬 -->
<LhButton @click="dialogAdv7 = true">내용 가운데 정렬(center)</LhButton>
<LhDialog v-model="dialogAdv7" title="내용 가운데 정렬" center>
<p>center는 제목과 내용을 가운데 정렬합니다(구버전 호환, 새 코드는 position 사용을 권장).</p>
<template #footer>
<LhButton @click="dialogAdv7 = false">취소</LhButton>
<LhButton type="primary" @click="dialogAdv7 = false">확인</LhButton>
</template>
</LhDialog>
</template>vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'
export default {
components: { LhButton, LhDialog },
data() {
return {
dialogAdv4: false,
dialogAdv5: false,
dialogAdv6: false,
dialogAdv7: false,
}
},
}
</script>
<template>
<!-- 전체 화면 -->
<LhButton @click="dialogAdv4 = true">전체 화면</LhButton>
<LhDialog v-model="dialogAdv4" title="전체 화면 대화상자" fullscreen>
<p>fullscreen일 때 대화상자가 뷰포트 전체를 채웁니다.</p>
</LhDialog>
<!-- 하단 위치 -->
<LhButton @click="dialogAdv5 = true">하단 위치</LhButton>
<LhDialog v-model="dialogAdv5" title="하단 위치" position="bottom">
<p>position이 bottom이면 대화상자가 뷰포트 하단에 가깝게 표시됩니다.</p>
</LhDialog>
<!-- 상단 오프셋 + z-index -->
<LhButton @click="dialogAdv6 = true">상단 오프셋 + z-index</LhButton>
<LhDialog v-model="dialogAdv6" title="상단 오프셋 + z-index" position="top" top="10vh" :z-index="3000">
<p>top으로 뷰포트 상단까지의 거리를 조정하고, z-index로 쌓임 순서를 제어합니다.</p>
</LhDialog>
<!-- 내용 가운데 정렬 -->
<LhButton @click="dialogAdv7 = true">내용 가운데 정렬(center)</LhButton>
<LhDialog v-model="dialogAdv7" title="내용 가운데 정렬" center>
<p>center는 제목과 내용을 가운데 정렬합니다(구버전 호환, 새 코드는 position 사용을 권장).</p>
<template #footer>
<LhButton @click="dialogAdv7 = false">취소</LhButton>
<LhButton type="primary" @click="dialogAdv7 = false">확인</LhButton>
</template>
</LhDialog>
</template>Dialog API
Props
| 속성 | 설명 | 타입 | 기본값 |
|---|---|---|---|
| modelValue | 대화상자 표시 여부 | boolean | false |
| title | 대화상자 제목 | string | '' |
| width | 대화상자 너비 | string | number | '480px' |
| fullscreen | 전체 화면 여부 | boolean | false |
| showClose | 닫기 버튼 표시 여부 | boolean | true |
| closeOnClickModal | 오버레이 클릭 시 닫기 여부 | boolean | true |
| closeOnPressEscape | ESC 누름 시 닫기 여부 | boolean | true |
| draggable | 드래그 가능 여부 | boolean | false |
| center | 가운데 정렬 여부(구버전 호환, position 사용을 권장) | boolean | false |
| position | 팝업 위치: top / center / bottom | "top" | "center" | "bottom" | 'center' |
| lockScroll | 스크롤 잠금 여부 | boolean | true |
| beforeClose | 닫기 전 콜백 | (done: () => void) => void | — |
| top | 상단 거리(px) | string | '15vh' |
| zIndex | z-index | number | — |
| themeVars | 컴포넌트 수준 테마 변수, ConfigProvider 설정을 덮어씀 | { [x: string]: string; } | — |
| bgPattern | 컴포넌트 수준 배경 문양, ConfigProvider 설정을 덮어씀 | string | — |
| sx | sx 빠른 레이아웃 속성 | LhSxProps | — |
Events
| 이벤트 | 설명 | 콜백 매개변수 |
|---|---|---|
| update:modelValue | 표시 상태 변경 | (value: boolean) |
| open | 열기 애니메이션 종료 | — |
| close | 닫기 애니메이션 종료 | — |
| opened | 대화상자가 완전히 열린 후 발생 | — |
| closed | 대화상자가 완전히 닫힌 후 발생 | — |
Slots
| 슬롯 | 설명 |
|---|---|
| default | 대화상자 내용 |
| header | 대화상자 제목 영역 |
| footer | 대화상자 하단 영역 |
타입 정의
이 컴포넌트가 외부로 내보내는 TypeScript 타입 구조는 다음과 같습니다(packages/components/dialog/src/types.ts와 @lh-ui/share/core/* 소스에서 자동 추출, 각 항목을 펼쳐 전체 정의를 확인하세요. 속성 설명은 위쪽 Props 표를 참고하세요).
LhDialogProps
ts
/**
* Dialog 컴포넌트 Props
*/
export interface LhDialogProps {
/** 표시 여부 */
modelValue?: boolean
/** 제목 */
title?: string
/** 너비 */
width?: string | number
/** 전체 화면 여부 */
fullscreen?: boolean
/** 닫기 버튼 표시 여부 */
showClose?: boolean
/**오버레이 클릭 시 닫기 여부 */
closeOnClickModal?: boolean
/** ESC 누름 시 닫기 여부 */
closeOnPressEscape?: boolean
/** 드래그 가능 여부 */
draggable?: boolean
/** 가운데 정렬 여부(구버전 호환, position 사용을 권장) */
center?: boolean
/** 팝업 위치: top / center / bottom */
position?: 'top' | 'center' | 'bottom'
/** 스크롤 잠금 여부 */
lockScroll?: boolean
/** 닫기 전 콜백 */
beforeClose?: (done: () => void) => void
/** 상단 거리(px) */
top?: string
/** z-index */
zIndex?: number
/** 컴포넌트 수준 테마 변수, ConfigProvider 설정을 덮어씀 */
themeVars?: Record<string, string>
/** 컴포넌트 수준 배경 문양, ConfigProvider 설정을 덮어씀 */
bgPattern?: string
/** sx 빠른 레이아웃 속성 */
sx?: LhSxProps
}