/* * ``: M3's side sheet, modal by default and co-planar as `standard` from 840px * (docs/reference/m3/components-actions-communication-containment.md § Side sheets → Specs; no * androidx Compose token file exists for it — Compose support is "Unavailable" per the site — so * the numbers come from the specs page and, for the standard variant's 0dp elevation, * material-components-android's `SideSheet.md`). * * [data-md-drawer] the wrapper; data-md-open, data-md-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], * [data-md-drawer-subtitle], [data-md-drawer-close] * [data-md-drawer-body] a size container, so its contents lay out by the sheet's own * 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 — 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 * (its anatomy's "Divider (optional)"). Below `expanded` (840px) it is the modal sheet — M3 caps * a side sheet at 400dp, and a 600px window has too little room left beside one, so the switch * sits at `expanded` rather than `medium`. `data-md-drawer-collapsed` (the view, from the * `wide` — window ≥ 840px — Alpine state) takes the standard sheet out of the layout entirely * while it is closed there, so the content beside it fills the space. */ @layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility; @import './button.css'; @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][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; z-index: 50; display: flex; width: 100%; flex-direction: column; overflow-y: auto; padding: var(--md-sys-measurement-space300); background-color: var(--md-sys-color-surface-container-low); color: var(--md-sys-color-on-surface); box-shadow: var(--md-sys-elevation-1); 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; } [data-md-drawer-sheet][data-md-side='end'] { inset-inline-end: 0; } [data-md-drawer-sheet][data-md-side='start'] { --sheet-offset: -100%; inset-inline-start: 0; } [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; 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: var(--sheet-offset) 0; } } @media (width >= 600px) { [data-md-drawer-sheet] { width: var(--sheet-width); max-width: calc(100vw - 64px); } [data-md-drawer-sheet][data-md-side='end'] { border-start-start-radius: var(--md-sys-shape-corner-lg); border-end-start-radius: var(--md-sys-shape-corner-lg); } [data-md-drawer-sheet][data-md-side='start'] { border-start-end-radius: var(--md-sys-shape-corner-lg); border-end-end-radius: var(--md-sys-shape-corner-lg); } } /* Co-planar from expanded: sticky beside the content, no scrim, no elevation, flat on `surface` with an outline-variant rule down the inner edge instead. It only fades here — an in-flow box does not travel like an overlay does. */ @media (width >= 840px) { [data-md-drawer][data-md-standard] { position: sticky; top: 0; height: 100dvh; flex-shrink: 0; align-self: flex-start; } [data-md-drawer][data-md-standard][data-md-drawer-collapsed] { display: none; } [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; height: 100%; translate: 0 0; border-radius: var(--md-sys-shape-corner-none); background-color: var(--md-sys-color-surface); box-shadow: none; opacity: 0; transition-property: opacity, display; transition-duration: var(--md-sys-motion-effects-default-duration); transition-timing-function: var(--md-sys-motion-easing-emphasized-accelerate); } [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] { translate: 0 0; opacity: 0; } } [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'] { border-inline-end: 1px solid var(--md-sys-color-outline-variant); } } [data-md-drawer-head] { margin-bottom: var(--md-sys-measurement-space200); } [data-md-drawer-head-row] { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; } [data-md-drawer-heading] { min-width: 0; } [data-md-drawer-title] { font: var(--md-sys-typescale-title-lg); letter-spacing: var(--md-sys-typescale-title-lg-tracking); } [data-md-drawer-subtitle] { margin-top: var(--md-sys-measurement-space50); color: var(--md-sys-color-on-surface-variant); font: var(--md-sys-typescale-body-md); letter-spacing: var(--md-sys-typescale-body-md-tracking); } [data-md-drawer-close] { display: inline-flex; flex-shrink: 0; margin-top: calc(-1 * var(--md-sys-measurement-space100)); margin-inline-end: -12px; } [data-md-drawer-head] > [data-md-divider] { margin-top: var(--md-sys-measurement-space200); } [data-md-drawer-body] { container-type: inline-size; flex: 1 1 0%; } [data-md-drawer-actions] { display: flex; min-height: var(--md-sys-measurement-space900); flex-shrink: 0; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: var(--md-sys-measurement-space100); padding-top: var(--md-sys-measurement-space200); } }