Skip to content

Commit

Permalink
fix(material/chips): Tokenize the selected state (#28498)
Browse files Browse the repository at this point in the history
* fix(material/chips): Tokenize the selected state

This will give us the flexibility we need to implement M3 chips

* more fixes

* trailing icon state

* fix test

* fix some disabled states

* Undo trailing icon changes

* only apply disabled checkmark opacity when selected
  • Loading branch information
mmalerba authored Feb 5, 2024
1 parent fca43aa commit 32f86e4
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 48 deletions.
14 changes: 7 additions & 7 deletions src/dev-app/chips/chips-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ <h4>With avatar, icons, and color</h4>
<mat-icon matChipAvatar>home</mat-icon>
Home
<button matChipRemove aria-label="Remove chip">
<mat-icon>cancel</mat-icon>
<mat-icon>close</mat-icon>
</button>
</mat-chip>

<mat-chip highlighted="true" color="accent">
<mat-chip-avatar>P</mat-chip-avatar>
Portel
<button matChipRemove aria-label="Remove chip">
<mat-icon>cancel</mat-icon>
<mat-icon>close</mat-icon>
</button>
</mat-chip>

Expand All @@ -59,7 +59,7 @@ <h4>With avatar, icons, and color</h4>
<mat-chip>
Koby
<button matChipRemove aria-label="Remove chip">
<mat-icon>cancel</mat-icon>
<mat-icon>close</mat-icon>
</button>
</mat-chip>

Expand All @@ -76,7 +76,7 @@ <h4>With avatar, icons, and color</h4>
<img src="https://material.angular.io/assets/img/examples/shiba2.jpg" matChipAvatar>
Husi
<button matChipRemove>
<mat-icon>cancel</mat-icon>
<mat-icon>close</mat-icon>
</button>
</mat-chip>

Expand All @@ -100,7 +100,7 @@ <h4>With Events</h4>
(destroyed)="displayMessage('chip destroyed')" (removed)="toggleVisible()">
With Events
<button matChipRemove aria-label="Remove chip">
<mat-icon>cancel</mat-icon>
<mat-icon>close</mat-icon>
</button>
</mat-chip>
}
Expand Down Expand Up @@ -180,7 +180,7 @@ <h4>Input is last child of chip grid</h4>
(edited)="edit(person, $event)">
{{person.name}}
<button matChipRemove aria-label="Remove contributor">
<mat-icon>cancel</mat-icon>
<mat-icon>close</mat-icon>
</button>
</mat-chip-row>
}
Expand All @@ -201,7 +201,7 @@ <h4>Input is next sibling child of chip grid</h4>
<mat-chip-row (removed)="remove(person)">
{{person.name}}
<button matChipRemove aria-label="Remove contributor">
<mat-icon>cancel</mat-icon>
<mat-icon>close</mat-icon>
</button>
</mat-chip-row>
}
Expand Down
74 changes: 65 additions & 9 deletions src/material-experimental/theming/_custom-tokens.scss
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,49 @@
);
}

/// Generates custom tokens for the mat-chip.
/// @param {Map} $systems The MDC system tokens
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
/// @return {Map} A set of custom tokens for the mat-chip
@function chip($systems, $exclude-hardcoded) {
@return ((
disabled-container-opacity: _hardcode(1, $exclude-hardcoded),
selected-trailing-icon-color: map.get($systems, md-sys-color, on-secondary-container),
selected-disabled-trailing-icon-color: map.get($systems, md-sys-color, on-surface),
trailing-action-state-layer-color: map.get($systems, md-sys-color, on-surface-variant),
selected-trailing-action-state-layer-color:
map.get($systems, md-sys-color, on-secondary-container),
trailing-action-hover-state-layer-opacity:
map.get($systems, md-sys-state, hover-state-layer-opacity),
trailing-action-focus-state-layer-opacity:
map.get($systems, md-sys-state, focus-state-layer-opacity),
), (
primary: (
selected-trailing-icon-color: map.get($systems, md-sys-color, on-primary-container),
selected-trailing-action-state-layer-color:
map.get($systems, md-sys-color, on-primary-container),
),
secondary: (), // Default, no overrides needed.
tertiary: (
selected-trailing-icon-color: map.get($systems, md-sys-color, on-tertiary-container),
selected-trailing-action-state-layer-color:
map.get($systems, md-sys-color, on-tertiary-container),
),
error: (
selected-trailing-icon-color: map.get($systems, md-sys-color, on-error-container),
selected-trailing-action-state-layer-color:
map.get($systems, md-sys-color, on-error-container),
),
));
}

