<main>
<button id="show-toast-button">Show Toast</button>
</main>
<style>
#show-toast-button {
padding-block: 0.375rem;
padding-inline: 0.625rem;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #111827;
background-color: #ffffff;
cursor: pointer;
&:hover {
background-color: #F9FAFB;
}
}
.toast {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 1rem;
border-radius: 8px;
min-width: 300px;
position: fixed;
bottom: 1rem;
right: 1rem;
}
.toast button {
color: black;
padding: .5rem;
background: none;
cursor: pointer;
}
.toast button:hover {
opacity: 1;
}
.toast[popover] {
/* Initial state - hidden */
opacity: 0;
transform: translateX(100%);
transition:
opacity 0.3s ease,
transform 0.3s ease,
overlay 0.3s ease allow-discrete,
display 0.3s ease allow-discrete;
}
.toast[popover]:popover-open {
/* Shown state */
opacity: 1;
transform: translateX(0);
@starting-style {
opacity: 0;
transform: translateX(100%);
}
}
</style>
<script>
function createToast({ message }) {
const toast = document.createElement('div');
toast.className = 'toast';
toast.setAttribute('popover', 'manual');
// Toast content
toast.innerHTML = `
<p>${message}</p>
<button aria-label="Close notification">×</button>
`;
// Add to container
document.body.appendChild(toast);
// Show the popover
toast.showPopover();
// Manual close button
const closeBtn = toast.querySelector('button');
closeBtn.addEventListener('click', () => {
hideToast(toast);
});
}
function hideToast(toast) {
if (toast && toast.matches(':popover-open')) {
toast.hidePopover();
// Remove from DOM after animation completes
setTimeout(() => {
if (toast.parentNode) {
toast.parentNode.removeChild(toast);
}
}, 300);
}
}
// Button event listener
document.getElementById('show-toast-button').addEventListener('click', () => {
createToast({
message: 'This is a toast notification!'
});
});
</script>