@use './button-base'; @use '../core/style/private' as style-private; @use '../core/style/vendor-prefixes'; @use '../core/tokens/token-utils'; @use '../core/focus-indicators/private' as focus-indicators-private; @use '../core/tokens/m2/mdc/filled-button' as tokens-mdc-filled-button; @use '../core/tokens/m2/mat/filled-button' as tokens-mat-filled-button; @use '../core/tokens/m2/mdc/outlined-button' as tokens-mdc-outlined-button; @use '../core/tokens/m2/mat/outlined-button' as tokens-mat-outlined-button; @use '../core/tokens/m2/mdc/protected-button' as tokens-mdc-protected-button; @use '../core/tokens/m2/mat/protected-button' as tokens-mat-protected-button; @use '../core/tokens/m2/mdc/text-button' as tokens-mdc-text-button; @use '../core/tokens/m2/mat/text-button' as tokens-mat-text-button; .mat-mdc-button-base { text-decoration: none; } .mdc-button { @include vendor-prefixes.user-select(none); position: relative; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; min-width: 64px; border: none; outline: none; line-height: inherit; -webkit-appearance: none; overflow: visible; vertical-align: middle; background: transparent; padding: 0 8px; &::-moz-focus-inner { padding: 0; border: 0; } &:active { outline: none; } &:hover { cursor: pointer; } &:disabled { cursor: default; pointer-events: none; } &[hidden] { display: none; } .mdc-button__label { position: relative; } } .mat-mdc-button { $mat-text-button-slots: tokens-mat-text-button.get-token-slots(); @include token-utils.use-tokens(tokens-mat-text-button.$prefix, $mat-text-button-slots) { padding: 0 #{token-utils.get-token-variable(horizontal-padding, true)}; } @include token-utils.use-tokens( tokens-mdc-text-button.$prefix, tokens-mdc-text-button.get-token-slots() ) { @include token-utils.create-token-slot(height, container-height); @include token-utils.create-token-slot(font-family, label-text-font); @include token-utils.create-token-slot(font-size, label-text-size); @include token-utils.create-token-slot(letter-spacing, label-text-tracking); @include token-utils.create-token-slot(text-transform, label-text-transform); @include token-utils.create-token-slot(font-weight, label-text-weight); &, .mdc-button__ripple { @include token-utils.create-token-slot(border-radius, container-shape); } &:not(:disabled) { @include token-utils.create-token-slot(color, label-text-color); } // We need to re-apply the disabled tokens since MDC uses // `:disabled` which doesn't apply to anchors. @include button-base.mat-private-button-disabled { @include token-utils.create-token-slot(color, disabled-label-text-color); } } @include button-base.mat-private-button-horizontal-layout(tokens-mat-text-button.$prefix, $mat-text-button-slots, true); @include button-base.mat-private-button-ripple(tokens-mat-text-button.$prefix, $mat-text-button-slots); @include button-base.mat-private-button-touch-target(false, tokens-mat-text-button.$prefix, $mat-text-button-slots); } .mat-mdc-unelevated-button { $mat-filled-button-slots: tokens-mat-filled-button.get-token-slots(); transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1); @include token-utils.use-tokens( tokens-mdc-filled-button.$prefix, tokens-mdc-filled-button.get-token-slots() ) { @include token-utils.create-token-slot(height, container-height); @include token-utils.create-token-slot(font-family, label-text-font); @include token-utils.create-token-slot(font-size, label-text-size); @include token-utils.create-token-slot(letter-spacing, label-text-tracking); @include token-utils.create-token-slot(text-transform, label-text-transform); @include token-utils.create-token-slot(font-weight, label-text-weight); } @include token-utils.use-tokens(tokens-mat-filled-button.$prefix, $mat-filled-button-slots) { padding: 0 #{token-utils.get-token-variable(horizontal-padding, true)}; } @include button-base.mat-private-button-horizontal-layout(tokens-mat-filled-button.$prefix, $mat-filled-button-slots, false); @include button-base.mat-private-button-ripple(tokens-mat-filled-button.$prefix, $mat-filled-button-slots); @include button-base.mat-private-button-touch-target(false, tokens-mat-filled-button.$prefix, $mat-filled-button-slots); @include token-utils.use-tokens( tokens-mdc-filled-button.$prefix, tokens-mdc-filled-button.get-token-slots() ) { &:not(:disabled) { @include token-utils.create-token-slot(color, label-text-color); @include token-utils.create-token-slot(background-color, container-color); } &, .mdc-button__ripple { @include token-utils.create-token-slot(border-radius, container-shape); } // We need to re-apply the disabled tokens since MDC uses // `:disabled` which doesn't apply to anchors. @include button-base.mat-private-button-disabled { @include token-utils.create-token-slot(color, disabled-label-text-color); @include token-utils.create-token-slot(background-color, disabled-container-color); } } } .mat-mdc-raised-button { $mat-protected-button-slots: tokens-mat-protected-button.get-token-slots(); transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1); @include token-utils.use-tokens( tokens-mdc-protected-button.$prefix, tokens-mdc-protected-button.get-token-slots() ) { @include button-base.mat-private-button-elevation(container-elevation); @include token-utils.create-token-slot(height, container-height); @include token-utils.create-token-slot(font-family, label-text-font); @include token-utils.create-token-slot(font-size, label-text-size); @include token-utils.create-token-slot(letter-spacing, label-text-tracking); @include token-utils.create-token-slot(text-transform, label-text-transform); @include token-utils.create-token-slot(font-weight, label-text-weight); } @include token-utils.use-tokens( tokens-mat-protected-button.$prefix, $mat-protected-button-slots ) { padding: 0 #{token-utils.get-token-variable(horizontal-padding, true)}; } @include button-base.mat-private-button-horizontal-layout(tokens-mat-protected-button.$prefix, $mat-protected-button-slots, false); @include button-base.mat-private-button-ripple(tokens-mat-protected-button.$prefix, $mat-protected-button-slots); @include button-base.mat-private-button-touch-target(false, tokens-mat-protected-button.$prefix, $mat-protected-button-slots); @include token-utils.use-tokens( tokens-mdc-protected-button.$prefix, tokens-mdc-protected-button.get-token-slots() ) { &:not(:disabled) { @include token-utils.create-token-slot(color, label-text-color); @include token-utils.create-token-slot(background-color, container-color); } &, .mdc-button__ripple { @include token-utils.create-token-slot(border-radius, container-shape); } &:hover { @include button-base.mat-private-button-elevation(hover-container-elevation); } &:focus { @include button-base.mat-private-button-elevation(focus-container-elevation); } &:active, &:focus:active { @include button-base.mat-private-button-elevation(pressed-container-elevation); } // We need to re-apply the disabled tokens since MDC uses // `:disabled` which doesn't apply to anchors. @include button-base.mat-private-button-disabled { @include token-utils.create-token-slot(color, disabled-label-text-color); @include token-utils.create-token-slot(background-color, disabled-container-color); &.mat-mdc-button-disabled { @include button-base.mat-private-button-elevation(disabled-container-elevation); } } } } .mat-mdc-outlined-button { $mat-outlined-button-slots: tokens-mat-outlined-button.get-token-slots(); border-style: solid; transition: border 280ms cubic-bezier(0.4, 0, 0.2, 1); @include token-utils.use-tokens( tokens-mdc-outlined-button.$prefix, tokens-mdc-outlined-button.get-token-slots() ) { @include token-utils.create-token-slot(height, container-height); @include token-utils.create-token-slot(font-family, label-text-font); @include token-utils.create-token-slot(font-size, label-text-size); @include token-utils.create-token-slot(letter-spacing, label-text-tracking); @include token-utils.create-token-slot(text-transform, label-text-transform); @include token-utils.create-token-slot(font-weight, label-text-weight); @include token-utils.create-token-slot(border-radius, container-shape); @include token-utils.create-token-slot(border-width, outline-width); } @include token-utils.use-tokens(tokens-mat-outlined-button.$prefix, $mat-outlined-button-slots) { padding: 0 #{token-utils.get-token-variable(horizontal-padding, true)}; } @include button-base.mat-private-button-horizontal-layout(tokens-mat-outlined-button.$prefix, $mat-outlined-button-slots, false); @include button-base.mat-private-button-ripple(tokens-mat-outlined-button.$prefix, $mat-outlined-button-slots); @include button-base.mat-private-button-touch-target(false, tokens-mat-outlined-button.$prefix, $mat-outlined-button-slots); @include token-utils.use-tokens( tokens-mdc-outlined-button.$prefix, tokens-mdc-outlined-button.get-token-slots() ) { &:not(:disabled) { @include token-utils.create-token-slot(color, label-text-color); @include token-utils.create-token-slot(border-color, outline-color); } // We need to re-apply the disabled tokens since MDC uses // `:disabled` which doesn't apply to anchors. @include button-base.mat-private-button-disabled { @include token-utils.create-token-slot(color, disabled-label-text-color); @include token-utils.create-token-slot(border-color, disabled-outline-color); } // TODO(crisbeto): this causes a weird gap between the ripple and the // outline. We should remove it and update the screenshot tests. .mdc-button__ripple { @include token-utils.create-token-slot(border-width, outline-width); border-style: solid; border-color: transparent; } } } .mat-mdc-button, .mat-mdc-unelevated-button, .mat-mdc-raised-button, .mat-mdc-outlined-button { @include button-base.mat-private-button-interactive(); @include style-private.private-animation-noop(); // Similar to MDC's `_icon-structure`, apart from the margin which we // handle via custom tokens in `mat-private-button-horizontal-layout`. & > .mat-icon { $icon-size: 1.125rem; display: inline-block; position: relative; vertical-align: top; font-size: $icon-size; height: $icon-size; width: $icon-size; } } // Since the stroked button has has an actual border that reduces the available space for // child elements such as the ripple container or focus overlay, an inherited border radius // for the absolute-positioned child elements does not work properly. This is because the // child element cannot expand to the same boundaries as the parent element with a border. // In order to work around this issue by *not* hiding overflow, we adjust the child elements // to fully cover the actual button element. This means that the border-radius would be correct // then. See: https://github.com/angular/components/issues/13738 .mat-mdc-outlined-button .mat-mdc-button-ripple, .mat-mdc-outlined-button .mdc-button__ripple { $offset: -1px; top: $offset; left: $offset; bottom: $offset; right: $offset; } // For the button element, default inset/offset values are necessary to ensure that // the focus indicator is sufficiently contrastive and renders appropriately. .mat-mdc-unelevated-button, .mat-mdc-raised-button { .mat-focus-indicator::before { $default-border-width: focus-indicators-private.$default-border-width; $border-width: var(--mat-focus-indicator-border-width, #{$default-border-width}); $offset: calc(#{$border-width} + 2px); margin: calc(#{$offset} * -1); } } .mat-mdc-outlined-button .mat-focus-indicator::before { $default-border-width: focus-indicators-private.$default-border-width; $border-width: var(--mat-focus-indicator-border-width, #{$default-border-width}); $offset: calc(#{$border-width} + 3px); margin: calc(#{$offset} * -1); }