Skip to content

Commit 09f0394

Browse files
committed
Close #3
1 parent 7d6f576 commit 09f0394

File tree

4 files changed

+203
-0
lines changed

4 files changed

+203
-0
lines changed

css/components/modal.css

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/* Base Modal Styling */
2+
.modal-overlay {
3+
position: fixed;
4+
top: 0;
5+
left: 0;
6+
width: 100%;
7+
height: 100%;
8+
background-color: rgba(0, 0, 0, 0.6); /* Slightly deeper background for better contrast */
9+
display: flex;
10+
justify-content: center;
11+
align-items: center;
12+
z-index: var(--z-50);
13+
opacity: 0;
14+
visibility: hidden;
15+
transition: opacity 0.35s ease, visibility 0.35s ease;
16+
backdrop-filter: blur(4px); /* Adds a modern blur effect */
17+
}
18+
19+
.modal-overlay.active {
20+
opacity: 1;
21+
visibility: visible;
22+
}
23+
24+
.modal {
25+
background-color: var(--neutral-50);
26+
border-radius: var(--radius-2xl); /* Softer, rounded corners */
27+
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3); /* Enhanced shadow for depth */
28+
max-width: clamp(20rem, 50vw, 40rem);
29+
width: 100%;
30+
position: relative;
31+
animation: modal-appear 0.4s cubic-bezier(0.25, 1, 0.5, 1);
32+
overflow: hidden;
33+
}
34+
35+
@keyframes modal-appear {
36+
from {
37+
transform: translateY(-20px);
38+
opacity: 0;
39+
}
40+
to {
41+
transform: translateY(0);
42+
opacity: 1;
43+
}
44+
}
45+
46+
/* Modal Header */
47+
.modal-header {
48+
padding: var(--space-4);
49+
background-color: var(--neutral-100);
50+
border-bottom: 1px solid var(--neutral-300);
51+
display: flex;
52+
justify-content: space-between;
53+
align-items: center;
54+
}
55+
56+
.modal-header.no-title {
57+
display: none;
58+
}
59+
60+
.modal-title {
61+
font-size: clamp(1.125rem, 2vw, 1.5rem);
62+
font-weight: 600;
63+
color: var(--neutral-900);
64+
letter-spacing: 0.5px; /* Slightly increased letter-spacing for elegance */
65+
}
66+
67+
.modal-close {
68+
background: none;
69+
border: none;
70+
font-size: 1.5rem;
71+
cursor: pointer;
72+
color: var(--neutral-700);
73+
transition: color 0.2s ease-in-out, transform 0.2s ease;
74+
}
75+
76+
.modal-close:hover {
77+
color: var(--danger);
78+
transform: scale(1.1); /* Slight enlargement for feedback */
79+
}
80+
81+
/* Modal Body */
82+
.modal-body {
83+
padding: var(--space-4);
84+
overflow-y: auto;
85+
max-height: 60vh;
86+
scrollbar-color: var(--primary) var(--neutral-200);
87+
scrollbar-width: thin;
88+
}
89+
90+
/* Custom Scrollbar */
91+
.modal-body::-webkit-scrollbar {
92+
width: 8px;
93+
background-color: var(--neutral-200);
94+
}
95+
96+
.modal-body::-webkit-scrollbar-thumb {
97+
background-color: var(--primary);
98+
border-radius: 4px;
99+
}
100+
101+
.modal-body::-webkit-scrollbar-track {
102+
background-color: var(--neutral-100);
103+
}
104+
105+
/* Modal Footer */
106+
.modal-footer {
107+
padding: var(--space-4);
108+
background-color: var(--neutral-100);
109+
border-top: 1px solid var(--neutral-300);
110+
text-align: right;
111+
}
112+
113+
/* Scrollable Modal */
114+
.modal-scrollable .modal-body {
115+
max-height: 70vh;
116+
padding-right: 1rem; /* Ensures space for custom scrollbar */
117+
}
118+
119+
/* Fullscreen Modal */
120+
.modal-fullscreen {
121+
width: 100%;
122+
height: 100%;
123+
border-radius: 0;
124+
max-width: none;
125+
max-height: none;
126+
}
127+
128+
/* Variants */
129+
.modal-primary { border-left: 5px solid var(--primary); }
130+
.modal-secondary { border-left: 5px solid var(--secondary); }
131+
.modal-success { border-left: 5px solid var(--success); }
132+
.modal-danger { border-left: 5px solid var(--danger); }
133+
.modal-warning { border-left: 5px solid var(--warning); }
134+
.modal-info { border-left: 5px solid var(--info); }
135+
136+
/* Animation for Modal Close */
137+
.modal-overlay.closing {
138+
opacity: 0;
139+
visibility: hidden;
140+
transition: opacity 0.2s ease, visibility 0.2s ease;
141+
}
142+
143+
/* Responsive Adjustments */
144+
@media (max-width: 768px) {
145+
.modal {
146+
max-width: 90vw;
147+
padding: var(--space-2);
148+
}
149+
150+
.modal-body {
151+
max-height: 50vh; /* Adjust for smaller screens */
152+
}
153+
}

