diff --git a/src/material-experimental/mdc-button/_button-base.scss b/src/material-experimental/mdc-button/_button-base.scss
index 7c5cbfa28515..f0b0f8ee88ef 100644
--- a/src/material-experimental/mdc-button/_button-base.scss
+++ b/src/material-experimental/mdc-button/_button-base.scss
@@ -1,3 +1,4 @@
+@use 'sass:map';
@use '@material/touch-target' as mdc-touch-target;
@use '../mdc-helpers/mdc-helpers';
@use '../../material/core/style/layout-common';
@@ -8,22 +9,10 @@
// ripple and state container so that they fill the button, match the border radius, and avoid
// pointer events.
@mixin mat-private-button-interactive() {
- .mdc-button__ripple::before, .mdc-button__ripple::after,
- .mdc-fab__ripple::before, .mdc-fab__ripple::after {
- content: '';
- pointer-events: none;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- opacity: 0;
- border-radius: inherit;
- @content;
- }
-
// The ripple container should match the bounds of the entire button.
- .mat-mdc-button-ripple, .mdc-button__ripple, .mdc-fab__ripple {
+ .mat-mdc-button-ripple,
+ .mat-mdc-button-persistent-ripple,
+ .mat-mdc-button-persistent-ripple::before {
@include layout-common.fill;
// Disable pointer events for the ripple container and state overlay because the container
@@ -38,6 +27,17 @@
border-radius: inherit;
}
+ // We use ::before so that we can reuse some of MDC's theming.
+ .mat-mdc-button-persistent-ripple::before {
+ content: '';
+ opacity: 0;
+ background-color: var(--mat-mdc-button-persistent-ripple-color);
+ }
+
+ .mat-ripple-element {
+ background-color: var(--mat-mdc-button-ripple-color);
+ }
+
// The content should appear over the state and ripple layers, otherwise they may adversely affect
// the accessibility of the text content.
.mdc-button__label {
@@ -59,6 +59,7 @@
&[disabled] {
cursor: default;
pointer-events: none;
+ @content;
}
}
@@ -75,3 +76,15 @@
$query: mdc-helpers.$mat-base-styles-query);
}
}
+
+// Changes a button theme to exclude the ripple styles.
+@function mat-private-button-remove-ripple($theme) {
+ @return map.merge($theme, (
+ focus-state-layer-color: null,
+ focus-state-layer-opacity: null,
+ hover-state-layer-color: null,
+ hover-state-layer-opacity: null,
+ pressed-state-layer-color: null,
+ pressed-state-layer-opacity: null,
+ ));
+}
diff --git a/src/material-experimental/mdc-button/_button-theme-private.scss b/src/material-experimental/mdc-button/_button-theme-private.scss
index 46b97177d996..742438150fd8 100644
--- a/src/material-experimental/mdc-button/_button-theme-private.scss
+++ b/src/material-experimental/mdc-button/_button-theme-private.scss
@@ -1,28 +1,43 @@
+@use 'sass:map';
+@use '@material/ripple/ripple-theme' as mdc-ripple-theme;
@use '@material/theme/theme-color' as mdc-theme-color;
-@use '@material/theme/theme' as mdc-theme;
@use '../../material/core/ripple/ripple-theme';
-// Selector for the element that has a background color and opacity applied to its ::before and
-// ::after for state interactions (hover, active, focus). Their API calls this their
-// "ripple target", but we do not use it as our ripple, just state color.
-$button-state-target: '.mdc-button__ripple';
-$fab-state-target: '.mdc-fab__ripple';
-
-// The MDC button's ripple ink color is based on the theme color, not on the foreground base
-// which is what the ripple mixin uses. This creates a new theme that sets the color to the
-// foreground base to appropriately color the ink.
-@mixin ripple-ink-color($mdc-color) {
- @include ripple-theme.color((
- foreground: (
- base: mdc-theme-color.prop-value($mdc-color)
- ),
- ));
+@mixin _ripple-color($color) {
+ --mat-mdc-button-persistent-ripple-color: #{$color};
+ --mat-mdc-button-ripple-color: #{rgba($color, 0.1)};
}
-// Applies the disabled theme color to the text color.
-@mixin apply-disabled-color() {
- @include mdc-theme.prop(color,
- mdc-theme-color.ink-color-for-fill_(disabled, mdc-theme-color.$background));
+@mixin ripple-theme-styles($config, $is-filled) {
+ $opacities: if(map.get($config, is-dark),
+ mdc-ripple-theme.$light-ink-opacities, mdc-ripple-theme.$dark-ink-opacities);
+
+ // Ideally these styles would be structural, but MDC bases some of the opacities on the theme.
+ &:hover .mat-mdc-button-persistent-ripple::before {
+ opacity: map.get($opacities, hover);
+ }
+
+ &:focus .mat-mdc-button-persistent-ripple::before {
+ opacity: map.get($opacities, focus);
+ }
+
+ &:active .mat-mdc-button-persistent-ripple::before {
+ opacity: map.get($opacities, press);
+ }
+
+ @include _ripple-color(mdc-theme-color.prop-value(on-surface));
+
+ &.mat-primary {
+ @include _ripple-color(mdc-theme-color.prop-value(if($is-filled, on-primary, primary)));
+ }
+
+ &.mat-accent {
+ @include _ripple-color(mdc-theme-color.prop-value(if($is-filled, on-secondary, secondary)));
+ }
+
+ &.mat-warn {
+ @include _ripple-color(mdc-theme-color.prop-value(if($is-filled, on-error, error)));
+ }
}
// Wraps the content style in a selector for the disabled state.
@@ -37,14 +52,6 @@ $fab-state-target: '.mdc-fab__ripple';
}
}
-// Applies the disabled theme background color for raised buttons. Value is taken from
-// mixin `mdc-button--filled`.
-// TODO(andrewseguin): Discuss with the MDC team about providing a variable for the 0.12 value
-// or otherwise have a mixin we can call to apply this style for both button and anchors.
-@mixin apply-disabled-background() {
- @include mdc-theme.prop(background-color, rgba(mdc-theme-color.prop-value(on-surface), 0.12));
-}
-
// Hides the touch target on lower densities.
@mixin touch-target-density($scale) {
@if ($scale == -2 or $scale == 'minimum') {
diff --git a/src/material-experimental/mdc-button/_button-theme.scss b/src/material-experimental/mdc-button/_button-theme.scss
index 4f0df23e0872..9f4225d128ff 100644
--- a/src/material-experimental/mdc-button/_button-theme.scss
+++ b/src/material-experimental/mdc-button/_button-theme.scss
@@ -1,146 +1,181 @@
+@use 'sass:map';
@use '@material/button/button' as mdc-button;
@use '@material/button/button-theme' as mdc-button-theme;
-@use '@material/ripple/ripple-theme' as mdc-ripple-theme;
+@use '@material/button/button-text-theme' as mdc-button-text-theme;
+@use '@material/button/button-filled-theme' as mdc-button-filled-theme;
+@use '@material/button/button-protected-theme' as mdc-button-protected-theme;
+@use '@material/button/button-outlined-theme' as mdc-button-outlined-theme;
@use '@material/theme/theme-color' as mdc-theme-color;
-@use '@material/theme/theme' as mdc-theme;
-@use '@material/elevation/elevation-theme' as mdc-elevation-theme;
-@use '../../material/core/ripple/ripple-theme';
@use '../../material/core/typography/typography';
@use '../mdc-helpers/mdc-helpers';
@use '../../material/core/theming/theming';
@use './button-theme-private';
+@mixin _button-variant($color) {
+ @include mdc-button-text-theme.theme((
+ label-text-color: $color,
+ ));
+}
+
+@mixin _unelevated-button-variant($foreground, $background) {
+ @include mdc-button-filled-theme.theme((
+ container-color: $background,
+ label-text-color: $foreground,
+ ));
+}
+
+@mixin _raised-button-variant($foreground, $background) {
+ @include mdc-button-protected-theme.theme((
+ container-color: $background,
+ label-text-color: $foreground,
+ ));
+}
+
+@mixin _outlined-button-variant($color) {
+ @include mdc-button-outlined-theme.theme((
+ label-text-color: $color,
+ outline-color: $color,
+ ));
+}
+
@mixin color($config-or-theme) {
$config: theming.get-color-config($config-or-theme);
@include mdc-helpers.mat-using-mdc-theme($config) {
- // Add state interactions for hover, focus, press, active. Colors are changed based on
- // the mixin mdc-states-base-color
- .mat-mdc-button, .mat-mdc-raised-button, .mat-mdc-unelevated-button, .mat-mdc-outlined-button {
- @include mdc-ripple-theme.states(
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- }
-
- .mat-mdc-button, .mat-mdc-outlined-button {
+ $is-dark: map.get($config, is-dark);
+ $on-surface: mdc-theme-color.prop-value(on-surface);
+ $surface: mdc-theme-color.prop-value(surface);
+ $disabled-ink-color: rgba($on-surface, if($is-dark, 0.5, 0.38));
+ $disabled-container-color: rgba($on-surface, 0.12);
+ $primary: mdc-theme-color.prop-value(primary);
+ $on-primary: mdc-theme-color.prop-value(on-primary);
+ $secondary: mdc-theme-color.prop-value(secondary);
+ $on-secondary: mdc-theme-color.prop-value(on-secondary);
+ $error: mdc-theme-color.prop-value(error);
+ $on-error: mdc-theme-color.prop-value(on-error);
+
+ .mat-mdc-button {
&.mat-unthemed {
- @include mdc-button-theme.ink-color(mdc-theme-color.$on-surface,
- $query: mdc-helpers.$mat-theme-styles-query);
+ @include _button-variant($on-surface);
}
&.mat-primary {
- @include mdc-button-theme.ink-color(primary, $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-ripple-theme.states-base-color(primary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include button-theme-private.ripple-ink-color(primary);
+ @include _button-variant($primary);
}
&.mat-accent {
- @include mdc-button-theme.ink-color(secondary, $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-ripple-theme.states-base-color(secondary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include button-theme-private.ripple-ink-color(secondary);
+ @include _button-variant($secondary);
}
&.mat-warn {
- @include mdc-button-theme.ink-color(error, $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-ripple-theme.states-base-color(error,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include button-theme-private.ripple-ink-color(error);
+ @include _button-variant($error);
+ }
+
+ @include button-theme-private.apply-disabled-style() {
+ @include mdc-button-text-theme.theme((
+ // We need to pass both the disabled and enabled values, because the enabled
+ // ones apply to anchors while the disabled ones are for buttons.
+ disabled-label-text-color: $disabled-ink-color,
+ label-text-color: $disabled-ink-color
+ ));
}
}
- .mat-mdc-raised-button,
.mat-mdc-unelevated-button {
&.mat-unthemed {
- @include mdc-button-theme.container-fill-color(mdc-theme-color.$surface,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-button-theme.ink-color(mdc-theme-color.$on-surface,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-ripple-theme.states-base-color(mdc-theme-color.$on-surface,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
+ @include _unelevated-button-variant($on-surface, $surface);
}
&.mat-primary {
- @include mdc-button-theme.container-fill-color(primary,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-button-theme.ink-color(on-primary,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-ripple-theme.states-base-color(on-primary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include button-theme-private.ripple-ink-color(on-primary);
+ @include _unelevated-button-variant($on-primary, $primary);
}
&.mat-accent {
- @include mdc-button-theme.container-fill-color(secondary,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-button-theme.ink-color(on-secondary,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-ripple-theme.states-base-color(on-secondary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include button-theme-private.ripple-ink-color(on-secondary);
+ @include _unelevated-button-variant($on-secondary, $secondary);
}
&.mat-warn {
- @include mdc-button-theme.container-fill-color(error,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-button-theme.ink-color(on-error, $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-ripple-theme.states-base-color(on-error,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include button-theme-private.ripple-ink-color(on-error);
+ @include _unelevated-button-variant($on-error, $error);
}
@include button-theme-private.apply-disabled-style() {
- @include button-theme-private.apply-disabled-background();
+ @include mdc-button-filled-theme.theme((
+ // We need to pass both the disabled and enabled values, because the enabled
+ // ones apply to anchors while the disabled ones are for buttons.
+ disabled-container-color: $disabled-container-color,
+ disabled-label-text-color: $disabled-ink-color,
+ container-color: $disabled-container-color,
+ label-text-color: $disabled-ink-color,
+ ));
}
}
- .mat-mdc-outlined-button {
+ .mat-mdc-raised-button {
&.mat-unthemed {
- @include mdc-button-theme.outline-color(mdc-theme-color.$on-surface,
- $query: mdc-helpers.$mat-theme-styles-query);
+ @include _raised-button-variant($on-surface, $surface);
}
&.mat-primary {
- @include mdc-button-theme.outline-color(primary,
- $query: mdc-helpers.$mat-theme-styles-query);
+ @include _raised-button-variant($on-primary, $primary);
}
&.mat-accent {
- @include mdc-button-theme.outline-color(secondary,
- $query: mdc-helpers.$mat-theme-styles-query);
+ @include _raised-button-variant($on-secondary, $secondary);
}
&.mat-warn {
- @include mdc-button-theme.outline-color(error,
- $query: mdc-helpers.$mat-theme-styles-query);
+ @include _raised-button-variant($on-error, $error);
}
@include button-theme-private.apply-disabled-style() {
- @include mdc-theme.prop(border-color,
- mdc-theme-color.ink-color-for-fill_(disabled, mdc-theme-color.$background));
+ @include mdc-button-protected-theme.theme((
+ // We need to pass both the disabled and enabled values, because the enabled
+ // ones apply to anchors while the disabled ones are for buttons.
+ disabled-container-color: $disabled-container-color,
+ disabled-label-text-color: $disabled-ink-color,
+ container-color: $disabled-container-color,
+ label-text-color: $disabled-ink-color,
+ container-elevation: 0,
+ ));
}
}
- .mat-mdc-raised-button {
- @include button-theme-private.apply-disabled-style() {
- @include mdc-elevation-theme.elevation(0, $query: mdc-helpers.$mat-theme-styles-query);
+ .mat-mdc-outlined-button {
+ &.mat-unthemed {
+ @include _outlined-button-variant($on-surface);
+ }
+
+ &.mat-primary {
+ @include _outlined-button-variant($primary);
+ }
+
+ &.mat-accent {
+ @include _outlined-button-variant($secondary);
+ }
+
+ &.mat-warn {
+ @include _outlined-button-variant($error);
}
- }
- .mat-mdc-button, .mat-mdc-raised-button, .mat-mdc-unelevated-button, .mat-mdc-outlined-button {
@include button-theme-private.apply-disabled-style() {
- @include button-theme-private.apply-disabled-color();
+ @include mdc-button-outlined-theme.theme((
+ // We need to pass both the disabled and enabled values, because the enabled
+ // ones apply to anchors while the disabled ones are for buttons.
+ label-text-color: $disabled-ink-color,
+ outline-color: $disabled-ink-color,
+ disabled-label-text-color: $disabled-ink-color,
+ disabled-outline-color: $disabled-ink-color,
+ ));
}
}
- @include mdc-button.without-ripple($query: mdc-helpers.$mat-theme-styles-query);
+ // Ripple colors
+ .mat-mdc-button, .mat-mdc-outlined-button {
+ @include button-theme-private.ripple-theme-styles($config, false);
+ }
+
+ .mat-mdc-raised-button, .mat-mdc-unelevated-button {
+ @include button-theme-private.ripple-theme-styles($config, true);
+ }
}
}
diff --git a/src/material-experimental/mdc-button/_fab-theme.scss b/src/material-experimental/mdc-button/_fab-theme.scss
index 676fa8340ce3..68075b26bb35 100644
--- a/src/material-experimental/mdc-button/_fab-theme.scss
+++ b/src/material-experimental/mdc-button/_fab-theme.scss
@@ -1,68 +1,62 @@
+@use 'sass:map';
@use '@material/fab/fab' as mdc-fab;
@use '@material/fab/fab-theme' as mdc-fab-theme;
-@use '@material/ripple/ripple-theme' as mdc-ripple-theme;
-@use '@material/elevation/elevation-theme' as mdc-elevation-theme;
@use '@material/theme/theme-color' as mdc-theme-color;
@use '../mdc-helpers/mdc-helpers';
@use '../../material/core/theming/theming';
@use '../../material/core/typography/typography';
@use './button-theme-private';
+@mixin _fab-variant($foreground, $background) {
+ @include mdc-fab-theme.theme((
+ container-color: $background,
+ icon-color: $foreground,
+ ));
+
+ --mat-mdc-fab-color: #{$foreground};
+}
+
@mixin color($config-or-theme) {
$config: theming.get-color-config($config-or-theme);
@include mdc-helpers.mat-using-mdc-theme($config) {
+ $on-surface: mdc-theme-color.prop-value(on-surface);
+ $is-dark: map.get($config, is-dark);
+
.mat-mdc-fab, .mat-mdc-mini-fab {
- @include mdc-ripple-theme.states(
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$fab-state-target);
+ @include button-theme-private.ripple-theme-styles($config, true);
&.mat-unthemed {
- @include mdc-ripple-theme.states-base-color(mdc-theme-color.$on-surface,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$fab-state-target);
- @include mdc-fab-theme.container-color(mdc-theme-color.$on-surface,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-fab-theme.ink-color(mdc-theme-color.$on-surface,
- $query: mdc-helpers.$mat-theme-styles-query);
+ @include _fab-variant($on-surface, mdc-theme-color.prop-value(surface));
}
&.mat-primary {
- @include mdc-ripple-theme.states-base-color(on-primary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$fab-state-target);
- @include mdc-fab-theme.container-color(primary,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-fab-theme.ink-color(on-primary, $query: mdc-helpers.$mat-theme-styles-query);
- @include button-theme-private.ripple-ink-color(on-primary);
+ @include _fab-variant(
+ mdc-theme-color.prop-value(on-primary),
+ mdc-theme-color.prop-value(primary)
+ );
}
&.mat-accent {
- @include mdc-ripple-theme.states-base-color(on-secondary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$fab-state-target);
- @include mdc-fab-theme.container-color(secondary,
- $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-fab-theme.ink-color(on-secondary, $query: mdc-helpers.$mat-theme-styles-query);
- @include button-theme-private.ripple-ink-color(on-secondary);
+ @include _fab-variant(
+ mdc-theme-color.prop-value(on-secondary),
+ mdc-theme-color.prop-value(secondary)
+ );
}
&.mat-warn {
- @include mdc-ripple-theme.states-base-color(on-error,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$fab-state-target);
- @include mdc-fab-theme.container-color(error, $query: mdc-helpers.$mat-theme-styles-query);
- @include mdc-fab-theme.ink-color(on-error, $query: mdc-helpers.$mat-theme-styles-query);
- @include button-theme-private.ripple-ink-color(on-error);
+ @include _fab-variant(
+ mdc-theme-color.prop-value(on-error),
+ mdc-theme-color.prop-value(error)
+ );
}
@include button-theme-private.apply-disabled-style() {
- @include button-theme-private.apply-disabled-color();
- @include button-theme-private.apply-disabled-background();
- @include mdc-elevation-theme.elevation(0, $query: mdc-helpers.$mat-theme-styles-query);
+ @include _fab-variant(
+ rgba($on-surface, if(map.get($config, is-dark), 0.5, 0.38)),
+ rgba($on-surface, 0.12)
+ );
}
}
-
- @include mdc-fab.without-ripple($query: mdc-helpers.$mat-theme-styles-query);
}
}
diff --git a/src/material-experimental/mdc-button/_icon-button-theme.scss b/src/material-experimental/mdc-button/_icon-button-theme.scss
index 16196ca888db..e69cb94f0dad 100644
--- a/src/material-experimental/mdc-button/_icon-button-theme.scss
+++ b/src/material-experimental/mdc-button/_icon-button-theme.scss
@@ -1,5 +1,7 @@
+@use 'sass:map';
@use '@material/icon-button/mixins' as mdc-icon-button;
-@use '@material/ripple/ripple-theme' as mdc-ripple-theme;
+@use '@material/icon-button/icon-button-theme' as mdc-icon-button-theme;
+@use '@material/theme/theme-color' as mdc-theme-color;
@use '../mdc-helpers/mdc-helpers';
@use '../../material/core/theming/theming';
@use '../../material/core/typography/typography';
@@ -8,41 +10,32 @@
@mixin color($config-or-theme) {
$config: theming.get-color-config($config-or-theme);
@include mdc-helpers.mat-using-mdc-theme($config) {
+ $is-dark: map.get($config, is-dark);
+ $on-surface: mdc-theme-color.prop-value(on-surface);
+ $disabled-color: rgba($on-surface, if($is-dark, 0.5, 0.38));
+
.mat-mdc-icon-button {
- @include mdc-ripple-theme.states(
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
+ @include button-theme-private.ripple-theme-styles($config, false);
&.mat-primary {
- @include mdc-ripple-theme.states-base-color(primary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include mdc-icon-button.ink-color(primary, $query: mdc-helpers.$mat-theme-styles-query);
- @include button-theme-private.ripple-ink-color(primary);
+ @include mdc-icon-button-theme.theme((icon-color: mdc-theme-color.prop-value(primary)));
}
&.mat-accent {
- @include mdc-ripple-theme.states-base-color(secondary,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include mdc-icon-button.ink-color(secondary, $query: mdc-helpers.$mat-theme-styles-query);
- @include button-theme-private.ripple-ink-color(secondary);
+ @include mdc-icon-button-theme.theme((icon-color: mdc-theme-color.prop-value(secondary)));
}
&.mat-warn {
- @include mdc-ripple-theme.states-base-color(error,
- $query: mdc-helpers.$mat-theme-styles-query,
- $ripple-target: button-theme-private.$button-state-target);
- @include mdc-icon-button.ink-color(error, $query: mdc-helpers.$mat-theme-styles-query);
- @include button-theme-private.ripple-ink-color(error);
+ @include mdc-icon-button-theme.theme((icon-color: (mdc-theme-color.prop-value(error))));
}
@include button-theme-private.apply-disabled-style() {
- @include button-theme-private.apply-disabled-color();
+ @include mdc-icon-button-theme.theme((
+ icon-color: $disabled-color,
+ disabled-icon-color: $disabled-color,
+ ));
}
}
-
- @include mdc-icon-button.without-ripple($query: mdc-helpers.$mat-theme-styles-query);
}
}
diff --git a/src/material-experimental/mdc-button/button-base.ts b/src/material-experimental/mdc-button/button-base.ts
index a288955246f1..9d6806a1de71 100644
--- a/src/material-experimental/mdc-button/button-base.ts
+++ b/src/material-experimental/mdc-button/button-base.ts
@@ -85,12 +85,12 @@ export class MatButtonBase
extends _MatButtonMixin
implements CanDisable, CanColor, CanDisableRipple
{
- /** Whether the ripple is centered on the button. */
- _isRippleCentered = false;
-
/** Whether this button is a FAB. Used to apply the correct class on the ripple. */
_isFab = false;
+ /** Whether this button is an icon button. Used to apply the correct class on the ripple. */
+ _isIconButton = false;
+
/** Reference to the MatRipple instance of the button. */
@ViewChild(MatRipple) ripple: MatRipple;
diff --git a/src/material-experimental/mdc-button/button.html b/src/material-experimental/mdc-button/button.html
index acca8bffd4c9..d8644898e680 100644
--- a/src/material-experimental/mdc-button/button.html
+++ b/src/material-experimental/mdc-button/button.html
@@ -1,6 +1,8 @@
+ class="mat-mdc-button-persistent-ripple"
+ [class.mdc-button__ripple]="!_isFab && !_isIconButton"
+ [class.mdc-fab__ripple]="_isFab"
+ [class.mdc-icon-button__ripple]="_isIconButton">
@@ -18,7 +20,7 @@
diff --git a/src/material-experimental/mdc-button/button.scss b/src/material-experimental/mdc-button/button.scss
index 72c072e85aa0..04972576ee79 100644
--- a/src/material-experimental/mdc-button/button.scss
+++ b/src/material-experimental/mdc-button/button.scss
@@ -1,10 +1,55 @@
+@use 'sass:map';
@use '@material/button/button' as mdc-button;
+@use '@material/button/button-base' as mdc-button-base;
@use '@material/button/variables' as mdc-button-variables;
+@use '@material/button/button-text-theme' as mdc-button-text-theme;
+@use '@material/button/button-filled-theme' as mdc-button-filled-theme;
+@use '@material/button/button-protected-theme' as mdc-button-protected-theme;
+@use '@material/button/button-outlined-theme' as mdc-button-outlined-theme;
@use '../../material/core/style/private';
@use '../mdc-helpers/mdc-helpers';
@use 'button-base';
-@include mdc-button.without-ripple($query: mdc-helpers.$mat-base-styles-query);
+@include mdc-helpers.disable-fallback-declarations {
+ @include mdc-button.static-styles-without-ripple($query: mdc-helpers.$mat-base-styles-query);
+
+ // Keys to exclude from the MDC theme config, allowing us to drop styles we don't need.
+ $override-keys: button-base.mat-private-button-remove-ripple((
+ label-text-font: null,
+ label-text-size: null,
+ label-text-tracking: null,
+ label-text-transform: null,
+ label-text-weight: null,
+ with-icon-icon-size: null,
+ label-text-color: inherit,
+ ));
+
+ // Note that we don't include a feature query, because this mixins declare
+ // all the "slots" for CSS variables that will be defined in the theme.
+ .mat-mdc-button {
+ @include mdc-button-text-theme.theme-styles(
+ map.merge(mdc-button-text-theme.$light-theme, $override-keys));
+ }
+
+ .mat-mdc-unelevated-button {
+ @include mdc-button-filled-theme.theme-styles(
+ map.merge(map.merge(mdc-button-filled-theme.$light-theme, $override-keys), (
+ container-color: transparent,
+ )));
+ }
+
+ .mat-mdc-raised-button {
+ @include mdc-button-protected-theme.theme-styles(
+ map.merge(map.merge(mdc-button-protected-theme.$light-theme, $override-keys), (
+ container-color: transparent,
+ )));
+ }
+
+ .mat-mdc-outlined-button {
+ @include mdc-button-outlined-theme.theme-styles(
+ map.merge(mdc-button-outlined-theme.$light-theme, $override-keys));
+ }
+}
.mat-mdc-button,
.mat-mdc-unelevated-button,
@@ -24,10 +69,10 @@
// mixins will style the icons appropriately.
.mat-mdc-button {
.mat-icon {
- @include mdc-button.icon();
+ @include mdc-button-base.icon();
}
.mdc-button__label + .mat-icon {
- @include mdc-button.icon-trailing();
+ @include mdc-button-base.icon-trailing();
}
}
@@ -36,12 +81,12 @@
.mat-mdc-outlined-button {
// Icons inside contained buttons have different styles due to increased button padding
.mat-icon {
- @include mdc-button.icon();
- @include mdc-button.icon-contained();
+ @include mdc-button-base.icon();
+ @include mdc-button-base.icon-contained();
}
.mdc-button__label + .mat-icon {
- @include mdc-button.icon-contained-trailing();
+ @include mdc-button-base.icon-contained-trailing();
}
}
diff --git a/src/material-experimental/mdc-button/fab.scss b/src/material-experimental/mdc-button/fab.scss
index b93fe1dbcdf5..cba815029ef9 100644
--- a/src/material-experimental/mdc-button/fab.scss
+++ b/src/material-experimental/mdc-button/fab.scss
@@ -1,16 +1,49 @@
@use '@material/fab' as mdc-fab;
+@use '@material/elevation/elevation-theme' as mdc-elevation-theme;
@use '../../material/core/style/private';
@use '../mdc-helpers/mdc-helpers';
-@use 'button-base';
+@use './button-base';
-@include mdc-fab.without-ripple($query: mdc-helpers.$mat-base-styles-query);
+@include mdc-helpers.disable-fallback-declarations {
+ @include mdc-fab.without-ripple($query: mdc-helpers.$mat-base-styles-query);
+}
.mat-mdc-fab, .mat-mdc-mini-fab {
@include button-base.mat-private-button-interactive();
- @include button-base.mat-private-button-disabled();
@include button-base.mat-private-button-touch-target(true);
@include private.private-animation-noop();
+ @include mdc-helpers.disable-fallback-declarations {
+ // Theme configuration is copied over from MDC, because it isn't exported
+ @include mdc-fab.theme-styles(button-base.mat-private-button-remove-ripple((
+ container-color: transparent,
+ container-shape: mdc-fab.$shape-radius,
+ icon-color: inherit,
+ )));
+
+ // TODO(crisbeto): the elevation can be controlled using `container-elevation` in `theme-styles`
+ // however when it is passed in, MDC throws an error that `container-shadow-color` isn't
+ // passed in. When `container-shadow-color` is passed in, MDC throws another error, because
+ // the produced value isn't valid CSS. Eventually we should switch to it once it's fixed.
+ @include mdc-elevation-theme.elevation(6);
+
+ &:hover, &:focus {
+ @include mdc-elevation-theme.elevation(8);
+ }
+
+ &:active, &:focus:active {
+ @include mdc-elevation-theme.elevation(12);
+ }
+
+ @include button-base.mat-private-button-disabled {
+ @include mdc-elevation-theme.elevation(0);
+ }
+ }
+
+ // TODO(crisbeto): `theme-styles` doesn't allow for the color to be controlled. Define a custom
+ // variable for now so we have something to target.
+ color: var(--mat-mdc-fab-color, inherit);
+
// Prevent the button from shrinking since it's always supposed to be a circle.
flex-shrink: 0;
diff --git a/src/material-experimental/mdc-button/icon-button.scss b/src/material-experimental/mdc-button/icon-button.scss
index 379c22de9356..e94bffff67c7 100644
--- a/src/material-experimental/mdc-button/icon-button.scss
+++ b/src/material-experimental/mdc-button/icon-button.scss
@@ -1,15 +1,27 @@
+@use 'sass:map';
@use '@material/icon-button/icon-button' as mdc-icon-button;
+@use '@material/icon-button/icon-button-theme' as mdc-icon-button-theme;
@use '../../material/core/style/private';
@use '../mdc-helpers/mdc-helpers';
@use 'button-base';
-@include mdc-icon-button.without-ripple(
- $query: mdc-helpers.$mat-base-styles-query
-);
+@include mdc-helpers.disable-fallback-declarations {
+ @include mdc-icon-button.without-ripple($query: mdc-helpers.$mat-base-styles-query);
+}
.mat-mdc-icon-button {
- @include button-base.mat-private-button-interactive() {
- border-radius: 50%;
+ @include mdc-helpers.disable-fallback-declarations {
+ $theme-overrides: button-base.mat-private-button-remove-ripple((
+ icon-color: inherit,
+ // We don't change the color on focus/hover so exclude
+ // these styles both to reduce bundle size and specificity.
+ focus-icon-color: null,
+ hover-icon-color: null,
+ pressed-icon-color: null,
+ ));
+
+ @include mdc-icon-button-theme.theme-styles(
+ map.merge(mdc-icon-button-theme.$light-theme, $theme-overrides));
}
// Border radius is inherited by ripple to know its shape. Set to 50% so the ripple is round.
@@ -18,10 +30,20 @@
// Prevent the button from shrinking since it's always supposed to be a circle.
flex-shrink: 0;
- @include button-base.mat-private-button-disabled();
+ @include button-base.mat-private-button-disabled() {
+ // The color is already dimmed when the button is disabled. Restore the opacity both to
+ // help with the color contrast and to align with what we had before switching to the new API.
+ opacity: 1;
+ };
+
+ @include button-base.mat-private-button-interactive();
@include button-base.mat-private-button-touch-target(true);
@include private.private-animation-noop();
+ .mat-mdc-button-persistent-ripple {
+ border-radius: 50%;
+ }
+
// MDC adds some styles to icon buttons that conflict with some of our focus indicator styles
// and don't actually do anything. This undoes those conflicting styles.
&.mat-unthemed,
diff --git a/src/material-experimental/mdc-button/icon-button.ts b/src/material-experimental/mdc-button/icon-button.ts
index d9bf4e8aae6e..548875a196b8 100644
--- a/src/material-experimental/mdc-button/icon-button.ts
+++ b/src/material-experimental/mdc-button/icon-button.ts
@@ -43,8 +43,7 @@ import {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatIconButton extends MatButtonBase {
- // Set the ripple to be centered for icon buttons
- override _isRippleCentered = true;
+ override _isIconButton = true;
constructor(
elementRef: ElementRef,
@@ -72,8 +71,7 @@ export class MatIconButton extends MatButtonBase {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatIconAnchor extends MatAnchorBase {
- // Set the ripple to be centered for icon buttons
- override _isRippleCentered = true;
+ override _isIconButton = true;
constructor(
elementRef: ElementRef,