Skip to content

Commit 13b8ad1

Browse files
committed
refactor(material/button): handle disabled state of icon buttons through tokens
* Fixes that icon buttons weren't using the right token for disabled state. * Fixes that the specificity of the icon button disabled styles was really high. * Moves the logic for generating the palette tokens into the icon button tokens file. * Fixes one place where we were referencing a token directly instead of using the API to generate the name.
1 parent e2d9cfa commit 13b8ad1

File tree

4 files changed

+65
-48
lines changed

4 files changed

+65
-48
lines changed

src/dev-app/button/button-demo.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,25 @@ <h4 class="demo-section-header"> Icon Buttons [mat-icon-button]</h4>
150150
</button>
151151
</section>
152152

153+
<h4 class="demo-section-header"> Icon Button Anchors [mat-icon-button]</h4>
154+
<section>
155+
<a href="#" mat-icon-button>
156+
<mat-icon>cached</mat-icon>
157+
</a>
158+
<a href="#" mat-icon-button color="primary">
159+
<mat-icon>cached</mat-icon>
160+
</a>
161+
<a href="#" mat-icon-button color="accent">
162+
<mat-icon>backup</mat-icon>
163+
</a>
164+
<a href="#" mat-icon-button color="warn">
165+
<mat-icon>trending_up</mat-icon>
166+
</a>
167+
<a href="#" mat-icon-button disabled>
168+
<mat-icon>visibility</mat-icon>
169+
</a>
170+
</section>
171+
153172
<h4 class="demo-section-header">Fab Buttons [mat-fab]</h4>
154173
<section>
155174
<button mat-fab>

src/material/button/_icon-button-theme.scss

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
@use 'sass:math';
22
@use '@material/density/functions' as mdc-density-functions;
33
@use '@material/icon-button/icon-button-theme' as mdc-icon-button-theme;
4-
@use '@material/theme/theme-color' as mdc-theme-color;
54
@use '../core/style/sass-utils';
65
@use '../core/tokens/m2/mdc/icon-button' as tokens-mdc-icon-button;
76

@@ -11,19 +10,12 @@
1110

1211
$_icon-size: 24px;
1312

13+
// TODO(crisbeto): move these into tokens
1414
@mixin _ripple-color($color) {
1515
--mat-mdc-button-persistent-ripple-color: #{$color};
1616
--mat-mdc-button-ripple-color: #{rgba($color, 0.1)};
1717
}
1818

