Hide a standard side sheet's scrim from 840px again

Plan step 36 review of 9dd527f3. The old view hid a standard sheet's
scrim with `expanded:hidden`; the stylesheet lost that rule (and the
render test lost its assertion), so an open standard sheet at 840px and
up laid a full-window scrim over the page it sits beside, one click from
closing. The rule is back, pinned by a test.

The same review: the scrim now fades out as well as in (with no closed
opacity, allow-discrete only held it at 32% for 200ms and then dropped
it); the modal sheet slides without the fade the old enter and leave
classes never had; it slides from its own edge in a right-to-left
document, which translate-x-full never did; the state rules match the
root's own sheet and scrim, so a sheet nested in an open one keeps its
state; the script's breakpoint is 840px, not 52.5rem, which disagreed
with the stylesheet's px query once the reader's text size grew; and
`width` and the standard sheet's cap are M3's 400px.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 22:04:13 +02:00
co-authored by Claude Opus 5
parent d86392fd47
commit b6259d45f3
4 changed files with 84 additions and 43 deletions
+47 -25
View File
@@ -6,7 +6,7 @@
* material-components-android's `SideSheet.md`).
*
* [data-md-drawer] the wrapper; data-md-open, data-md-standard
* [data-md-drawer-scrim] modal only (hidden by JS once the sheet is wide/standard)
* [data-md-drawer-scrim] modal only (a standard sheet's is hidden from 840px)
* [data-md-drawer-sheet] surface-container-low, elevation 1; data-md-side
* [data-md-drawer-head] title/subtitle/close, and the separator's divider
* [data-md-drawer-head-row], [data-md-drawer-heading], [data-md-drawer-title],
@@ -15,11 +15,16 @@
* width (`@md:`), never the viewport's
* [data-md-drawer-actions] left-aligned, 72dp (C-10 — a dialog's are trailing-aligned)
*
* 400px cap, 24dp start/end padding, a large corner on the inner edge only, 56dp side-sheet
* width start — all from the specs table. It enters on the emphasized-decelerate easing rather
* than a spring, because a sheet anchored to an edge that overshot would open a gap; below
* `expanded` it slides, and once `standard` makes it co-planar it only fades (an in-flow box does
* not need to travel).
* 400px cap, 24dp start/end padding, a large corner on the inner edge only — from the specs
* table. It enters on the emphasized-decelerate easing rather than a spring, because a sheet
* anchored to an edge that overshot would open a gap, and leaves on emphasized accelerate: the
* view keeps `x-show`, so `@starting-style` gives the entry its start and `allow-discrete` holds
* `display` through the exit, whose timing comes from the closed state's own rule (a transition
* takes the after-change style's). Reduced motion zeroes both duration tokens (tokens/motion.css).
* Below `expanded` it slides, from whichever edge `data-md-side` names in the document's direction;
* once `standard` makes it co-planar it only fades (an in-flow box does not need to travel). Every
* state rule matches the sheet and scrim as the root's children, so a sheet nested in an open one
* keeps its own.
*
* A `standard` sheet drops the scrim, the trap and the elevation, and swaps surface-container-low
* for `surface` with an outline-variant rule down its inner edge, in place of the scrim
@@ -36,24 +41,34 @@
@import './divider.css';
@layer material.components {
/* The scrim fades in and, while `display` is held by `allow-discrete`, back out. */
[data-md-drawer-scrim] {
position: fixed;
inset: 0;
z-index: 40;
background-color: color-mix(in srgb, var(--md-sys-color-scrim) 32%, transparent);
opacity: 0;
transition-property: opacity, display;
transition-duration: var(--md-sys-motion-effects-default-duration);
transition-timing-function: var(--md-sys-motion-effects-default);
transition-behavior: allow-discrete;
}
[data-md-drawer][data-md-open] > [data-md-drawer-scrim] {
opacity: 1;
}
@starting-style {
[data-md-drawer-scrim] {
[data-md-drawer][data-md-open] > [data-md-drawer-scrim] {
opacity: 0;
}
}
/* Closed, the sheet waits one width past its own edge (`--sheet-offset`, mirrored in RTL) and
slides there on emphasized accelerate; open, it comes back on emphasized decelerate. */
[data-md-drawer-sheet] {
--sheet-offset: 100%;
position: fixed;
top: var(--material-safe-top, env(safe-area-inset-top));
bottom: 0;
@@ -66,9 +81,8 @@
background-color: var(--md-sys-color-surface-container-low);
color: var(--md-sys-color-on-surface);
box-shadow: var(--md-sys-elevation-1);
translate: 100% 0;
opacity: 0;
transition-property: translate, opacity, display;
translate: var(--sheet-offset) 0;
transition-property: translate, display;
transition-duration: var(--md-sys-motion-effects-default-duration);
transition-timing-function: var(--md-sys-motion-easing-emphasized-accelerate);
transition-behavior: allow-discrete;
@@ -79,25 +93,28 @@
}
[data-md-drawer-sheet][data-md-side='start'] {
--sheet-offset: -100%;
inset-inline-start: 0;
translate: -100% 0;
}
[data-md-drawer][data-md-open] [data-md-drawer-sheet] {
[data-md-drawer-sheet][data-md-side='end']:dir(rtl) {
--sheet-offset: -100%;
}
[data-md-drawer-sheet][data-md-side='start']:dir(rtl) {
--sheet-offset: 100%;
}
[data-md-drawer][data-md-open] > [data-md-drawer-sheet] {
translate: 0 0;
opacity: 1;
transition-duration: var(--md-sys-motion-spatial-default-duration);
transition-timing-function: var(--md-sys-motion-easing-emphasized-decelerate);
}
@starting-style {
[data-md-drawer][data-md-open] [data-md-drawer-sheet] {
translate: 100% 0;
opacity: 0;
}
[data-md-drawer][data-md-open] [data-md-drawer-sheet][data-md-side='start'] {
translate: -100% 0;
[data-md-drawer][data-md-open] > [data-md-drawer-sheet] {
translate: var(--sheet-offset) 0;
}
}
@@ -134,7 +151,11 @@
display: none;
}
[data-md-drawer][data-md-standard] [data-md-drawer-sheet] {
[data-md-drawer][data-md-standard] > [data-md-drawer-scrim] {
display: none;
}
[data-md-drawer][data-md-standard] > [data-md-drawer-sheet] {
position: relative;
top: 0;
z-index: auto;
@@ -149,23 +170,24 @@
transition-timing-function: var(--md-sys-motion-easing-emphasized-accelerate);
}
[data-md-drawer][data-md-standard][data-md-open] [data-md-drawer-sheet] {
[data-md-drawer][data-md-standard][data-md-open] > [data-md-drawer-sheet] {
opacity: 1;
transition-duration: var(--md-sys-motion-spatial-default-duration);
transition-timing-function: var(--md-sys-motion-easing-emphasized-decelerate);
}
@starting-style {
[data-md-drawer][data-md-standard][data-md-open] [data-md-drawer-sheet] {
[data-md-drawer][data-md-standard][data-md-open] > [data-md-drawer-sheet] {
translate: 0 0;
opacity: 0;
}
}
[data-md-drawer][data-md-standard] [data-md-drawer-sheet][data-md-side='end'] {
[data-md-drawer][data-md-standard] > [data-md-drawer-sheet][data-md-side='end'] {
border-inline-start: 1px solid var(--md-sys-color-outline-variant);
}
[data-md-drawer][data-md-standard] [data-md-drawer-sheet][data-md-side='start'] {
[data-md-drawer][data-md-standard] > [data-md-drawer-sheet][data-md-side='start'] {
border-inline-end: 1px solid var(--md-sys-color-outline-variant);
}
}