Installation
import { sheet } from 'https://esm.sh/gh/erikthalen/sheet/src/lib'
const sheets = document.querySelectorAll('dialog').map(sheet)
// init function returns a teardown function
sheets.forEach(destroy => destroy())
body {
/* can be any color */
background-color: white;
/* disable scroll */
&:has(dialog[open]) {
overflow: hidden;
touch-action: none;
}
/* can be any transition */
dialog {
transform: translateY(100vh);
transition: all 500ms var(--sheet-easing);
transition-behavior: allow-discrete;
}
dialog::backdrop {
background-color: rgb(0 0 0 / 25%);
opacity: 0;
transition: all 500ms var(--sheet-easing) allow-discrete;
touch-action: none;
}
dialog[open] {
transform: translateY(0);
}
dialog[open]::backdrop {
opacity: calc(1 - var(--amount, 0));
}
@starting-style {
dialog[open] {
transform: translateY(100vh);
}
dialog[open]::backdrop {
opacity: 0;
}
}
}
Minimal example
<button onclick="document.getElementById('dialog')?.showModal()">
Open sheet
</button>
<dialog id="dialog" closedby="any">
<button data-sheet-handle aria-title="Drag to close">
—
</button>
<p>Content</p>
</dialog>
Configuration
body {
--sheet-top-margin: 3rem;
--sheet-background-scale-amount: 10px;
--sheet-background-border-radius: 10px;
--sheet-easing: cubic-bezier(0.32, 0.72, 0, 1);
--sheet-duration: 500ms;
}