19-
@function _variable-safe-contrast-tone($value, $is-dark) {
20-
@if ($value == 'dark' or $value == 'light' or type-of($value) == 'color') {
21-
@return mdc-theme-color.contrast-tone($value);
22-
}
23-
24-
@return if($is-dark, 'light', 'dark');
25-
}
26-
2719
@mixin base($theme) {
2820
// Add default values for tokens not related to color, typography, or density.
2921
@include sass-utils.current-selector-or-root() {
@@ -33,45 +25,34 @@ $_icon-size: 24px;
3325

3426
@mixin color($theme) {
3527
$color-tokens: tokens-mdc-icon-button.get-color-tokens($theme);
36-
$surface: inspection.get-theme-color($theme, background, card);
3728
$is-dark: inspection.get-theme-type($theme) == dark;
38-
$on-surface: if(_variable-safe-contrast-tone($surface, $is-dark) == 'dark', #000, #fff);
3929

4030
.mat-mdc-icon-button {
4131
@include button-theme-private.ripple-theme-styles($theme, false);
4232
@include mdc-icon-button-theme.theme($color-tokens);
43-
@include _ripple-color($on-surface);
33+
@include _ripple-color(if($is-dark, #fff, #000));
4434

4535
&.mat-primary {
46-
$color: inspection.get-theme-color($theme, primary);
47-
@include mdc-icon-button-theme.theme((icon-color: $color));
48-
@include _ripple-color($color);
36+
@include _ripple-color(inspection.get-theme-color($theme, primary));
37+
@include mdc-icon-button-theme.theme(
38+
tokens-mdc-icon-button.private-get-color-palette-color-tokens($theme, primary));
4939
}
5040

5141
&.mat-accent {
52-
$color: inspection.get-theme-color($theme, accent);
53-
@include mdc-icon-button-theme.theme((icon-color: $color));
54-
@include _ripple-color($color);
42+
@include _ripple-color(inspection.get-theme-color($theme, accent));
43+
@include mdc-icon-button-theme.theme(
44+
tokens-mdc-icon-button.private-get-color-palette-color-tokens($theme, accent));
5545
}
5646

5747
&.mat-warn {
58-
$color: inspection.get-theme-color($theme, warn);
59-
@include mdc-icon-button-theme.theme((icon-color: $color));
60-
@include _ripple-color($color);
61-
}
62-
63-
@include button-theme-private.apply-disabled-style() {
64-
$disabled-color: rgba($on-surface, if($is-dark, 0.5, 0.38));
65-
@include mdc-icon-button-theme.theme((
66-
icon-color: $disabled-color,
67-
disabled-icon-color: $disabled-color,
68-
));
48+
@include _ripple-color(inspection.get-theme-color($theme, warn));
49+
@include mdc-icon-button-theme.theme(
50+
tokens-mdc-icon-button.private-get-color-palette-color-tokens($theme, warn));
6951
}
7052
}
7153
}
7254

73-
@mixin typography($theme) {
74-
}
55+
@mixin typography($theme) {}
7556

7657
@mixin density($theme) {
7758
$density-scale: inspection.get-theme-density($theme);

src/material/button/icon-button.scss

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
@use '@material/icon-button/icon-button-theme' as mdc-icon-button-theme;
33
@use '@material/theme/custom-properties' as mdc-custom-properties;
44

5-
@use '../core/tokens/m2/mdc/icon-button' as m2-mdc-icon-button;
5+
@use '../core/tokens/m2/mdc/icon-button' as tokens-mdc-icon-button;
66

77
@use './button-base';
88
@use '../core/style/private';
9+
@use '../core/tokens/token-utils';
910

1011
// The slots for tokens that will be configured in the theme can be emitted with no fallback.
1112
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
12-
$token-slots: m2-mdc-icon-button.get-token-slots();
13+
$token-slots: tokens-mdc-icon-button.get-token-slots();
1314

1415
// Add the MDC component static styles.
1516
@include mdc-icon-button.static-styles();
@@ -25,10 +26,6 @@
2526
// TODO: Determine how to enforce theming exists, otherwise padding will be unset.
2627
padding: 12px;
2728

28-
// Icon size used to be placed on the host element. Now, in `theme-styles` it is placed on
29-
// the unused `.mdc-button__icon` class. Explicitly set the font-size here.
30-
font-size: var(--mdc-icon-button-icon-size);
31-
3229
// Border radius is inherited by ripple to know its shape. Set to 50% so the ripple is round.
3330
border-radius: 50%;
3431

@@ -42,11 +39,18 @@
4239
vertical-align: baseline;
4340
}
4441

45-
@include button-base.mat-private-button-disabled() {
46-
// The color is already dimmed when the button is disabled. Restore the opacity both to
47-
// help with the color contrast and to align with what we had before switching to the new API.
48-
opacity: 1;
49-
};
42+
@include token-utils.use-tokens(
43+
tokens-mdc-icon-button.$prefix, tokens-mdc-icon-button.get-token-slots()) {
44+
// Icon size used to be placed on the host element. Now, in `theme-styles` it is placed on
45+
// the unused `.mdc-button__icon` class. Explicitly set the font-size here.
46+
@include token-utils.create-token-slot(font-size, icon-size);
47+
48+
@include button-base.mat-private-button-disabled {
49+
// MDC's disabled styles target the `:disabled` selector which doesn't work on links.
50+
// We re-apply the disabled icon color here since we support Material buttons on links too.
51+
@include token-utils.create-token-slot(color, disabled-icon-color);
52+
};
53+
}
5054

5155
@include button-base.mat-private-button-interactive();
5256
@include button-base.mat-private-button-touch-target(true);

src/material/core/tokens/m2/mdc/_icon-button.scss

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
@use 'sass:map';
12
@use '../../../style/sass-utils';
3+
@use '../../../theming/inspection';
24
@use '../../token-utils';
35

46
// The prefix used to generate the fully qualified name for tokens in this file.
@@ -20,12 +22,7 @@ $prefix: (mdc, icon-button);
2022
state-layer-size: 48px,
2123
// MDC's icon size applied to svg and img elements inside the component
2224
icon-size: 24px,
23-
// Only applies to :disabled icons, but Angular Components uses [disabled] since :disabled
24-
// wouldn't work on <a> tags.
25-
disabled-icon-color: black,
26-
// Angular version applies an opacity 1 with a color change, and this only applies with
27-
// :disabled anyways.
28-
disabled-icon-opacity: 0.38,
25+
2926
// =============================================================================================
3027
// = TOKENS NOT USED IN ANGULAR MATERIAL =
3128
// =============================================================================================
@@ -41,13 +38,29 @@ $prefix: (mdc, icon-button);
4138
pressed-state-layer-opacity: null,
4239
focus-ring-color: null,
4340
focus-ring-offset: null,
41+
42+
// We use a color with an opacity to show the disabled state,
43+
// instead of applying it to the entire button.
44+
disabled-icon-opacity: null,
4445
);
4546
}
4647

4748
// Tokens that can be configured through Angular Material's color theming API.
4849
@function get-color-tokens($theme) {
50+
$is-dark: inspection.get-theme-type($theme) == dark;
51+
4952
@return (
5053
icon-color: inherit,
54+
disabled-icon-color: if($is-dark, rgba(#fff, 0.5), rgba(#000, 0.38)),
55+
);
56+
}
57+
58+
// Generates the mapping for the properties that change based on the button palette color.
59+
@function private-get-color-palette-color-tokens($theme, $palette-name) {
60+
$palette: map.get($theme, $palette-name);
61+
62+
@return (
63+
icon-color: inspection.get-theme-color($theme, $palette-name)
5164
);
5265
}
5366

0 commit comments

Comments
 (0)