🎨 Refactor code style for consistency and readability in BaseModal component

This commit is contained in:
2026-01-28 22:24:11 +00:00
parent 94b1828c88
commit 4cb66eafbd

View File

@@ -60,7 +60,7 @@ const props = defineProps({
type: Boolean, type: Boolean,
required: true required: true
}, },
/** /**
* Modal title (alternative to header slot) * Modal title (alternative to header slot)
*/ */
@@ -68,7 +68,7 @@ const props = defineProps({
type: String, type: String,
default: null default: null
}, },
/** /**
* Modal size * Modal size
* @type {'small' | 'medium' | 'large' | 'full'} * @type {'small' | 'medium' | 'large' | 'full'}
@@ -76,9 +76,9 @@ const props = defineProps({
size: { size: {
type: String, type: String,
default: 'medium', default: 'medium',
validator: (value) => ['small', 'medium', 'large', 'full'].includes(value) validator: value => ['small', 'medium', 'large', 'full'].includes(value)
}, },
/** /**
* Whether clicking overlay closes the modal * Whether clicking overlay closes the modal
*/ */
@@ -86,7 +86,7 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: true default: true
}, },
/** /**
* Whether modal can be closed (hides X button, prevents ESC/overlay close) * Whether modal can be closed (hides X button, prevents ESC/overlay close)
*/ */
@@ -94,7 +94,7 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false default: false
}, },
/** /**
* Whether to show the close X button * Whether to show the close X button
*/ */
@@ -123,7 +123,7 @@ const handleOverlayClick = () => {
} }
}; };
const handleEscapeKey = (event) => { const handleEscapeKey = event => {
if (event.key === 'Escape' && props.modelValue && !props.persistent) { if (event.key === 'Escape' && props.modelValue && !props.persistent) {
handleClose(); handleClose();
} }
@@ -132,7 +132,7 @@ const handleEscapeKey = (event) => {
// Focus management // Focus management
const getFocusableElements = () => { const getFocusableElements = () => {
if (!modalRef.value) return []; if (!modalRef.value) return [];
const focusableSelectors = [ const focusableSelectors = [
'a[href]', 'a[href]',
'area[href]', 'area[href]',
@@ -143,21 +143,21 @@ const getFocusableElements = () => {
'[tabindex]:not([tabindex="-1"])', '[tabindex]:not([tabindex="-1"])',
'[contenteditable="true"]' '[contenteditable="true"]'
]; ];
return Array.from( return Array.from(
modalRef.value.querySelectorAll(focusableSelectors.join(',')) modalRef.value.querySelectorAll(focusableSelectors.join(','))
); );
}; };
const handleTabKey = (event) => { const handleTabKey = event => {
if (!props.modelValue) return; if (!props.modelValue) return;
const focusableElements = getFocusableElements(); const focusableElements = getFocusableElements();
if (focusableElements.length === 0) return; if (focusableElements.length === 0) return;
const firstElement = focusableElements[0]; const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1]; const lastElement = focusableElements[focusableElements.length - 1];
if (event.shiftKey) { if (event.shiftKey) {
// Shift + Tab: move focus backwards // Shift + Tab: move focus backwards
if (document.activeElement === firstElement) { if (document.activeElement === firstElement) {
@@ -173,7 +173,7 @@ const handleTabKey = (event) => {
} }
}; };
const handleKeyDown = (event) => { const handleKeyDown = event => {
if (event.key === 'Escape') { if (event.key === 'Escape') {
handleEscapeKey(event); handleEscapeKey(event);
} else if (event.key === 'Tab') { } else if (event.key === 'Tab') {
@@ -182,32 +182,35 @@ const handleKeyDown = (event) => {
}; };
// Lifecycle hooks // Lifecycle hooks
watch(() => props.modelValue, async (newValue) => { watch(
if (newValue) { () => props.modelValue,
// Modal opened async newValue => {
previousActiveElement.value = document.activeElement; if (newValue) {
document.body.style.overflow = 'hidden'; // Modal opened
emit('open'); previousActiveElement.value = document.activeElement;
document.body.style.overflow = 'hidden';
// Focus first focusable element after render emit('open');
await nextTick();
const focusableElements = getFocusableElements(); // Focus first focusable element after render
if (focusableElements.length > 0) { await nextTick();
focusableElements[0].focus(); const focusableElements = getFocusableElements();
} else if (modalRef.value) { if (focusableElements.length > 0) {
modalRef.value.focus(); focusableElements[0].focus();
} } else if (modalRef.value) {
} else { modalRef.value.focus();
// Modal closed }
document.body.style.overflow = ''; } else {
// Modal closed
// Restore focus to previous element document.body.style.overflow = '';
if (previousActiveElement.value) {
previousActiveElement.value.focus(); // Restore focus to previous element
previousActiveElement.value = null; if (previousActiveElement.value) {
previousActiveElement.value.focus();
previousActiveElement.value = null;
}
} }
} }
}); );
onMounted(() => { onMounted(() => {
document.addEventListener('keydown', handleKeyDown); document.addEventListener('keydown', handleKeyDown);
@@ -244,7 +247,9 @@ onBeforeUnmount(() => {
.modal-container { .modal-container {
background: white; background: white;
border-radius: 0.5rem; border-radius: 0.5rem;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); box-shadow:
0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04);
max-height: 90vh; max-height: 90vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;