<h1>Invoker commands!</h1>
<p>Using the commandfor on a button to trigger a dialog element</p>
<button commandfor="my-modal" command="show-modal">Invoke dialog</button>
<dialog id="my-modal">
<header>
<h2>Well hello there!</h2>
<button class="btn btn--clean" commandfor="my-modal" command="close">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="sr-only"></span>
</button>
</header>
<main>
<p>I am a lovely dialog with HTML, using invoker commands, currently available in canary</p>
</main>
<footer>
<button class="outline" commandfor="my-modal" command="close">
close
</button>
</footer>
</dialog>
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wdth@75..100&family=Oswald:wght@600&display=swap");
body:has(dialog[open]) {
overflow: hidden;
}
@layer dialog.content {
dialog {
width: 100%;
max-width: 600px;
padding: 0;
background: #fff;
border-radius: 8px;
border: 1px solid #dedede;
box-shadow: rgba(0, 0, 0, 0.3) 0px 19px 38px,
rgba(0, 0, 0, 0.22) 0px 15px 12px;
opacity: 0;
translate: 0 30%;
transition-property: opacity, translate, overlay, display;
transition-duration: 0.8s;
transition-behavior: allow-discrete;
&::backdrop {
/* Loving that gradient.style example <3 */
background-image: linear-gradient(
133deg in oklab,
oklch(70% 0.5 340) 0%,
oklch(90% 0.5 200) 100%
);
opacity: 0;
cursor: pointer;
transition-property: opacity, translate, overlay;
transition-duration: 1s;
transition-behavior: allow-discrete;
}
&[open] {
opacity: 1;
translate: 0 0;
&::backdrop {
opacity: 0.8;
}
}
}
@starting-style {
dialog[open]::backdrop {
opacity: 0;
}
dialog[open] {
opacity: 0;
translate: 0 -30%;
}
}
}
@layer dialog.content {
dialog header {
position: sticky;
top: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 24px;
background: #fff;
border-bottom: 1px solid rgba(238, 118, 116, 1);
h2 {
margin: 0;
}
}
dialog footer {
border-top: 1px solid rgba(238, 118, 116, 1);
}
dialog > * {
padding: 24px;
}
dialog p:last-of-type {
margin-bottom: 0;
}
}
@layer buttons {
button {
--_color: var(--color, fuchsia);
padding: 0.5rem 1.2rem;
border-radius: 5px;
font-family: "Open Sans", sans-serif;
font-size: 1.3rem;
cursor: pointer;
background: var(--_color);
border: 2px solid var(--_color);
color: white;
transition: background 0.3s ease-out, color 0.3s ease-out,
border-color 0.3s ease-out;
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px,
rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
}
button.outline {
background: transparent;
color: var(--_color);
box-shadow: none;
}
button:is(:hover, :focus) {
--color: var(--hoverColor, deeppink);
}
.btn--clean {
background: transparent;
padding: 0;
border: 0;
color: inherit;
box-shadow: none;
&:is(:hover, :active, :focus) {
color: darkviolet;
}
}
}
@layer base {
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
font-family: "Open Sans", sans-serif;
font-size: 1.3rem;
line-height: 1.6;
min-block-size: 100dvb;
display: flex;
background: #474056;
color: #fff;
}
h1,
h2 {
font-family: "Oswald", sans-serif;
font-weight: 600;
font-size: 4rem;
margin-block-end: 1rem;
text-shadow: -1px -1px 1px rgba(255, 255, 255, 0.2),
1px 1px 1px rgba(0, 0, 0, 0.6);
}
h2 {
font-size: 2rem;
margin: 0;
}
p {
margin-block-start: 0;
}
.sr-only {
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
}
svg {
width: 1.4rem;
color: inherit;
}
}
const dialogs = document.querySelectorAll("dialog");
dialogs.forEach(function (el) {
el.addEventListener("click", ({ target: dialog }) => {
if (dialog.nodeName === "DIALOG") {
dialog.close("dismiss");
}
});
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.