/// Generates custom tokens for the mdc-chip. (MDC has a chip component, but they
/// seem to have made up the tokens rather than using ones generated from the token database,
/// therefore we need a custom token function for it).
/// @param {Map} $systems The MDC system tokens
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
/// @return {Map} A set of custom tokens for the mdc-chip
@function chip($systems, $exclude-hardcoded) {
@function mdc-chip($systems, $exclude-hardcoded) {
@return (mat.private-merge-all(
_generate-typography-tokens($systems, label-text, label-large),
(
Expand All @@ -212,16 +248,10 @@
),
with-icon-icon-size: _hardcode(18px, $exclude-hardcoded),
with-icon-icon-color: map.get($systems, md-sys-color, on-surface-variant),
with-icon-disabled-icon-color: mat.private-safe-color-change(
map.get($systems, md-sys-color, on-surface),
$alpha: 0.38,
),
with-icon-disabled-icon-color: map.get($systems, md-sys-color, on-surface),
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-secondary-container),
with-trailing-icon-trailing-icon-color: map.get($systems, md-sys-color, on-surface-variant),
with-trailing-icon-disabled-trailing-icon-color: mat.private-safe-color-change(
map.get($systems, md-sys-color, on-surface),
$alpha: 0.38,
),
with-trailing-icon-disabled-trailing-icon-color: map.get($systems, md-sys-color, on-surface),
focus-state-layer-opacity: map.get($systems, md-sys-state, focus-state-layer-opacity),
focus-state-layer-color: map.get($systems, md-sys-color, on-surface-variant),
outline-width: _hardcode(1px, $exclude-hardcoded),
Expand All @@ -234,18 +264,44 @@
hover-state-layer-color: map.get($systems, md-sys-color, on-surface-variant),
hover-state-layer-opacity: map.get($systems, md-sys-state, hover-state-layer-opacity),
with-avatar-disabled-avatar-opacity: _hardcode(0.38, $exclude-hardcoded),
elevated-selected-container-color: map.get($systems, md-sys-color, secondary-container),
flat-selected-outline-width: _hardcode(0, $exclude-hardcoded),
selected-label-text-color: map.get($systems, md-sys-color, on-secondary-container),
flat-disabled-selected-container-color: mat.private-safe-color-change(
map.get($systems, md-sys-color, on-surface),
$alpha: 0.12,
),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-secondary-container),
selected-hover-state-layer-opacity:
map.get($systems, md-sys-state, hover-state-layer-opacity),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-secondary-container),
selected-focus-state-layer-opacity:
map.get($systems, md-sys-state, focus-state-layer-opacity),
with-icon-disabled-icon-opacity: _hardcode(0.38, $exclude-hardcoded),
),
), (
// Color variants:
primary: (
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-primary-container),
elevated-selected-container-color: map.get($systems, md-sys-color, primary-container),
selected-label-text-color: map.get($systems, md-sys-color, on-primary-container),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-primary-container),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-primary-container),
),
secondary: (), // Default, no overrides needed.
tertiary: (
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-tertiary-container),
elevated-selected-container-color: map.get($systems, md-sys-color, tertiary-container),
selected-label-text-color: map.get($systems, md-sys-color, on-tertiary-container),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-tertiary-container),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-tertiary-container),
),
error: (
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-error-container),
elevated-selected-container-color: map.get($systems, md-sys-color, error-container),
selected-label-text-color: map.get($systems, md-sys-color, on-error-container),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-error-container),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-error-container),
)
));
}
Expand Down
7 changes: 6 additions & 1 deletion src/material-experimental/theming/_m3-tokens.scss
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@
),
_namespace-tokens(
(mdc, chip),
custom-tokens.chip($systems, $exclude-hardcoded),
custom-tokens.mdc-chip($systems, $exclude-hardcoded),
$token-slots
),
_namespace-tokens(
Expand Down Expand Up @@ -753,6 +753,11 @@
custom-tokens.card($systems, $exclude-hardcoded),
$token-slots
),
_namespace-tokens(
(mat, chip),
custom-tokens.chip($systems, $exclude-hardcoded),
$token-slots
),
_namespace-tokens(
(mat, datepicker),
custom-tokens.datepicker($systems, $exclude-hardcoded),
Expand Down
8 changes: 7 additions & 1 deletion src/material/chips/_chips-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,22 @@
&.mat-primary {
$primary-color-tokens: tokens-mdc-chip.get-color-tokens($theme, primary);
@include mdc-chip-theme.theme($primary-color-tokens);
@include token-utils.create-token-values(
tokens-mat-chip.$prefix, tokens-mat-chip.get-color-tokens($theme, primary));
}

&.mat-accent {
$accent-color-tokens: tokens-mdc-chip.get-color-tokens($theme, accent);
@include mdc-chip-theme.theme($accent-color-tokens);
@include token-utils.create-token-values(
tokens-mat-chip.$prefix, tokens-mat-chip.get-color-tokens($theme, accent));
}

&.mat-warn {
$warn-color-tokens: tokens-mdc-chip.get-color-tokens($theme, warn);
@include mdc-chip-theme.theme($warn-color-tokens);
@include token-utils.create-token-values(
tokens-mat-chip.$prefix, tokens-mat-chip.get-color-tokens($theme, warn));
}
}
}
Expand Down Expand Up @@ -121,7 +127,7 @@

