mirror of
https://github.com/tabler/tabler.git
synced 2026-10-12 05:06:55 +04:00
Style the native dialog backdrop and contain scroll chaining (#2868)
This commit is contained in:
1 parent
6f96282f3c
commit
c1786b55b1
6 files changed
+89
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@tabler/core": minor
|
||||||
|
"@tabler/preview": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Added `dialog::backdrop` styling so a native `<dialog>` uses the same backdrop as modals.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tabler/core": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Added `overscroll-behavior: contain` to `.modal`, `.modal-body`, `.offcanvas-body` and `.dropdown-menu-scrollable`.
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
height: auto;
|
height: auto;
|
||||||
max-height: $dropdown-scrollable-height;
|
max-height: $dropdown-scrollable-height;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
overscroll-behavior: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-menu-column {
|
.dropdown-menu-column {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
.modal-body {
|
.modal-body {
|
||||||
@include scrollbar();
|
@include scrollbar();
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
|
||||||
.modal-title {
|
.modal-title {
|
||||||
margin-bottom: var(--modal-body-title-margin-bottom);
|
margin-bottom: var(--modal-body-title-margin-bottom);
|
||||||
@@ -74,7 +75,25 @@
|
|||||||
--modal-body-title-margin-bottom: #{$modal-body-title-margin-bottom};
|
--modal-body-title-margin-bottom: #{$modal-body-title-margin-bottom};
|
||||||
--modal-footer-padding-y: #{$modal-footer-padding-y};
|
--modal-footer-padding-y: #{$modal-footer-padding-y};
|
||||||
|
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
|
||||||
@include media-print() {
|
@include media-print() {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Native dialog
|
||||||
|
//
|
||||||
|
// Make the backdrop of a native `<dialog>` opened with `showModal()` match the
|
||||||
|
// backdrop used by modals and offcanvases.
|
||||||
|
//
|
||||||
|
// The alpha is part of the color instead of `opacity`, so that `backdrop-filter`
|
||||||
|
// blurs the page instead of blending a blurred copy over the sharp one.
|
||||||
|
dialog::backdrop {
|
||||||
|
background: color-mix(in sRGB, var(--backdrop-bg) calc(var(--backdrop-opacity) * 100%), transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.modal-blur::backdrop {
|
||||||
|
backdrop-filter: var(--backdrop-filter);
|
||||||
|
}
|
||||||
@@ -6,6 +6,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.offcanvas-body {
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
border-bottom: var(--border-width) var(--border-style) var(--border-color);
|
border-bottom: var(--border-width) var(--border-style) var(--border-color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
// Every modal is rendered inline via ModalInline (in place, unlike Modal.astro
|
// Every modal is rendered inline via ModalInline (in place, unlike Modal.astro
|
||||||
// which drains to <body>).
|
// which drains to <body>).
|
||||||
import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
|
import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
|
||||||
|
import CaptureScript from '@shared/components/CaptureScript.astro'
|
||||||
|
import Button from '@ui/Button.astro'
|
||||||
|
import ButtonList from '@ui/ButtonList.astro'
|
||||||
import Card from '@ui/Card.astro'
|
import Card from '@ui/Card.astro'
|
||||||
import CardBody from '@ui/CardBody.astro'
|
import CardBody from '@ui/CardBody.astro'
|
||||||
import ModalInline from '@shared/components/modals/ModalInline.astro'
|
import ModalInline from '@shared/components/modals/ModalInline.astro'
|
||||||
@@ -52,6 +55,7 @@ const cardClass = 'position-relative rounded d-block bg-surface-backdrop py-6 w-
|
|||||||
<a href="#modal-confirm-delete" class="nav-link">Confirm delete modal</a>
|
<a href="#modal-confirm-delete" class="nav-link">Confirm delete modal</a>
|
||||||
<a href="#modal-change-password" class="nav-link">Change password modal</a>
|
<a href="#modal-change-password" class="nav-link">Change password modal</a>
|
||||||
<a href="#modal-add-task" class="nav-link">Add task modal</a>
|
<a href="#modal-add-task" class="nav-link">Add task modal</a>
|
||||||
|
<a href="#modal-native" class="nav-link">Native dialog</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@@ -158,9 +162,59 @@ const cardClass = 'position-relative rounded d-block bg-surface-backdrop py-6 w-
|
|||||||
<AddTaskModalContent />
|
<AddTaskModalContent />
|
||||||
</ModalInline>
|
</ModalInline>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="modal-native">
|
||||||
|
<h3>Native dialog</h3>
|
||||||
|
<p class="text-secondary">
|
||||||
|
A native <code><dialog></code> opened with <code>showModal()</code>. The browser paints the backdrop and Tabler styles it to match the one used by modals, with
|
||||||
|
<code>.modal-blur</code> blurring the page behind it. Buttons inside <code><form method="dialog"></code> close the dialog without any script. The panel uses the card classes on a child element, because the modal classes read CSS variables set on <code>.modal</code>, and a <code>display</code> value
|
||||||
|
on the dialog itself would keep it visible when closed.
|
||||||
|
</p>
|
||||||
|
<ButtonList>
|
||||||
|
<Button element="button" color="primary" id="native-dialog-open" text="Open native dialog" />
|
||||||
|
<Button element="button" id="native-dialog-open-blur" text="Open with blur" />
|
||||||
|
</ButtonList>
|
||||||
|
<dialog id="native-dialog" class="p-0 border-0 bg-transparent" style="width: 28rem; max-width: calc(100% - 2rem)">
|
||||||
|
<form method="dialog" class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Native dialog</h3>
|
||||||
|
<div class="card-actions">
|
||||||
|
<button type="submit" class="btn-close" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>The browser keeps the page behind this dialog inert, traps focus inside it and closes it on Esc.</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer text-end">
|
||||||
|
<Button element="button" type="submit" color="primary" text="Close" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<CaptureScript>
|
||||||
|
<!-- BEGIN NATIVE DIALOG SCRIPT -->
|
||||||
|
<script is:inline>
|
||||||
|
// Only opening a native <dialog> needs a script. Closing is handled by the
|
||||||
|
// <form method="dialog"> buttons inside it and by the Esc key.
|
||||||
|
function initNativeDialog() {
|
||||||
|
const nativeDialog = document.getElementById('native-dialog')
|
||||||
|
|
||||||
|
const openNativeDialog = (blur) => {
|
||||||
|
nativeDialog.classList.toggle('modal-blur', blur)
|
||||||
|
nativeDialog.showModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('native-dialog-open').addEventListener('click', () => openNativeDialog(false))
|
||||||
|
document.getElementById('native-dialog-open-blur').addEventListener('click', () => openNativeDialog(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
document.readyState !== 'loading' ? initNativeDialog() : document.addEventListener('DOMContentLoaded', initNativeDialog, { once: true })
|
||||||
|
</script>
|
||||||
|
<!-- END NATIVE DIALOG SCRIPT -->
|
||||||
|
</CaptureScript>
|
||||||
</DefaultLayout>
|
</DefaultLayout>
|
||||||
Reference in new issue
Block a user