sass-references/angular-material/material/menu/menu.scss

228 lines
7.8 KiB
SCSS
Raw Permalink Normal View History

2024-12-06 10:42:08 +08:00
@use '@angular/cdk';
@use '../core/tokens/m2/mat/menu' as tokens-mat-menu;
@use '../core/tokens/token-utils';
@use '../core/style/menu-common';
@use '../core/style/button-common';
@use '../core/style/vendor-prefixes';
// Prevent rendering mat-menu as it can affect the flex layout.
mat-menu {
display: none;
}
.mat-mdc-menu-content {
margin: 0;
padding: 8px 0;
outline: 0;
&,
.mat-mdc-menu-item .mat-mdc-menu-item-text {
@include vendor-prefixes.smooth-font();
flex: 1;
white-space: normal;
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
@include token-utils.create-token-slot(font-family, item-label-text-font);
@include token-utils.create-token-slot(line-height, item-label-text-line-height);
@include token-utils.create-token-slot(font-size, item-label-text-size);
@include token-utils.create-token-slot(letter-spacing, item-label-text-tracking);
@include token-utils.create-token-slot(font-weight, item-label-text-weight);
}
}
}
.mat-mdc-menu-panel {
@include menu-common.base;
box-sizing: border-box;
outline: 0;
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
@include token-utils.create-token-slot(border-radius, container-shape);
@include token-utils.create-token-slot(background-color, container-color);
@include token-utils.create-token-slot(box-shadow, container-elevation-shadow);
}
// TODO(crisbeto): we don't need this for anything, but it was there when
// we used MDC's structural styles and removing it leads to sub-pixels
// differences in text rendering which break a lot of screenshots internally.
// We should clean it up eventually and re-approve all the screenshots.
will-change: transform, opacity;
// Prevent users from interacting with the panel while it's animating. Note that
// people won't be able to click through it, because the overlay pane will catch the click.
// This fixes the following issues:
// * Users accidentally opening sub-menus when the `overlapTrigger` option is enabled.
// * Users accidentally tapping on content inside the sub-menu on touch devices, if the
// sub-menu overlaps the trigger. The issue is due to touch devices emulating the
// `mouseenter` event by dispatching it on tap.
&.ng-animating {
pointer-events: none;
// If the same menu is assigned to multiple triggers and the user moves quickly between them
// (e.g. in a nested menu), the panel for the old menu may show up as empty while it's
// animating away. Hide such cases since they can look off to users.
&:has(.mat-mdc-menu-content:empty) {
display: none;
}
}
@include cdk.high-contrast {
outline: solid 1px;
}
.mat-divider {
// Use margin instead of padding since divider uses border-top to render out the line.
@include token-utils.use-tokens(
tokens-mat-menu.$prefix,
tokens-mat-menu.get-token-slots()
) {
color: token-utils.get-token-variable(divider-color);
margin-bottom: token-utils.get-token-variable(divider-bottom-spacing);
margin-top: token-utils.get-token-variable(divider-top-spacing);
}
}
}
.mat-mdc-menu-item {
display: flex;
position: relative;
align-items: center;
justify-content: flex-start;
overflow: hidden;
padding: 0;
// MDC's menu items are `<li>` nodes which don't need resets, however ours
// can be anything, including buttons, so we need to do the reset ourselves.
cursor: pointer;
width: 100%;
text-align: left;
box-sizing: border-box;
color: inherit;
font-size: inherit;
background: none;
text-decoration: none;
margin: 0; // Resolves an issue where buttons have an extra 2px margin on Safari.
min-height: 48px;
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
@include token-utils.create-token-slot(padding-left, item-leading-spacing);
@include token-utils.create-token-slot(padding-right, item-trailing-spacing);
}
@include button-common.reset;
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
$icons-selector: '.material-icons, mat-icon, [matButtonIcon]';
[dir='rtl'] & {
@include token-utils.create-token-slot(padding-left, item-trailing-spacing);
@include token-utils.create-token-slot(padding-right, item-leading-spacing);
}
&:has(#{$icons-selector}) {
@include token-utils.create-token-slot(padding-left, item-with-icon-leading-spacing);
@include token-utils.create-token-slot(padding-right, item-with-icon-trailing-spacing);
}
[dir='rtl'] &:has(#{$icons-selector}) {
@include token-utils.create-token-slot(padding-left, item-with-icon-trailing-spacing);
@include token-utils.create-token-slot(padding-right, item-with-icon-leading-spacing);
}
}
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
// The class selector isn't specific enough to overide the link pseudo selectors so we need
// to target them specifically, otherwise the item color might be overwritten by the user
// agent resets of the app.
&, &:visited, &:link {
@include token-utils.create-token-slot(color, item-label-text-color);
}
.mat-icon-no-color,
.mat-mdc-menu-submenu-icon {
@include token-utils.create-token-slot(color, item-icon-color);
}
}
&[disabled] {
cursor: default;
opacity: 0.38;
// The browser prevents clicks on disabled buttons from propagating which prevents the menu
// from closing, but clicks on child nodes still propagate which is inconsistent (see #16694).
// In order to keep the behavior consistent and prevent the menu from closing, we add an overlay
// on top of the content that will catch all the clicks while disabled.
&::after {
display: block;
position: absolute;
content: '';
top: 0;
left: 0;
bottom: 0;
right: 0;
}
}
// Inherited from MDC and necessary for some internal tests.
&:focus {
outline: 0;
}
.mat-icon {
flex-shrink: 0;
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
margin-right: token-utils.get-token-variable(item-spacing);
height: token-utils.get-token-variable(item-icon-size);
width: token-utils.get-token-variable(item-icon-size);
}
}
[dir='rtl'] & {
text-align: right;
.mat-icon {
margin-right: 0;
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
margin-left: token-utils.get-token-variable(item-spacing);
}
}
}
&:not([disabled]) {
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
&:hover {
@include token-utils.create-token-slot(background-color, item-hover-state-layer-color);
}
&.cdk-program-focused,
&.cdk-keyboard-focused,
&.mat-mdc-menu-item-highlighted {
@include token-utils.create-token-slot(background-color, item-focus-state-layer-color);
}
}
}
@include cdk.high-contrast {
$outline-width: 1px;
// We need to move the item 1px down, because Firefox seems to have
// an issue rendering the top part of the outline (see #21524).
margin-top: $outline-width;
}
}
.mat-mdc-menu-submenu-icon {
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
@include menu-common.item-submenu-icon(
token-utils.get-token-variable(item-spacing),
token-utils.get-token-variable(item-icon-size)
);
}
}
// Increase specificity because ripple styles are part of the `mat-core` mixin and can
// potentially overwrite the absolute position of the container.
.mat-mdc-menu-item .mat-mdc-menu-ripple {
@include menu-common.item-ripple;
}