@mixin _theme-from-tokens($tokens, $options...) {
$mdc-chip-tokens: token-utils.get-tokens-for($tokens, tokens-mdc-chip.$prefix, $options...);
$mat-chip-tokens: token-utils.get-tokens-for($tokens, tokens-mat-chip.$prefix);
$mat-chip-tokens: token-utils.get-tokens-for($tokens, tokens-mat-chip.$prefix, $options...);
@include mdc-chip-theme.theme($mdc-chip-tokens);
@include token-utils.create-token-values(tokens-mat-chip.$prefix, $mat-chip-tokens);
}
74 changes: 65 additions & 9 deletions src/material/chips/chip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,76 @@
.mat-mdc-chip-focus-overlay {
@include token-utils.create-token-slot(background, focus-state-layer-color);

.mat-mdc-chip-selected & {
@include token-utils.create-token-slot(background, selected-focus-state-layer-color);
}

.mat-mdc-chip:hover & {
@include token-utils.create-token-slot(background, hover-state-layer-color);
@include token-utils.create-token-slot(opacity, hover-state-layer-opacity);
}

.mat-mdc-chip-selected:hover & {
@include token-utils.create-token-slot(background, selected-hover-state-layer-color);
@include token-utils.create-token-slot(opacity, selected-hover-state-layer-opacity);
}

.mat-mdc-chip.cdk-focused & {
@include token-utils.create-token-slot(background, focus-state-layer-color);
@include token-utils.create-token-slot(opacity, focus-state-layer-opacity);
}

.mat-mdc-chip-selected.cdk-focused & {
@include token-utils.create-token-slot(background, selected-focus-state-layer-color);
@include token-utils.create-token-slot(opacity, selected-focus-state-layer-opacity);
}
}

.mdc-evolution-chip--disabled:not(.mdc-evolution-chip--selected) .mat-mdc-chip-avatar {
@include token-utils.create-token-slot(opacity, with-avatar-disabled-avatar-opacity);
}

