Skip to content

Commit f0ed657

Browse files
Add Dialog Article
1 parent 513326a commit f0ed657

File tree

7 files changed

+642
-400
lines changed

7 files changed

+642
-400
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
const modalId = `modal-${crypto.randomUUID()}`
3+
const {
4+
modalStyle,
5+
purpleBackdrop = false,
6+
btnText = "Open",
7+
isModal = false,
8+
closeOnOutsideClick = false,
9+
modalText = isModal ? "This is a modal" : "This is a dialog",
10+
} = Astro.props
11+
---
12+
13+
<div class="modal-wrapper">
14+
<button class="btn" data-modal-open-target={modalId} data-is-modal={isModal}
15+
>{btnText}</button
16+
>
17+
<dialog
18+
style={modalStyle}
19+
data-close-on-outside-click={closeOnOutsideClick}
20+
class={`dialog ${isModal ? "modal" : ""} ${
21+
purpleBackdrop ? "purple-backdrop" : ""
22+
}`}
23+
id={modalId}
24+
>
25+
<slot>
26+
<div class="modal-content">
27+
{modalText}
28+
</div>
29+
<button class="btn" data-modal-close-target={modalId}>Close</button>
30+
</slot>
31+
</dialog>
32+
</div>
33+
34+
<style>
35+
.modal-wrapper {
36+
background: var(--test);
37+
position: relative;
38+
}
39+
40+
.dialog {
41+
z-index: 10;
42+
}
43+
44+
.dialog:not(.modal) {
45+
margin-top: 10px;
46+
}
47+
48+
.dialog.modal {
49+
top: 50%;
50+
left: 50%;
51+
translate: -50% -50%;
52+
}
53+
54+
.dialog::backdrop {
55+
background-color: rgba(0, 0, 0, 0.5);
56+
}
57+
58+
.dialog.purple-backdrop::backdrop {
59+
background-color: hsl(250, 100%, 50%, 0.25);
60+
}
61+
62+
.btn {
63+
border: none;
64+
border-radius: 0.25em;
65+
padding: 0.5em 0.75em;
66+
font-size: inherit;
67+
background: var(--theme-purple);
68+
cursor: pointer;
69+
}
70+
71+
.btn:hover {
72+
background: var(--theme-purple-hover);
73+
}
74+
75+
.modal-content {
76+
margin-bottom: 1rem;
77+
}
78+
</style>
79+
80+
<script>
81+
const openBtns = document.querySelectorAll("[data-modal-open-target]")
82+
const closeBtns = document.querySelectorAll("[data-modal-close-target]")
83+
const closeOnOutsideClickDialogs = document.querySelectorAll(
84+
"[data-close-on-outside-click]"
85+
)
86+
closeOnOutsideClickDialogs.forEach(dialog => {
87+
dialog.addEventListener("click", e => {
88+
const dialogDimensions = dialog.getBoundingClientRect()
89+
if (
90+
e.clientX < dialogDimensions.left ||
91+
e.clientX > dialogDimensions.right ||
92+
e.clientY < dialogDimensions.top ||
93+
e.clientY > dialogDimensions.bottom
94+
) {
95+
dialog.close()
96+
}
97+
})
98+
})
99+
100+
openBtns.forEach(btn => {
101+
btn.addEventListener("click", () => {
102+
const id = btn.getAttribute("data-modal-open-target")
103+
const modal = document.getElementById(id)
104+
const isModal = btn.getAttribute("data-is-modal")
105+
if (isModal === "" || isModal === "true") {
106+
modal.showModal()
107+
} else {
108+
modal.show()
109+
}
110+
const backdrop = modal.querySelector("::backdrop")
111+
console.log(backdrop)
112+
})
113+
})
114+
115+
closeBtns.forEach(btn => {
116+
btn.addEventListener("click", () => {
117+
const id = btn.getAttribute("data-modal-close-target")
118+
const modal = document.getElementById(id)
119+
modal.close()
120+
})
121+
})
122+
</script>

src/blogComponents/intersectionObserver/IntersectionObserver.astro

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ const { threshold = 0, percentage = false, rootMargin = 0 } = Astro.props
3434
.clone-container {
3535
position: absolute;
3636
z-index: -1;
37-
background-color: rgba(0, 0, 0, .1);
37+
background-color: rgba(0, 0, 0, 0.1);
3838
left: 0;
3939
right: 0;
4040
border: 1px solid white;
4141
bottom: 0;
4242
}
4343

4444
:root[data-theme="dark"] .clone-container {
45-
background-color: rgba(255, 255, 255, .1);
45+
background-color: rgba(255, 255, 255, 0.1);
4646
}
4747

4848
.root-margin-lines {
@@ -58,14 +58,27 @@ const { threshold = 0, percentage = false, rootMargin = 0 } = Astro.props
5858
}
5959
</style>
6060