css/main.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@
2929
@import './components/tooltip.css';
3030
@import './components/breadcrumbs.css';
3131
@import './components/toggle.css';
32+
@import './components/modal.css';

js/components/modal.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
export class Modal {
2+
constructor(modalId) {
3+
this.modal = document.getElementById(modalId);
4+
this.overlay = this.modal.closest('.modal-overlay');
5+
this.closeButton = this.modal.querySelector('.modal-close');
6+
7+
if (this.closeButton) {
8+
this.closeButton.addEventListener('click', () => this.close());
9+
}
10+
11+
this.overlay.addEventListener('click', (e) => {
12+
if (e.target === this.overlay && !this.overlay.classList.contains('no-close-on-outside-click')) {
13+
this.close();
14+
}
15+
});
16+
}
17+
18+
open() {
19+
this.overlay.classList.add('active');
20+
document.body.style.overflow = 'hidden'; // Prevent background scrolling
21+
}
22+
23+
close() {
24+
this.overlay.classList.remove('active');
25+
document.body.style.overflow = ''; // Restore background scrolling
26+
}
27+
28+
static initAll() {
29+
document.querySelectorAll('.modal-overlay').forEach((overlay) => {
30+
const modalId = overlay.querySelector('.modal').id;
31+
new Modal(modalId);
32+
});
33+
}
34+
}
35+
36+
// Initialize modals when the document is ready
37+
document.addEventListener('DOMContentLoaded', () => {
38+
Modal.initAll();
39+
40+
document.querySelectorAll('[data-toggle="modal"]').forEach((trigger) => {
41+
const targetId = trigger.dataset.target;
42+
trigger.addEventListener('click', () => {
43+
const modal = new Modal(targetId);
44+
modal.open();
45+
});
46+
});
47+
});

js/main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { toggleAccordion } from './components/accordion.js';
33
import { showHologram } from './components/hologram.js';
44
import { showTabContent } from './components/tabs.js';
55
import { showToast, showToastHistory, dismissToast, startAutoDismiss, pauseAllProgressBars, closeToastHistory } from './components/toast.js';
6+
import { Modal } from './components/modal.js'; // Import the Modal component
67

78
// Initialize alert close functionality
89
document.querySelectorAll('.alert-dismissible .alert-close').forEach(button => {
@@ -23,3 +24,4 @@ window.dismissToast = dismissToast;
2324
window.startAutoDismiss = startAutoDismiss;
2425
window.pauseAllProgressBars = pauseAllProgressBars;
2526
window.closeToastHistory = closeToastHistory;
27+
window.Modal = Modal; // Export the Modal class globally

0 commit comments

Comments
 (0)