<div popover="manual" class="window popup og">
<div class="title-bar">
<div class="title-bar-text">OG Pop-up</div>
</div>
<div class="window-body">
<p>Using this pop-up, generate lots of other pop-ups.</p>
<p>We're using JavaScript to manage which pop-ups get a <code>::backdrop</code>.<br>
In this case, we only ever want one <code>::backdrop</code>.
</p>
<section class="field-row">
<button data-popup-clearer="true">Clear pop-ups</button>
<button data-popup-generator="true">Generate pop-up</button>
</section>
</div>
</div>
@import url("https://unpkg.com/xp.css");
@layer demo {
button[popover] {
top: 50%;
left: 50%;
translate: -50% -50%;
scale: 1.25;
margin: 0;
}
code {
background: transparent;
color: var(--red-8);
}
.popup {
transform: translate(-50%, -50%);
text-align: center;
position: fixed;
left: calc(var(--x, 50) * 1%);
top: calc(var(--y, 50) * 1%);
white-space: nowrap;
margin: 0;
border: 0;
}
.popup[data-hasbackdrop]::backdrop {
background: hsl(0 10% 10%/ 0.35);
backdrop-filter: blur(2px);
}
.popup[data-hasbackdrop]:open::backdrop {
opacity: 1;
}
.window-body {
display: flex;
flex-direction: column;
}
.window-body p {
padding: var(--size-2) var(--size-4);
font-size: 12px;
letter-spacing: unset;
line-height: 1.2;
}
.title-bar {
height: auto;
min-height: 28px;
}
.title-bar-controls button {
height: 21px;
}
.field-row {
justify-content: flex-end;
}
button {
height: auto;
color: #000;
}
}
@layer base {
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
background: var(--gradient-7);
font-family: "Google Sans", sans-serif, system-ui;
}
:where([popover]) {
margin: auto;
border-width: initial;
border-style: solid;
}
}
const OG_POP = document.querySelector(".og[popover]");
const ADDER = document.querySelector("button[data-popup-generator]");
const CLEARER = document.querySelector("button[data-popup-clearer]");
const BACKDROP_ATTRIBUTE = "data-hasbackdrop";
let popUps = [];
const randomInRange = (min, max) =>
Math.floor(
Math.random() * (Math.floor(max) - Math.ceil(min) + 1) + Math.ceil(min)
);
const destroyPopUp = (e) => {
// Remove the id from the list
const popIndex = popUps.indexOf(e.target.id);
if (popIndex !== -1) {
// If there is an index before, add the attribute to that.
popUps.splice(popIndex, 1);
if (popUps.length !== 0)
document
.querySelector(`#${popUps[0]}`)
.setAttribute(BACKDROP_ATTRIBUTE, true);
e.target.remove();
}
};
const createPopUp = () => {
const pop = Object.assign(document.createElement("div"), {
id: `pop--${popUps.length}`,
popover: "manual",
className: "window popup",
innerHTML: `
<div class="title-bar">
<div class="title-bar-text">Generated Pop-up</div>
<div class="title-bar-controls">
<button aria-label="Close"></button>
</div>
</div>
<div class="window-body">
<p>There's only ever one backdrop!</p>
<section class="field-row">
<button autofocus>Add another pop-up</button>
<button>Cancel</button>
</section>
</div>
`
});
const POP_BUTTONS = pop.querySelectorAll("button");
POP_BUTTONS[0].addEventListener("click", () => pop.hidePopover());
POP_BUTTONS[1].addEventListener("click", createPopUp);
POP_BUTTONS[2].addEventListener("click", () => pop.hidePopover());
pop.addEventListener("popuphide", destroyPopUp);
if (popUps.length === 0) pop.setAttribute(BACKDROP_ATTRIBUTE, true);
document.body.insertBefore(pop, OG_POP);
pop.style.setProperty("--x", randomInRange(20, 80));
pop.style.setProperty("--y", randomInRange(20, 80));
popUps.push(pop.id);
pop.showPopover();
// Remove and Re-add the OG to promote it above others in the top layer
OG_POP.hidePopover();
OG_POP.showPopover();
};
const clearPopUps = () => {
const POPS = document.querySelectorAll("[popover]:not(.og)");
for (const POP of POPS) {
POP.hidePopover();
}
};
ADDER.addEventListener("click", createPopUp);
CLEARER.addEventListener("click", clearPopUps);
OG_POP.showPopover();