From e05795dde0ca56be3398f34cb834df007f18da1a Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 16 Jan 2024 09:38:43 +0100 Subject: [PATCH] fix(material/button): calculate icon button padding based on tokens Uses token values to calculate the padding for icon buttons, instead of doing it statically. --- src/material/button/icon-button.scss | 22 ++++++++++++++----- .../core/tokens/m2/mdc/_icon-button.scss | 22 +++++++++++++------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/material/button/icon-button.scss b/src/material/button/icon-button.scss index 03c48380f098..c16af087f0a7 100644 --- a/src/material/button/icon-button.scss +++ b/src/material/button/icon-button.scss @@ -1,3 +1,4 @@ +@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/theme/custom-properties' as mdc-custom-properties; @@ -18,15 +19,14 @@ .mat-mdc-icon-button { // Add the official slots for the MDC component. - @include mdc-icon-button-theme.theme-styles($token-slots); + @include mdc-icon-button-theme.theme-styles(map.merge($token-slots, ( + // Exclude the state layer size since we'll re-emit it below with a default value. + state-layer-size: null, + ))); } } .mat-mdc-icon-button { - // Not all applications import the theming which would apply a default padding. - // TODO: Determine how to enforce theming exists, otherwise padding will be unset. - padding: 12px; - // Border radius is inherited by ripple to know its shape. Set to 50% so the ripple is round. border-radius: 50%; @@ -42,6 +42,18 @@ @include token-utils.use-tokens( tokens-mdc-icon-button.$prefix, tokens-mdc-icon-button.get-token-slots()) { + $button-size: var(#{token-utils.get-token-variable(state-layer-size)}, 48px); + $icon-size: var(#{token-utils.get-token-variable(icon-size)}, 24px); + + // We emit these tokens ourselves here so we can provide a default value. + // This avoids a lot internal breakages in apps that didn't include the icon button theme. + width: $button-size; + height: $button-size; + + // Note: this is wrapped in an interpolation, because of an internal lint rule that bans + // interpolations in `calc`, even though this is the only way to achieve what we're looking for. + padding: #{calc(#{calc(#{$button-size} - #{$icon-size})} / 2)}; + // Icon size used to be placed on the host element. Now, in `theme-styles` it is placed on // the unused `.mdc-button__icon` class. Explicitly set the font-size here. @include token-utils.create-token-slot(font-size, icon-size); diff --git a/src/material/core/tokens/m2/mdc/_icon-button.scss b/src/material/core/tokens/m2/mdc/_icon-button.scss index 1fbc989bf3e2..2846f0c477c3 100644 --- a/src/material/core/tokens/m2/mdc/_icon-button.scss +++ b/src/material/core/tokens/m2/mdc/_icon-button.scss @@ -1,4 +1,6 @@ +@use 'sass:map'; @use '../../../style/sass-utils'; +@use '../../../theming/theming'; @use '../../../theming/inspection'; @use '../../token-utils'; @@ -13,12 +15,6 @@ $prefix: (mdc, icon-button); // our CSS. @function get-unthemable-tokens() { @return ( - // ============================================================================================= - // = TOKENS THAT SHOULD NOT BE CUSTOMIZABLE = - // ============================================================================================= - // Determines the size of the icon. Name is inaccurate - applies to the whole component, - // not just the state layer. - state-layer-size: 48px, // MDC's icon size applied to svg and img elements inside the component icon-size: 24px, @@ -68,7 +64,19 @@ $prefix: (mdc, icon-button); // Tokens that can be configured through Angular Material's density theming API. @function get-density-tokens($theme) { - @return (); + $scale: theming.clamp-density(inspection.get-theme-density($theme), -5); + + @return ( + // The diameter of the checkbox's ripple. + state-layer-size: map.get(( + 0: 48px, + -1: 44px, + -2: 40px, + -3: 36px, + -4: 32px, + -5: 28px, + ), $scale) + ); } // Combines the tokens generated by the above functions into a single map with placeholder values.