/* * ``'s dividers: the rule under the pinned header and the rule over the pinned actions. * * M3 lists a divider in the anatomy of both dialogs, 1dp high (docs/reference/m3/ * components-actions-communication-containment.md § Dialogs → Anatomy, Specs), in outline-variant * (DividerTokens: Color = OutlineVariant, Thickness = 1dp, androidx Compose Material 3, * Apache-2.0). A scrolling dialog keeps its title and buttons pinned and scrolls only what is * between them (§ Dialogs → Behaviour), and a rule there only says something while content is * hidden on its far side: the one under the header shows once the body is scrolled away from its * top, the one over the actions while more of the body is below. resources/js/dialog.js marks the * `` with `data-overflow-top` and `data-overflow-bottom`; a row with `data-separator` (the * `separator` prop) draws its rule whatever the scroll. * * Each rule is a pseudo-element laid over the edge of its own row's padding, as Material Web's * dialog lays its dividers at the bottom of the headline and the top of the actions * (material-components/material-web, dialog/internal/_dialog.scss): it takes no room, so showing * it moves nothing, and it lies outside the body's scrollport, so no content scrolls over it. The * rule is full-bleed, the width of the dialog. Only the head and actions of a dialog that has a * body carry the hooks (resources/views/components/modal.blade.php). * * The child combinators tie a mark to its own dialog's rows, never to those of a dialog opened * from inside its body. The rule fades on the effects-fast token, which reduced motion sets to * zero (resources/css/tokens/motion.css), so there it simply appears. */ @layer components { [data-dialog-head], [data-dialog-actions] { position: relative; } [data-dialog-head]::after, [data-dialog-actions]::before { content: ''; position: absolute; inset-inline: 0; height: 1px; background-color: var(--md-sys-color-outline-variant); opacity: 0; pointer-events: none; transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); } [data-dialog-head]::after { bottom: 0; } [data-dialog-actions]::before { top: 0; } dialog[data-overflow-top] > * > [data-dialog-head]::after, dialog[data-overflow-bottom] > * > [data-dialog-actions]::before, [data-dialog-head][data-separator]::after, [data-dialog-actions][data-separator]::before { opacity: 1; } } /* * The scrolling body is a keyboard stop of its own when nothing inside it can take focus: Chrome * makes a scroll container focusable so the keyboard can scroll it, and `showModal()` hands it the * dialog's first focus. It then showed the browser's own ring. It takes M3's focus indicator * instead — 3px in secondary (tokens/state.css) — drawn inside its edge, because the dialog's * rounded, overflow-hidden box would clip a ring drawn 2px outside. */ @layer components { [data-dialog-body] { outline: none; } [data-dialog-body]:focus-visible { outline: 3px solid var(--md-sys-color-secondary); outline-offset: -3px; } }