Skip to content

refactor(material-experimental/mdc-button): switch to new theming API #24201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions src/material-experimental/mdc-button/_button-base.scss
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -59,6 +59,7 @@
&[disabled] {
cursor: default;
pointer-events: none;
@content;
}
}

Expand All @@ -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,
));
}
63 changes: 35 additions & 28 deletions src/material-experimental/mdc-button/_button-theme-private.scss
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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') {
Expand Down
Loading