/* * The menus: `` and what a form's own dropdowns wear too, so a menu and a form read as * one family. * * Three lists wear it: * * - ``'s own popover (`[data-md-menu-popover]`) and, inside it, a submenu * (`[data-md-submenu]`, menu-item.css). * - ``'s: the native with no field chrome โ€” M3's menus embed a text field, not a text * field component. */ [data-md-menu-filter] { position: sticky; inset-block-start: 0; z-index: 1; display: flex; align-items: center; gap: 12px; min-block-size: var(--md-sys-measurement-space600); padding-inline: var(--md-sys-measurement-space200); border-block-end: 1px solid var(--md-sys-color-outline-variant); background-color: var(--material-menu-surface, var(--md-sys-color-surface-container-low)); } [data-md-menu-filter] input { flex: 1; min-inline-size: 0; border-width: 0; background-color: transparent; padding: 0; color: inherit; font: var(--md-sys-typescale-body-lg); letter-spacing: var(--md-sys-typescale-body-lg-tracking); font-variation-settings: normal; outline: none; } [data-md-menu-filter] input::placeholder { color: color-mix(in srgb, var(--material-menu-ink, var(--md-sys-color-on-surface)) 70%, transparent); } [data-md-menu-list] { padding: var(--md-sys-measurement-space50); } [data-md-menu-empty] { padding-inline: var(--md-sys-measurement-space200); padding-block: 12px; color: var(--md-sys-color-on-surface-variant); font: var(--md-sys-typescale-body-md); letter-spacing: var(--md-sys-typescale-body-md-tracking); font-variation-settings: normal; } /* The filter hides what the query leaves out with the `hidden` attribute; a row's own `display: flex` would otherwise beat the user agent's `[hidden] { display: none }`. */ :is([data-md-menu-popover], [data-md-menu-sheet]) [hidden] { display: none; } /* `data-md-active` is the row the arrow keys are on while the focus stays in the field โ€” the state layer the roving focus would have drawn, without taking the focus off the field. A chosen or current row keeps its own colour. */ :is([data-md-menu-popover], [data-md-menu-sheet]) [role^="menuitem"][data-md-active]:not([aria-checked="true"], [aria-current="page"]) { background-color: color-mix(in srgb, var(--material-menu-ink, var(--md-sys-color-on-surface)) 8%, transparent); } /* * ``: the copy of the list in the bottom sheet a compact window opens * instead of the popover. The sheet is surface-container-low, as the standard menu is, so the * fallbacks above already paint its field; the field reaches both edges of the sheet and holds * its icon where the rows hold theirs, 24px in (the list is 8px in, a row's own padding 16px). * `-24px` cancels the bottom sheet's own padding. */ [data-md-menu-sheet] { margin-inline: calc(-1 * var(--md-sys-measurement-space300)); padding-inline: var(--md-sys-measurement-space100); } [data-md-menu-sheet]:has(> [data-md-menu-filter]) { padding-inline: 0; } [data-md-menu-sheet] [data-md-menu-filter] { padding-inline: var(--md-sys-measurement-space300); } [data-md-menu-sheet] [data-md-menu-list] { padding-inline: var(--md-sys-measurement-space100); padding-block: var(--md-sys-measurement-space50) 0; } /* * A submenu there opens in place: its list stands under the item, inset by 16px, instead of in * a popover beside it, which a sheet has no room for (M3 calls submenus "best suited to large * screens", docs/reference/m3/components-actions-communication-containment.md ยง Menus). The * markup is the popover's, never shown as one: the user agent's `[popover]` box is undone, the * list is shown while its item says `aria-expanded="true"`, and it fades in on the effects * track. */ [data-md-menu-sheet] [data-md-submenu] { position: static; inset: auto; inline-size: auto; max-inline-size: none; block-size: auto; max-block-size: none; margin: 0; padding-block: var(--md-sys-measurement-space25); padding-inline: var(--md-sys-measurement-space200) 0; overflow: visible; border-radius: 0; background-color: transparent; color: inherit; box-shadow: none; opacity: 1; scale: none; transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); } [data-md-menu-sheet] [aria-expanded="true"] + [data-md-submenu] { display: block; @starting-style { opacity: 0; } } /* The chevron turns from the way a popover would open to the way this list did: down, which is a quarter turn the other way on the chevron `mirror-rtl` mirrors too. */ [data-md-menu-sheet] [data-md-submenu-chevron] { transition: rotate var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast); } [data-md-menu-sheet] [aria-expanded="true"] > [data-md-submenu-chevron] { rotate: 90deg; &:dir(rtl) { rotate: -90deg; } } [data-md-field-menu] { max-block-size: 18rem; overflow-y: auto; padding-block: var(--md-sys-measurement-space100); border-radius: var(--md-sys-shape-corner-xs); background-color: var(--md-sys-color-surface-container); box-shadow: var(--md-sys-elevation-2); } /* As a popover (``), it hangs under its field, as wide, and goes above only when there is no room below. */ [data-md-field-menu][popover] { inset: auto; top: anchor(bottom); left: anchor(left); width: anchor-size(width); margin: var(--md-sys-measurement-space50) 0; border-width: 0; padding-inline: 0; color: var(--md-sys-color-on-surface); position-try-fallbacks: flip-block; } [data-md-field-option][aria-disabled="true"] { color: color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent); cursor: default; } [data-md-field-option] { display: flex; align-items: center; gap: 12px; min-block-size: var(--md-sys-measurement-space600); padding-inline: var(--md-sys-measurement-space200); color: var(--md-sys-color-on-surface); font: var(--md-sys-typescale-body-lg); letter-spacing: var(--md-sys-typescale-body-lg-tracking); font-variation-settings: normal; cursor: pointer; } /* `data-md-active` is the row the arrow keys or the pointer are on. */ [data-md-field-option][data-md-active] { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 8%, transparent); } [data-md-field-option][aria-selected="true"] { background-color: var(--md-sys-color-secondary-container); color: var(--md-sys-color-on-secondary-container); } [data-md-field-option][aria-selected="true"][data-md-active] { background-color: color-mix(in srgb, var(--md-sys-color-on-secondary-container) 8%, var(--md-sys-color-secondary-container)); } [data-md-field-check] { margin-inline-start: auto; } [data-md-field-option]:not([aria-selected="true"]) [data-md-field-check] { visibility: hidden; } @supports (appearance: base-select) { /* The select itself opts in from select.css, after its own `appearance: none`: both sit in `material.components` with the same specificity, and select.css's block always comes after this file, which it imports. */ select[data-md-field-control]::picker(select) { appearance: base-select; } /* The menu. The browser anchors it to the select; the select covers its whole field (field.css), so the menu is at least the field's width. It hangs under the field and goes above only when it does not fit there โ€” the browser's own order tries the roomier side first, which opened a menu upwards with room to spare under it. It opens with a fade and a grow on the spatial spring and closes with a fade, as `` does. */ select[data-md-field-control]::picker(select) { position-try-order: normal; max-block-size: 18rem; max-inline-size: calc(100vw - 32px); margin-block: var(--md-sys-measurement-space50); padding-block: var(--md-sys-measurement-space100); border-width: 0; border-radius: var(--md-sys-shape-corner-xs); background-color: var(--md-sys-color-surface-container); color: var(--md-sys-color-on-surface); box-shadow: var(--md-sys-elevation-2); opacity: 0; transform-origin: top; transition-property: opacity, display, overlay; transition-duration: var(--md-sys-motion-effects-fast-duration); transition-timing-function: var(--md-sys-motion-effects-fast); transition-behavior: allow-discrete; } select[data-md-field-control]:open::picker(select) { opacity: 1; transition-property: opacity, scale, display, overlay; transition-duration: var(--md-sys-motion-spatial-fast-duration); transition-timing-function: var(--md-sys-motion-spatial-fast); } @starting-style { select[data-md-field-control]:open::picker(select) { opacity: 0; scale: 0.95; } } select[data-md-field-control] option { display: flex; align-items: center; gap: 12px; min-block-size: var(--md-sys-measurement-space600); padding-block: 0; padding-inline: var(--md-sys-measurement-space200); background-color: transparent; color: var(--md-sys-color-on-surface); font: var(--md-sys-typescale-body-lg); letter-spacing: var(--md-sys-typescale-body-lg-tracking); font-variation-settings: normal; outline: none; cursor: pointer; } @media (hover: hover) { select[data-md-field-control] option:hover { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 8%, transparent); } } select[data-md-field-control] option:focus-visible { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent); } select[data-md-field-control] option:checked { background-color: var(--md-sys-color-secondary-container); color: var(--md-sys-color-on-secondary-container); } @media (hover: hover) { select[data-md-field-control] option:checked:hover { background-color: color-mix(in srgb, var(--md-sys-color-on-secondary-container) 8%, var(--md-sys-color-secondary-container)); } } select[data-md-field-control] option:checked:focus-visible { background-color: color-mix(in srgb, var(--md-sys-color-on-secondary-container) 10%, var(--md-sys-color-secondary-container)); } select[data-md-field-control] option:disabled { background-color: transparent; color: color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent); cursor: default; } /* The tick, at the row's end: the browser draws it before the label, and hides it on every row but the chosen one. The Material Symbol, as a mask, so it takes the row's ink. */ select[data-md-field-control] option::checkmark { content: ""; order: 1; flex: none; inline-size: var(--md-sys-measurement-space300); block-size: var(--md-sys-measurement-space300); margin-inline-start: auto; background-color: currentColor; mask: url("../../svg/symbols/outlined/check.svg") center / contain no-repeat; } } }