Dialog Component Design Documentation
Overview
The Dialog component is a core component in this library used for displaying modal dialogs. It adheres to the library's consistent design philosophy of "Separation of Concerns" and "Logic Abstraction." Through core mechanisms like useDialog and Teleport, it provides a complete and user-friendly dialog solution.
The Dialog component focuses on handling modal dialog display, interaction, and style management, offering users a powerful and flexible dialog management feature. It supports custom content, sizing, animation effects, and interaction behaviors, effectively enhancing the user experience in critical operation scenarios.
Design Philosophy
Layered Architecture
The Dialog component is strictly designed with a three-layer architecture:
- Structure Layer (
dialog.vue) - Responsible for the component's DOM structure and basic layout. - Logic Layer (
dialogComputed.ts) - Handles complex reactive computations and interaction logic. - Presentation Layer (
dialog.scss) - Defines the component's visual presentation and style rules.
Logic Abstraction
The Dialog component abstracts complex logic into core functions:
useDialog- Handles core dialog logic.useStyleComputed- Handles dynamic style computation.useClassComputed- Handles dynamic class name generation.
This design allows the component itself to simply declare the required logic, while the specific computations are handled by the logic functions.
Core Feature Design
Structured Props Design
The props design for the Dialog component is clean and straightforward:
export const dialogProps = {
/** Controls dialog visibility */
modelValue: {
type: Boolean,
default: false
},
/** Dialog title */
title: {
type: String,
default: ''
},
/** Dialog width */
width: {
type: [String, Number] as PropType<string | number>,
default: 400
},
/** Dialog height */
height: {
type: [String, Number] as PropType<string | number>,
default: 200
},
/** Whether clicking the overlay closes the dialog */
closeOnClickModal: {
type: Boolean,
default: true
},
/** Whether pressing Esc key closes the dialog */
closeOnPressEscape: {
type: Boolean,
default: true
},
/** Background color */
backgroundColor: {
type: String,
default: ''
},
/** Border color */
borderColor: {
type: String,
default: ''
},
/** Text color */
textColor: {
type: String,
default: ''
},
/** Whether to allow overflow */
overflow: {
type: Boolean,
default: false
}
}Parameter Descriptions:
- modelValue: Controls the visibility state of the dialog.
- title: The title text of the dialog.
- width and height: Control the dimensions of the dialog.
- closeOnClickModal: Controls whether clicking the overlay closes the dialog.
- closeOnPressEscape: Controls whether pressing Esc key closes the dialog.
- backgroundColor, borderColor, textColor: Support custom styling.
- overflow: Controls content overflow behavior.
Event System
The Dialog component provides rich event support:
export interface DialogEmits {
(e: 'update:modelValue', value: boolean): void
(e: 'open'): void
(e: 'close'): void
}Event Descriptions:
· update:modelValue: Triggered when dialog visibility state changes. · open: Triggered when the dialog opens. · close: Triggered when the dialog closes.
Style System Design
CSS Variable Control
The Dialog component achieves style control through CSS variables:
- --dialog-bg-color - Dialog background color.
- --dialog-text-color - Dialog text color.
- --overlay-bg-color - Overlay background color.
Layout System
The Dialog component supports flexible layout control:
- Modal Window - Uses Teleport to render the dialog under body.
- Centered Positioning - Uses Flexbox for vertical and horizontal centering.
- Dimension Control - Controls dialog dimensions via width and height properties.
State Styles
The Dialog component provides corresponding styles for different states:
- Open State - Fade-in animation.
- Closed State - Fade-out animation.
- Overflow State - Controls content overflow behavior via the overflow property.
Component Structure Design
Overall Structure
The overall structure of the Dialog component is as follows:
<Teleport to="body">
<Transition name="dialog-fade">
<div v-if="visible" class="my-overlay" @click.self="handleOverlayClick">
<div class="my-dialog" role="dialog" aria-modal="true" :style="dialogStyle" :class="dialogClass">
<header class="my-dialog__header">
<slot name="header">
<span class="my-dialog__title">{{ props.title }}</span>
</slot>
<button class="my-dialog__close" @click="close">×</button>
</header>
<div class="my-dialog__body">
<slot />
</div>
<footer class="my-dialog__footer" v-if="$slots.footer">
<slot name="footer" />
</footer>
</div>
</div>
</Transition>
</Teleport>Component Hierarchy
The Dialog component consists of four main parts:
- Overlay - .my-overlay - A semi-transparent background covering the entire viewport.
- Dialog Container - .my-dialog - Wraps the entire dialog.
- Dialog Header - .my-dialog__header - Contains the title and close button.
- Dialog Body - .my-dialog__body - Contains the main content.
- Dialog Footer - .my-dialog__footer - Contains action buttons.
Interaction Design
Dialog Visibility
The Dialog component controls visibility via modelValue:
const visible = ref(props.modelValue)
watch(
() => props.modelValue,
(val) => {
visible.value = val
if (val) emit('open')
}
)Overlay Click Handling
The Dialog component supports closing via overlay click:
const handleOverlayClick = () => {
if (props.closeOnClickModal) close()
}Keyboard Event Handling
The Dialog component supports closing via Esc key:
const handleKeydown = (e: KeyboardEvent) => {
if (e.key === 'Escape' && props.closeOnPressEscape) close()
}
onMounted(() => {
document.addEventListener('keydown', handleKeydown)
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', handleKeydown)
})Animation Effects
The Dialog component uses Vue's Transition component for fade animations:
.dialog-fade-enter-active,
.dialog-fade-leave-active {
transition: opacity 0.2s ease;
}
.dialog-fade-enter-from,
.dialog-fade-leave-to {
opacity: 0;
}Extensibility Design
The Dialog component offers excellent extensibility:
- Slot Support: Supports custom header, body, and footer via slots. · header: Custom dialog header. · Default slot: Custom dialog content. · footer: Custom dialog footer.
- Style Customization: Supports custom background, text colors via props.
- Interaction Configuration: Controls closing behavior via props.
- Dimension Control: Flexibly adjusts dialog dimensions via width and height properties.
Style Details
The Dialog component features the following style handling characteristics:
- Responsive Design: Supports flexible layout adaptation.
- Consistency: Maintains style consistency with other library components.
- Accessibility Design: Complies with WAI-ARIA specifications. · Sets role="dialog" and aria-modal="true". · Supports keyboard navigation.
- Animation Effects: Smooth show/hide effects using CSS transitions.
Performance Optimization
Performance is optimized through:
- Using
Teleportto avoid layout nesting issues. - Moving complex logic into independent functions.
- Avoiding unnecessary re-renders.
- Leveraging Vue 3 Composition API for runtime efficiency.
- Listening to and removing keyboard events on demand.
- Using CSS animations instead of JavaScript animations.
Design Value
The Dialog component embodies the design philosophy of our component library:
- Separation of Concerns: Complete decoupling of structure, style, and logic.
- High Reusability: Abstracting common logic via functions.
- Ease of Maintenance: Clear code structure and naming conventions.
- Strong Extensibility: Support for rich customization options.
- Consistency: Maintains a consistent design language with other components like Modal and Popover.