61-
<div data-intersection-observer-component class="container" style={`padding-top: ${WINDOW_HEIGHT - VIEWPORT_HEIGHT}px; padding-bottom: ${WINDOW_HEIGHT - VIEWPORT_HEIGHT}px;`}>
61+
<div
62+
data-intersection-observer-component
63+
class="container"
64+
style={`padding-top: ${WINDOW_HEIGHT - VIEWPORT_HEIGHT}px; padding-bottom: ${
65+
WINDOW_HEIGHT - VIEWPORT_HEIGHT
66+
}px;`}
67+
>
6268
<div
6369
data-scroll-element
6470
class="scroll-element"
6571
style={`height: ${VIEWPORT_HEIGHT}px;`}
6672
>
6773
<div style={`height: ${WINDOW_HEIGHT}px; padding-top: ${MARGIN}px;`}>
68-
<div data-main-element class="main-element" data-threshold={threshold} data-percentage={percentage.toString()} data-root-margin={rootMargin}></div>
74+
<div
75+
data-main-element
76+
class="main-element"
77+
data-threshold={threshold}
78+
data-percentage={percentage.toString()}
79+
data-root-margin={rootMargin}
80+
>
81+
</div>
6982
</div>
7083
</div>
7184
<div
@@ -75,53 +88,54 @@ const { threshold = 0, percentage = false, rootMargin = 0 } = Astro.props
7588
>
7689
<div data-clone-element class="clone-element"></div>
7790
</div>
78-
{rootMargin !== 0 && (
91+
{
92+
rootMargin !== 0 && (
7993
<div class="root-margin-lines">
80-
<div class="line" style={`top: ${rootMargin}px`}></div>
81-
<div class="line" style={`bottom: ${VIEWPORT_HEIGHT + rootMargin}px`}></div>
82-
</div>
83-
)}
94+
<div class="line" style={`top: ${rootMargin}px`} />
95+
<div class="line" style={`bottom: ${VIEWPORT_HEIGHT + rootMargin}px`} />
96+
</div>
97+
)
98+
}
8499
</div>
85100

86101
<script>
87-
if (document.readyState === "complete" || document.readyState === "interactive") {
88-
ready()
89-
} else {
90-
document.addEventListener("DOMContentLoaded", ready)
91-
}
102+
const containers = document.querySelectorAll(
103+
"[data-intersection-observer-component]"
104+
)
105+
containers.forEach(container => {
106+
const mainElement = container.querySelector("[data-main-element]")
107+
const cloneElement = container.querySelector("[data-clone-element]")
108+
const cloneContainer = container.querySelector("[data-clone-container]")
109+
const scrollElement = container.querySelector("[data-scroll-element]")
92110

93-
function ready() {
94-
const containers = document.querySelectorAll("[data-intersection-observer-component]")
95-
containers.forEach(container => {
96-
const mainElement = container.querySelector("[data-main-element]")
97-
const cloneElement = container.querySelector("[data-clone-element]")
98-
const cloneContainer = container.querySelector("[data-clone-container]")
99-
const scrollElement = container.querySelector("[data-scroll-element]")
100-
101-
const threshold = JSON.parse(mainElement.dataset.threshold)
102-
const percentage = JSON.parse(mainElement.dataset.percentage)
103-
const rootMargin = JSON.parse(mainElement.dataset.rootMargin)
104-
const observerCallback = ({ intersectionRatio, isIntersecting }, elements) => {
105-
if (percentage) {
106-
elements.forEach(element => {
107-
element.textContent = `${Math.round(intersectionRatio * 100)}%`
108-
})
109-
} else {
110-
elements.forEach(element => {
111-
element.style.backgroundColor = isIntersecting ? "var(--theme-blue)" : "var(--theme-orange)"
112-
})
113-
}
111+
const threshold = JSON.parse(mainElement.dataset.threshold)
112+
const percentage = JSON.parse(mainElement.dataset.percentage)
113+
const rootMargin = JSON.parse(mainElement.dataset.rootMargin)
114+
const observerCallback = (
115+
{ intersectionRatio, isIntersecting },
116+
elements
117+
) => {
118+
if (percentage) {
119+
elements.forEach(element => {
120+
element.textContent = `${Math.round(intersectionRatio * 100)}%`
121+
})
122+
} else {
123+
elements.forEach(element => {
124+
element.style.backgroundColor = isIntersecting
125+
? "var(--theme-blue)"
126+
: "var(--theme-orange)"
127+
})
114128
}
129+
}
115130

116-
scrollElement.addEventListener("scroll", e => {
117-
cloneContainer.style.bottom = `${e.target.scrollTop}px`
118-
})
119-
console.log(`${rootMargin}px`)
120-
const observer = new IntersectionObserver(
121-
entries => observerCallback(entries[0], [mainElement, cloneElement]),
122-
{ threshold, rootMargin: `${rootMargin}px`, root: scrollElement }
123-
)
124-
observer.observe(mainElement)
131+
scrollElement.addEventListener("scroll", e => {
132+
cloneContainer.style.bottom = `${e.target.scrollTop}px`
125133
})
126-
}
127-
</script>
134+
console.log(`${rootMargin}px`)
135+
const observer = new IntersectionObserver(
136+
entries => observerCallback(entries[0], [mainElement, cloneElement]),
137+
{ threshold, rootMargin: `${rootMargin}px`, root: scrollElement }
138+
)
139+
observer.observe(mainElement)
140+
})
141+
</script>

src/blogComponents/intersectionObserver/IntersectionObserverComponent.jsx

Lines changed: 0 additions & 107 deletions
This file was deleted.

0 commit comments

Comments
 (0)