.mdc-evolution-chip--disabled.mdc-evolution-chip--selected .mdc-evolution-chip__checkmark {
@include token-utils.create-token-slot(opacity, with-icon-disabled-icon-opacity);
}
}

@include token-utils.use-tokens(tokens-mat-chip.$prefix, $mat-chip-token-slots) {
// Historically, MDC did not support disabled chips, so we needed our own disabled styles.
// Now that MDC supports disabled styles, we should switch to using theirs.
.mat-mdc-standard-chip.mdc-evolution-chip--disabled {
@include token-utils.create-token-slot(opacity, disabled-container-opacity);
.mat-mdc-standard-chip {
&.mdc-evolution-chip--disabled {
@include token-utils.create-token-slot(opacity, disabled-container-opacity);
}

&.mdc-evolution-chip--selected {
.mdc-evolution-chip__icon--trailing {
@include token-utils.create-token-slot(color, selected-trailing-icon-color);
}

&.mdc-evolution-chip--disabled .mdc-evolution-chip__icon--trailing {
@include token-utils.create-token-slot(color, selected-disabled-trailing-icon-color);
}
}
}

.mat-mdc-chip-remove {
&::after {
@include token-utils.create-token-slot(background, trailing-action-state-layer-color);
}

&:hover::after {
@include token-utils.create-token-slot(opacity, trailing-action-hover-state-layer-opacity);
}

&:focus::after {
@include token-utils.create-token-slot(opacity, trailing-action-focus-state-layer-opacity);
}
}

.mat-mdc-chip-selected .mat-mdc-chip-remove::after {
@include token-utils.create-token-slot(
background, selected-trailing-action-state-layer-color);
}
}
}
Expand Down Expand Up @@ -79,13 +128,6 @@
mdc-chip-theme.$trailing-action-leading-padding,
mdc-chip-theme.$trailing-action-trailing-padding
);

// MDC has some code looking for a `with-icon-selected-disabled-icon-color` token for this
// color, but the token isn't defined in the theme map so the validation throws an error.
// We don't change the color anyway so we can point it to the enable color instead.
&.mdc-evolution-chip--disabled .mdc-evolution-chip__checkmark {
color: var(--mdc-chip-with-icon-selected-icon-color, currentColor);
}
}

.mdc-evolution-chip--with-avatar {
Expand Down Expand Up @@ -283,6 +325,20 @@
right: 8px;
}

// Used as a state overlay.
&::after {
$offset: 2px;
content: '';
display: block;
opacity: 0;
position: absolute;
top: 0 - $offset;
bottom: 0 - $offset;
left: 8px - $offset;
right: 8px - $offset;
border-radius: 50%;
}

.mat-icon {
width: inherit;
height: inherit;
Expand Down
2 changes: 2 additions & 0 deletions src/material/core/tokens/m2/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@use './mat/dialog' as tokens-mat-dialog;
@use './mat/bottom-sheet' as tokens-mat-bottom-sheet;
@use './mat/card' as tokens-mat-card;
@use './mat/chip' as tokens-mat-chip;
@use './mat/datepicker' as tokens-mat-datepicker;
@use './mat/divider' as tokens-mat-divider;
@use './mat/expansion' as tokens-mat-expansion;
Expand Down Expand Up @@ -119,6 +120,7 @@
_get-tokens-for-module($theme, tokens-mat-bottom-sheet),
_get-tokens-for-module($theme, tokens-mat-button-toggle),
_get-tokens-for-module($theme, tokens-mat-card),
_get-tokens-for-module($theme, tokens-mat-chip),
_get-tokens-for-module($theme, tokens-mat-datepicker),
_get-tokens-for-module($theme, tokens-mat-dialog),
_get-tokens-for-module($theme, tokens-mat-divider),
Expand Down
Loading

0 comments on commit 32f86e4

Please sign in to comment.