@magic-spells/dialog-panel 0.1.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -8
- package/dist/dialog-panel.cjs.js +161 -218
- package/dist/dialog-panel.cjs.js.map +1 -1
- package/dist/dialog-panel.css +71 -0
- package/dist/dialog-panel.esm.js +161 -218
- package/dist/dialog-panel.esm.js.map +1 -1
- package/dist/dialog-panel.js +511 -0
- package/dist/dialog-panel.js.map +1 -0
- package/dist/dialog-panel.min.css +1 -1
- package/dist/dialog-panel.min.js +1 -1
- package/dist/dialog-panel.scss +2 -0
- package/dist/scss/dialog-panel.scss +73 -0
- package/dist/scss/variables.scss +54 -0
- package/package.json +10 -4
- package/src/dialog-panel.js +174 -40
- package/src/index.scss +2 -0
- package/src/scss/dialog-panel.scss +73 -0
- package/src/scss/variables.scss +54 -0
- package/src/dialog-panel.css +0 -47
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Import variables using the modern @use rule
|
|
2
|
+
@use 'variables' as vars;
|
|
3
|
+
|
|
4
|
+
dialog-panel {
|
|
5
|
+
/* Make it take no space and be invisible in the document flow */
|
|
6
|
+
display: contents;
|
|
7
|
+
|
|
8
|
+
&[aria-hidden='false'] {
|
|
9
|
+
dialog-overlay,
|
|
10
|
+
dialog-content {
|
|
11
|
+
pointer-events: auto;
|
|
12
|
+
opacity: 1;
|
|
13
|
+
transform: scale(1);
|
|
14
|
+
filter: blur(0px);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Overlay background */
|
|
20
|
+
dialog-overlay {
|
|
21
|
+
position: fixed;
|
|
22
|
+
top: 0;
|
|
23
|
+
left: 0;
|
|
24
|
+
width: 100vw;
|
|
25
|
+
height: 100vh;
|
|
26
|
+
opacity: 0;
|
|
27
|
+
pointer-events: none;
|
|
28
|
+
z-index: var(--dp-overlay-z-index, 1000);
|
|
29
|
+
transition: var(--dp-overlay-transition, all 300ms ease-out);
|
|
30
|
+
background-color: var(
|
|
31
|
+
--dp-overlay-background,
|
|
32
|
+
rgba(20, 23, 26, 0.4)
|
|
33
|
+
);
|
|
34
|
+
backdrop-filter: var(
|
|
35
|
+
--dp-overlay-backdrop-filter,
|
|
36
|
+
blur(2px) saturate(120%)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
dialog-content {
|
|
41
|
+
position: fixed;
|
|
42
|
+
top: 50%;
|
|
43
|
+
left: 50%;
|
|
44
|
+
transform: translate(-50%, -50%) scale(0.95);
|
|
45
|
+
max-width: 90vw;
|
|
46
|
+
max-height: 85vh;
|
|
47
|
+
display: var(--dp-content-display, block);
|
|
48
|
+
opacity: 0;
|
|
49
|
+
background: var(--dp-content-background, white);
|
|
50
|
+
pointer-events: none;
|
|
51
|
+
z-index: var(--dp-content-z-index, 1001);
|
|
52
|
+
box-shadow: var(
|
|
53
|
+
--dp-content-shadow,
|
|
54
|
+
0 10px 25px rgba(0, 0, 0, 0.15)
|
|
55
|
+
);
|
|
56
|
+
border-radius: var(--dp-content-border-radius, 8px);
|
|
57
|
+
overflow: auto;
|
|
58
|
+
transition:
|
|
59
|
+
opacity var(--dp-transition-duration, 300ms)
|
|
60
|
+
var(--dp-transition-timing, ease-out),
|
|
61
|
+
transform var(--dp-transition-duration, 300ms)
|
|
62
|
+
var(--dp-transition-timing, ease-out);
|
|
63
|
+
|
|
64
|
+
/* When shown, reset transform to center */
|
|
65
|
+
dialog-panel[aria-hidden='false'] & {
|
|
66
|
+
transform: translate(-50%, -50%) scale(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* When explicitly hidden, remove from layout */
|
|
70
|
+
&.hidden {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Dialog Panel variables
|
|
2
|
+
// SCSS variables for internal component use and customization
|
|
3
|
+
// These variables can be customized by the user
|
|
4
|
+
|
|
5
|
+
// Layout
|
|
6
|
+
$panel-top: 0 !default;
|
|
7
|
+
$panel-left: 0 !default;
|
|
8
|
+
$panel-width: 100vw !default;
|
|
9
|
+
$panel-height: 100vh !default;
|
|
10
|
+
$panel-z-index: 10 !default;
|
|
11
|
+
|
|
12
|
+
// Overlay
|
|
13
|
+
$overlay-z-index: 1000 !default;
|
|
14
|
+
$overlay-background: rgba(20, 23, 26, 0.4) !default;
|
|
15
|
+
$overlay-backdrop-filter: blur(2px) saturate(120%) !default;
|
|
16
|
+
$overlay-transition: all 400ms ease-out !default;
|
|
17
|
+
|
|
18
|
+
// Content
|
|
19
|
+
$content-display: block !default;
|
|
20
|
+
$content-background: white !default;
|
|
21
|
+
$content-z-index: 1001 !default;
|
|
22
|
+
$content-shadow: 0 10px 25px rgba(0, 0, 0, 0.15) !default;
|
|
23
|
+
$content-border-radius: 8px !default;
|
|
24
|
+
|
|
25
|
+
// Animation
|
|
26
|
+
$transition-duration: 400ms !default;
|
|
27
|
+
$transition-timing: ease-out !default;
|
|
28
|
+
|
|
29
|
+
// Define CSS Custom Properties using SCSS values
|
|
30
|
+
:root {
|
|
31
|
+
// Layout
|
|
32
|
+
--dp-panel-top: #{$panel-top};
|
|
33
|
+
--dp-panel-left: #{$panel-left};
|
|
34
|
+
--dp-panel-width: #{$panel-width};
|
|
35
|
+
--dp-panel-height: #{$panel-height};
|
|
36
|
+
--dp-panel-z-index: #{$panel-z-index};
|
|
37
|
+
|
|
38
|
+
// Overlay
|
|
39
|
+
--dp-overlay-z-index: #{$overlay-z-index};
|
|
40
|
+
--dp-overlay-background: #{$overlay-background};
|
|
41
|
+
--dp-overlay-backdrop-filter: #{$overlay-backdrop-filter};
|
|
42
|
+
--dp-overlay-transition: #{$overlay-transition};
|
|
43
|
+
|
|
44
|
+
// Content
|
|
45
|
+
--dp-content-display: #{$content-display};
|
|
46
|
+
--dp-content-background: #{$content-background};
|
|
47
|
+
--dp-content-z-index: #{$content-z-index};
|
|
48
|
+
--dp-content-shadow: #{$content-shadow};
|
|
49
|
+
--dp-content-border-radius: #{$content-border-radius};
|
|
50
|
+
|
|
51
|
+
// Animation
|
|
52
|
+
--dp-transition-duration: #{$transition-duration};
|
|
53
|
+
--dp-transition-timing: #{$transition-timing};
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magic-spells/dialog-panel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A lightweight, customizable Dialog Panel web component for creating accessible and responsive modal dialogs.",
|
|
5
5
|
"author": "Cory Schulz",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,13 +9,17 @@
|
|
|
9
9
|
"module": "dist/dialog-panel.esm.js",
|
|
10
10
|
"unpkg": "dist/dialog-panel.min.js",
|
|
11
11
|
"style": "dist/dialog-panel.min.css",
|
|
12
|
+
"sass": "dist/dialog-panel.scss",
|
|
12
13
|
"exports": {
|
|
13
14
|
".": {
|
|
14
15
|
"import": "./dist/dialog-panel.esm.js",
|
|
15
16
|
"require": "./dist/dialog-panel.cjs.js",
|
|
16
17
|
"default": "./dist/dialog-panel.esm.js"
|
|
17
18
|
},
|
|
18
|
-
"./
|
|
19
|
+
"./css": "./dist/dialog-panel.css",
|
|
20
|
+
"./css/min": "./dist/dialog-panel.min.css",
|
|
21
|
+
"./scss": "./dist/dialog-panel.scss",
|
|
22
|
+
"./scss/*": "./dist/scss/*"
|
|
19
23
|
},
|
|
20
24
|
"sideEffects": true,
|
|
21
25
|
"repository": {
|
|
@@ -46,7 +50,8 @@
|
|
|
46
50
|
"lint": "eslint src/ rollup.config.mjs",
|
|
47
51
|
"format": "prettier --write .",
|
|
48
52
|
"prepublishOnly": "npm run build",
|
|
49
|
-
"serve": "rollup -c --watch"
|
|
53
|
+
"serve": "rollup -c --watch",
|
|
54
|
+
"dev": "rollup -c --watch"
|
|
50
55
|
},
|
|
51
56
|
"publishConfig": {
|
|
52
57
|
"access": "public",
|
|
@@ -67,7 +72,8 @@
|
|
|
67
72
|
"rollup": "^3.0.0",
|
|
68
73
|
"rollup-plugin-copy": "^3.5.0",
|
|
69
74
|
"rollup-plugin-postcss": "^4.0.2",
|
|
70
|
-
"rollup-plugin-serve": "^1.1.1"
|
|
75
|
+
"rollup-plugin-serve": "^1.1.1",
|
|
76
|
+
"sass": "^1.86.3"
|
|
71
77
|
},
|
|
72
78
|
"dependencies": {
|
|
73
79
|
"@magic-spells/focus-trap": "^1.0.6"
|
package/src/dialog-panel.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './index.scss';
|
|
2
2
|
import '@magic-spells/focus-trap';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -6,6 +6,53 @@ import '@magic-spells/focus-trap';
|
|
|
6
6
|
* @extends HTMLElement
|
|
7
7
|
*/
|
|
8
8
|
class DialogPanel extends HTMLElement {
|
|
9
|
+
#handleTransitionEnd;
|
|
10
|
+
#scrollPosition = 0;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Clean up event listeners when component is removed from DOM
|
|
14
|
+
*/
|
|
15
|
+
disconnectedCallback() {
|
|
16
|
+
const _ = this;
|
|
17
|
+
if (_.contentPanel) {
|
|
18
|
+
_.contentPanel.removeEventListener(
|
|
19
|
+
'transitionend',
|
|
20
|
+
_.#handleTransitionEnd
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Ensure body scroll is restored if component is removed while open
|
|
25
|
+
document.body.classList.remove('overflow-hidden');
|
|
26
|
+
this.#restoreScroll();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Saves current scroll position and locks body scrolling
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
#lockScroll() {
|
|
34
|
+
const _ = this;
|
|
35
|
+
// Save current scroll position
|
|
36
|
+
_.#scrollPosition = window.pageYOffset;
|
|
37
|
+
|
|
38
|
+
// Apply fixed position to body
|
|
39
|
+
document.body.classList.add('overflow-hidden');
|
|
40
|
+
document.body.style.top = `-${_.#scrollPosition}px`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Restores scroll position when dialog is closed
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
#restoreScroll() {
|
|
48
|
+
const _ = this;
|
|
49
|
+
// Remove fixed positioning
|
|
50
|
+
document.body.classList.remove('overflow-hidden');
|
|
51
|
+
document.body.style.removeProperty('top');
|
|
52
|
+
|
|
53
|
+
// Restore scroll position
|
|
54
|
+
window.scrollTo(0, _.#scrollPosition);
|
|
55
|
+
}
|
|
9
56
|
/**
|
|
10
57
|
* Initializes the dialog panel, sets up focus trap and overlay
|
|
11
58
|
*/
|
|
@@ -21,6 +68,24 @@ class DialogPanel extends HTMLElement {
|
|
|
21
68
|
_.focusTrap = document.createElement('focus-trap');
|
|
22
69
|
_.triggerEl = null;
|
|
23
70
|
|
|
71
|
+
// Create a handler for transition end events
|
|
72
|
+
_.#handleTransitionEnd = (e) => {
|
|
73
|
+
if (
|
|
74
|
+
e.propertyName === 'opacity' &&
|
|
75
|
+
_.getAttribute('aria-hidden') === 'true'
|
|
76
|
+
) {
|
|
77
|
+
_.contentPanel.classList.add('hidden');
|
|
78
|
+
|
|
79
|
+
// Dispatch afterHide event - dialog has completed its transition
|
|
80
|
+
_.dispatchEvent(
|
|
81
|
+
new CustomEvent('afterHide', {
|
|
82
|
+
bubbles: true,
|
|
83
|
+
detail: { triggerElement: _.triggerEl },
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
24
89
|
// Ensure we have labelledby and describedby references
|
|
25
90
|
if (!_.getAttribute('aria-labelledby')) {
|
|
26
91
|
const heading = _.querySelector('h1, h2, h3');
|
|
@@ -51,26 +116,31 @@ class DialogPanel extends HTMLElement {
|
|
|
51
116
|
* @private
|
|
52
117
|
*/
|
|
53
118
|
#bindUI() {
|
|
119
|
+
const _ = this;
|
|
120
|
+
|
|
54
121
|
// Handle trigger buttons
|
|
55
122
|
document.addEventListener('click', (e) => {
|
|
56
|
-
const trigger = e.target.closest(
|
|
57
|
-
`[aria-controls="${this.id}"]`
|
|
58
|
-
);
|
|
123
|
+
const trigger = e.target.closest(`[aria-controls="${_.id}"]`);
|
|
59
124
|
if (!trigger) return;
|
|
60
125
|
|
|
61
126
|
if (trigger.getAttribute('data-prevent-default') === 'true') {
|
|
62
127
|
e.preventDefault();
|
|
63
128
|
}
|
|
64
129
|
|
|
65
|
-
|
|
66
|
-
this.show(trigger);
|
|
130
|
+
_.show(trigger);
|
|
67
131
|
});
|
|
68
132
|
|
|
69
133
|
// Handle close buttons
|
|
70
|
-
|
|
134
|
+
_.addEventListener('click', (e) => {
|
|
71
135
|
if (!e.target.closest('[data-action="hide-dialog"]')) return;
|
|
72
|
-
|
|
136
|
+
_.hide();
|
|
73
137
|
});
|
|
138
|
+
|
|
139
|
+
// Add transition end listener
|
|
140
|
+
_.contentPanel.addEventListener(
|
|
141
|
+
'transitionend',
|
|
142
|
+
_.#handleTransitionEnd
|
|
143
|
+
);
|
|
74
144
|
}
|
|
75
145
|
|
|
76
146
|
/**
|
|
@@ -88,50 +158,108 @@ class DialogPanel extends HTMLElement {
|
|
|
88
158
|
/**
|
|
89
159
|
* Shows the dialog and traps focus within it
|
|
90
160
|
* @param {HTMLElement} [triggerEl=null] - The element that triggered the dialog
|
|
161
|
+
* @fires DialogPanel#beforeShow - Fired before the dialog starts to show
|
|
162
|
+
* @fires DialogPanel#show - Fired when the dialog has been shown
|
|
163
|
+
* @returns {boolean} False if the show was prevented by a beforeShow event handler
|
|
91
164
|
*/
|
|
92
165
|
show(triggerEl = null) {
|
|
93
|
-
|
|
166
|
+
const _ = this;
|
|
167
|
+
_.triggerEl = triggerEl || false;
|
|
94
168
|
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
169
|
+
// Dispatch beforeShow event - allows preventing the dialog from opening
|
|
170
|
+
const beforeShowEvent = new CustomEvent('beforeShow', {
|
|
171
|
+
bubbles: true,
|
|
172
|
+
cancelable: true,
|
|
173
|
+
detail: { triggerElement: _.triggerEl },
|
|
174
|
+
});
|
|
100
175
|
|
|
101
|
-
|
|
102
|
-
document.body.classList.add('overflow-hidden');
|
|
176
|
+
const showAllowed = _.dispatchEvent(beforeShowEvent);
|
|
103
177
|
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
178
|
+
// If event was canceled (preventDefault was called), don't show the dialog
|
|
179
|
+
if (!showAllowed) return false;
|
|
180
|
+
|
|
181
|
+
// Remove the hidden class first to ensure content is rendered
|
|
182
|
+
_.contentPanel.classList.remove('hidden');
|
|
183
|
+
|
|
184
|
+
// Give the browser a moment to process before starting animation
|
|
185
|
+
requestAnimationFrame(() => {
|
|
186
|
+
// Update ARIA states
|
|
187
|
+
_.setAttribute('aria-hidden', 'false');
|
|
188
|
+
if (_.triggerEl) {
|
|
189
|
+
_.triggerEl.setAttribute('aria-expanded', 'true');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Lock body scrolling and save scroll position
|
|
193
|
+
_.#lockScroll();
|
|
194
|
+
|
|
195
|
+
// Focus management
|
|
196
|
+
const firstFocusable = _.querySelector(
|
|
197
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
198
|
+
);
|
|
199
|
+
if (firstFocusable) {
|
|
200
|
+
requestAnimationFrame(() => {
|
|
201
|
+
firstFocusable.focus();
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Dispatch show event - dialog is now visible
|
|
206
|
+
_.dispatchEvent(
|
|
207
|
+
new CustomEvent('show', {
|
|
208
|
+
bubbles: true,
|
|
209
|
+
detail: { triggerElement: _.triggerEl },
|
|
210
|
+
})
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
return true;
|
|
113
215
|
}
|
|
114
216
|
|
|
115
217
|
/**
|
|
116
218
|
* Hides the dialog and restores focus
|
|
219
|
+
* @fires DialogPanel#beforeHide - Fired before the dialog starts to hide
|
|
220
|
+
* @fires DialogPanel#hide - Fired when the dialog has started hiding (transition begins)
|
|
221
|
+
* @fires DialogPanel#afterHide - Fired when the dialog has completed its hide transition
|
|
222
|
+
* @returns {boolean} False if the hide was prevented by a beforeHide event handler
|
|
117
223
|
*/
|
|
118
224
|
hide() {
|
|
119
|
-
|
|
120
|
-
|
|
225
|
+
const _ = this;
|
|
226
|
+
|
|
227
|
+
// Dispatch beforeHide event - allows preventing the dialog from closing
|
|
228
|
+
const beforeHideEvent = new CustomEvent('beforeHide', {
|
|
229
|
+
bubbles: true,
|
|
230
|
+
cancelable: true,
|
|
231
|
+
detail: { triggerElement: _.triggerEl },
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const hideAllowed = _.dispatchEvent(beforeHideEvent);
|
|
235
|
+
|
|
236
|
+
// If event was canceled (preventDefault was called), don't hide the dialog
|
|
237
|
+
if (!hideAllowed) return false;
|
|
238
|
+
|
|
239
|
+
// Restore body scroll and scroll position
|
|
240
|
+
_.#restoreScroll();
|
|
121
241
|
|
|
122
242
|
// Update ARIA states
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
console.log('we need to blur focus');
|
|
243
|
+
if (_.triggerEl) {
|
|
244
|
+
// remove focus from modal panel first
|
|
245
|
+
_.triggerEl.focus();
|
|
246
|
+
// mark trigger as no longer expanded
|
|
247
|
+
_.triggerEl.setAttribute('aria-expanded', 'false');
|
|
129
248
|
}
|
|
130
249
|
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
250
|
+
// Set aria-hidden to start transition
|
|
251
|
+
// The transitionend event handler will add display:none when complete
|
|
252
|
+
_.setAttribute('aria-hidden', 'true');
|
|
253
|
+
|
|
254
|
+
// Dispatch hide event - dialog is now starting to hide
|
|
255
|
+
_.dispatchEvent(
|
|
256
|
+
new CustomEvent('hide', {
|
|
257
|
+
bubbles: true,
|
|
258
|
+
detail: { triggerElement: _.triggerEl },
|
|
259
|
+
})
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
return true;
|
|
135
263
|
}
|
|
136
264
|
}
|
|
137
265
|
|
|
@@ -166,9 +294,15 @@ class DialogContent extends HTMLElement {
|
|
|
166
294
|
}
|
|
167
295
|
}
|
|
168
296
|
|
|
169
|
-
customElements.
|
|
170
|
-
customElements.define('dialog-
|
|
171
|
-
|
|
297
|
+
if (!customElements.get('dialog-panel')) {
|
|
298
|
+
customElements.define('dialog-panel', DialogPanel);
|
|
299
|
+
}
|
|
300
|
+
if (!customElements.get('dialog-overlay')) {
|
|
301
|
+
customElements.define('dialog-overlay', DialogOverlay);
|
|
302
|
+
}
|
|
303
|
+
if (!customElements.get('dialog-content')) {
|
|
304
|
+
customElements.define('dialog-content', DialogContent);
|
|
305
|
+
}
|
|
172
306
|
|
|
173
307
|
export { DialogPanel, DialogOverlay, DialogContent };
|
|
174
308
|
export default DialogPanel;
|
package/src/index.scss
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Import variables using the modern @use rule
|
|
2
|
+
@use 'variables' as vars;
|
|
3
|
+
|
|
4
|
+
dialog-panel {
|
|
5
|
+
/* Make it take no space and be invisible in the document flow */
|
|
6
|
+
display: contents;
|
|
7
|
+
|
|
8
|
+
&[aria-hidden='false'] {
|
|
9
|
+
dialog-overlay,
|
|
10
|
+
dialog-content {
|
|
11
|
+
pointer-events: auto;
|
|
12
|
+
opacity: 1;
|
|
13
|
+
transform: scale(1);
|
|
14
|
+
filter: blur(0px);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Overlay background */
|
|
20
|
+
dialog-overlay {
|
|
21
|
+
position: fixed;
|
|
22
|
+
top: 0;
|
|
23
|
+
left: 0;
|
|
24
|
+
width: 100vw;
|
|
25
|
+
height: 100vh;
|
|
26
|
+
opacity: 0;
|
|
27
|
+
pointer-events: none;
|
|
28
|
+
z-index: var(--dp-overlay-z-index, 1000);
|
|
29
|
+
transition: var(--dp-overlay-transition, all 300ms ease-out);
|
|
30
|
+
background-color: var(
|
|
31
|
+
--dp-overlay-background,
|
|
32
|
+
rgba(20, 23, 26, 0.4)
|
|
33
|
+
);
|
|
34
|
+
backdrop-filter: var(
|
|
35
|
+
--dp-overlay-backdrop-filter,
|
|
36
|
+
blur(2px) saturate(120%)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
dialog-content {
|
|
41
|
+
position: fixed;
|
|
42
|
+
top: 50%;
|
|
43
|
+
left: 50%;
|
|
44
|
+
transform: translate(-50%, -50%) scale(0.95);
|
|
45
|
+
max-width: 90vw;
|
|
46
|
+
max-height: 85vh;
|
|
47
|
+
display: var(--dp-content-display, block);
|
|
48
|
+
opacity: 0;
|
|
49
|
+
background: var(--dp-content-background, white);
|
|
50
|
+
pointer-events: none;
|
|
51
|
+
z-index: var(--dp-content-z-index, 1001);
|
|
52
|
+
box-shadow: var(
|
|
53
|
+
--dp-content-shadow,
|
|
54
|
+
0 10px 25px rgba(0, 0, 0, 0.15)
|
|
55
|
+
);
|
|
56
|
+
border-radius: var(--dp-content-border-radius, 8px);
|
|
57
|
+
overflow: auto;
|
|
58
|
+
transition:
|
|
59
|
+
opacity var(--dp-transition-duration, 300ms)
|
|
60
|
+
var(--dp-transition-timing, ease-out),
|
|
61
|
+
transform var(--dp-transition-duration, 300ms)
|
|
62
|
+
var(--dp-transition-timing, ease-out);
|
|
63
|
+
|
|
64
|
+
/* When shown, reset transform to center */
|
|
65
|
+
dialog-panel[aria-hidden='false'] & {
|
|
66
|
+
transform: translate(-50%, -50%) scale(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* When explicitly hidden, remove from layout */
|
|
70
|
+
&.hidden {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Dialog Panel variables
|
|
2
|
+
// SCSS variables for internal component use and customization
|
|
3
|
+
// These variables can be customized by the user
|
|
4
|
+
|
|
5
|
+
// Layout
|
|
6
|
+
$panel-top: 0 !default;
|
|
7
|
+
$panel-left: 0 !default;
|
|
8
|
+
$panel-width: 100vw !default;
|
|
9
|
+
$panel-height: 100vh !default;
|
|
10
|
+
$panel-z-index: 10 !default;
|
|
11
|
+
|
|
12
|
+
// Overlay
|
|
13
|
+
$overlay-z-index: 1000 !default;
|
|
14
|
+
$overlay-background: rgba(20, 23, 26, 0.4) !default;
|
|
15
|
+
$overlay-backdrop-filter: blur(2px) saturate(120%) !default;
|
|
16
|
+
$overlay-transition: all 400ms ease-out !default;
|
|
17
|
+
|
|
18
|
+
// Content
|
|
19
|
+
$content-display: block !default;
|
|
20
|
+
$content-background: white !default;
|
|
21
|
+
$content-z-index: 1001 !default;
|
|
22
|
+
$content-shadow: 0 10px 25px rgba(0, 0, 0, 0.15) !default;
|
|
23
|
+
$content-border-radius: 8px !default;
|
|
24
|
+
|
|
25
|
+
// Animation
|
|
26
|
+
$transition-duration: 400ms !default;
|
|
27
|
+
$transition-timing: ease-out !default;
|
|
28
|
+
|
|
29
|
+
// Define CSS Custom Properties using SCSS values
|
|
30
|
+
:root {
|
|
31
|
+
// Layout
|
|
32
|
+
--dp-panel-top: #{$panel-top};
|
|
33
|
+
--dp-panel-left: #{$panel-left};
|
|
34
|
+
--dp-panel-width: #{$panel-width};
|
|
35
|
+
--dp-panel-height: #{$panel-height};
|
|
36
|
+
--dp-panel-z-index: #{$panel-z-index};
|
|
37
|
+
|
|
38
|
+
// Overlay
|
|
39
|
+
--dp-overlay-z-index: #{$overlay-z-index};
|
|
40
|
+
--dp-overlay-background: #{$overlay-background};
|
|
41
|
+
--dp-overlay-backdrop-filter: #{$overlay-backdrop-filter};
|
|
42
|
+
--dp-overlay-transition: #{$overlay-transition};
|
|
43
|
+
|
|
44
|
+
// Content
|
|
45
|
+
--dp-content-display: #{$content-display};
|
|
46
|
+
--dp-content-background: #{$content-background};
|
|
47
|
+
--dp-content-z-index: #{$content-z-index};
|
|
48
|
+
--dp-content-shadow: #{$content-shadow};
|
|
49
|
+
--dp-content-border-radius: #{$content-border-radius};
|
|
50
|
+
|
|
51
|
+
// Animation
|
|
52
|
+
--dp-transition-duration: #{$transition-duration};
|
|
53
|
+
--dp-transition-timing: #{$transition-timing};
|
|
54
|
+
}
|
package/src/dialog-panel.css
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
dialog-panel {
|
|
2
|
-
position: fixed;
|
|
3
|
-
top: 0;
|
|
4
|
-
left: 0;
|
|
5
|
-
width: 100vw;
|
|
6
|
-
height: 100vh;
|
|
7
|
-
z-index: 10;
|
|
8
|
-
pointer-events: none;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/* transparent background */
|
|
12
|
-
dialog-overlay {
|
|
13
|
-
position: absolute;
|
|
14
|
-
top: 0;
|
|
15
|
-
left: 0;
|
|
16
|
-
width: 100vw;
|
|
17
|
-
height: 100vh;
|
|
18
|
-
opacity: 0;
|
|
19
|
-
pointer-events: none;
|
|
20
|
-
transition: all 300ms ease-out;
|
|
21
|
-
background-color: rgba(20, 23, 26, 0.4);
|
|
22
|
-
backdrop-filter: blur(2px) saturate(120%);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
dialog-content {
|
|
26
|
-
display: block;
|
|
27
|
-
opacity: 0;
|
|
28
|
-
background: white;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
dialog-panel[aria-hidden='false'] {
|
|
32
|
-
pointer-events: all;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
dialog-panel[aria-hidden='false'] dialog-overlay {
|
|
36
|
-
pointer-events: all;
|
|
37
|
-
opacity: 1;
|
|
38
|
-
transform: scale(1);
|
|
39
|
-
filter: blur(0px);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
dialog-panel[aria-hidden='false'] dialog-content {
|
|
43
|
-
opacity: 1;
|
|
44
|
-
z-index: 10;
|
|
45
|
-
transform: scale(1);
|
|
46
|
-
filter: blur(0px);
|
|
47
|
-
}
|