@use 'sass:meta'; @use 'sass:map'; @use '../core/tokens/m2-utils'; @use '../core/theming/theming'; @use '../core/theming/inspection'; @use '../core/style/sass-utils'; @use '../core/style/elevation'; // Tokens that can't be configured through Angular Material's current theming API, // but may be in a future version of the theming API. @function get-unthemable-tokens() { @return ( button-filled-container-shape: 4px, button-filled-horizontal-padding: 16px, button-filled-icon-offset: -4px, button-filled-icon-spacing: 8px, button-outlined-container-shape: 4px, button-outlined-horizontal-padding: 15px, // Normally it's 16px, but -1px for the outline. button-outlined-icon-offset: -4px, button-outlined-icon-spacing: 8px, button-outlined-keep-touch-target: false, button-outlined-outline-width: 1px, button-protected-container-elevation-shadow: elevation.get-box-shadow(2), button-protected-container-shape: 4px, button-protected-disabled-container-elevation-shadow: elevation.get-box-shadow(0), button-protected-focus-container-elevation-shadow: elevation.get-box-shadow(4), button-protected-horizontal-padding: 16px, button-protected-hover-container-elevation-shadow: elevation.get-box-shadow(4), button-protected-icon-offset: -4px, button-protected-icon-spacing: 8px, button-protected-pressed-container-elevation-shadow: elevation.get-box-shadow(8), button-text-container-shape: 4px, button-text-horizontal-padding: 8px, button-text-icon-offset: 0, button-text-icon-spacing: 8px, button-text-with-icon-horizontal-padding: 8px, button-tonal-container-shape: 4px, button-tonal-horizontal-padding: 16px, button-tonal-icon-offset: -4px, button-tonal-icon-spacing: 8px, ); } // Tokens that can be configured through Angular Material's color theming API. @function get-color-tokens($theme) { $is-dark: inspection.get-theme-type($theme) == dark; // Ideally we would derive all values directly from the theme, but it causes a lot of regressions // internally. For now we fall back to the old hardcoded behavior only for internal apps. $outline: if(m2-utils.$private-is-internal-build, rgba(if($is-dark, #fff, #000), 0.12), inspection.get-theme-color($theme, foreground, divider) ); @return ( button-filled-container-color: inspection.get-theme-color($theme, background, card), button-filled-disabled-container-color: inspection.get-theme-color($theme, foreground, disabled-button, 0.12), button-filled-disabled-label-text-color: inspection.get-theme-color($theme, foreground, disabled-button, if($is-dark, 0.5, 0.38)), button-filled-disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-filled-focus-state-layer-opacity: if($is-dark, 0.24, 0.12), button-filled-hover-state-layer-opacity: if($is-dark, 0.08, 0.04), button-filled-label-text-color: inspection.get-theme-color($theme, foreground, text, 1), button-filled-pressed-state-layer-opacity: if($is-dark, 0.24, 0.12), button-filled-ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1), button-filled-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-outlined-disabled-label-text-color: inspection.get-theme-color($theme, foreground, disabled-button, if($is-dark, 0.5, 0.38)), button-outlined-disabled-outline-color: $outline, button-outlined-disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-outlined-focus-state-layer-opacity: if($is-dark, 0.24, 0.12), button-outlined-hover-state-layer-opacity: if($is-dark, 0.08, 0.04), button-outlined-label-text-color: inspection.get-theme-color($theme, foreground, text, 1), button-outlined-outline-color: $outline, button-outlined-pressed-state-layer-opacity: if($is-dark, 0.24, 0.12), button-outlined-ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1), button-outlined-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-protected-container-color: inspection.get-theme-color($theme, background, card), button-protected-disabled-container-color: inspection.get-theme-color($theme, foreground, disabled-button, 0.12), button-protected-disabled-label-text-color: inspection.get-theme-color($theme, foreground, disabled-button, if($is-dark, 0.5, 0.38)), button-protected-disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-protected-focus-state-layer-opacity: if($is-dark, 0.24, 0.12), button-protected-hover-state-layer-opacity: if($is-dark, 0.08, 0.04), button-protected-label-text-color: inspection.get-theme-color($theme, foreground, text, 1), button-protected-pressed-state-layer-opacity: if($is-dark, 0.24, 0.12), button-protected-ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1), button-protected-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-text-disabled-label-text-color: inspection.get-theme-color($theme, foreground, disabled-button, if($is-dark, 0.5, 0.38)), button-text-disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-text-focus-state-layer-opacity: if($is-dark, 0.24, 0.12), button-text-hover-state-layer-opacity: if($is-dark, 0.08, 0.04), button-text-label-text-color: inspection.get-theme-color($theme, foreground, text, 1), button-text-pressed-state-layer-opacity: if($is-dark, 0.24, 0.12), button-text-ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1), button-text-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-tonal-container-color: inspection.get-theme-color($theme, background, card), button-tonal-disabled-container-color: inspection.get-theme-color($theme, foreground, disabled-button, 0.12), button-tonal-disabled-label-text-color: inspection.get-theme-color($theme, foreground, disabled-button, if($is-dark, 0.5, 0.38)), button-tonal-disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base), button-tonal-focus-state-layer-opacity: if($is-dark, 0.24, 0.12), button-tonal-hover-state-layer-opacity: if($is-dark, 0.08, 0.04), button-tonal-label-text-color: inspection.get-theme-color($theme, foreground, text, 1), button-tonal-pressed-state-layer-opacity: if($is-dark, 0.24, 0.12), button-tonal-ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1), button-tonal-state-layer-color: inspection.get-theme-color($theme, foreground, base), ); } // Generates the mapping for the properties that change based on the button palette color. @function private-get-color-palette-color-tokens($theme, $palette-name) { $color: inspection.get-theme-color($theme, $palette-name); $state-layer-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1); $ripple-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 0.1); $contrast-color: inspection.get-theme-color($theme, $palette-name, default-contrast); $container-color: inspection.get-theme-color($theme, $palette-name, default); $label-text-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1); $ripple-opacity: 0.1; // Ideally we would derive all values directly from the theme, but it causes a lot of regressions // internally. For now we fall back to the old hardcoded behavior only for internal apps. @if (m2-utils.$private-is-internal-build or meta.type-of($contrast-color) != 'color') { $is-dark: inspection.get-theme-type($theme) == dark; $container-color: inspection.get-theme-color($theme, $palette-name); $contrast-tone: m2-utils.contrast-tone($container-color, $is-dark); $color: if($contrast-tone == 'dark', #000, #fff); $state-layer-color: $color; $ripple-color: rgba($color, 0.1); $label-text-color: if($contrast-tone == 'dark', #000, #fff); } // outlined-outline-color: // TODO: we shouldn't have to set this since it's the same as the non-palette version, however // there are a bunch of tests internally that depend on it. We should remove this and clean // up the screenshots separately. @return ( button-filled-container-color: $container-color, button-filled-label-text-color: $label-text-color, button-filled-ripple-color: $ripple-color, button-filled-state-layer-color: $state-layer-color, button-outlined-label-text-color: inspection.get-theme-color($theme, $palette-name, default), button-outlined-outline-color: map.get(get-color-tokens($theme), button-outlined-outline-color), button-outlined-ripple-color: if( meta.type-of(inspection.get-theme-color($theme, $palette-name)) == color, rgba(inspection.get-theme-color($theme, $palette-name), $ripple-opacity), inspection.get-theme-color($theme, foreground, base, $ripple-opacity)), button-outlined-state-layer-color: inspection.get-theme-color($theme, $palette-name), button-protected-container-color: $container-color, button-protected-label-text-color: $label-text-color, button-protected-ripple-color: $ripple-color, button-protected-state-layer-color: $state-layer-color, button-text-label-text-color: inspection.get-theme-color($theme, $palette-name), button-text-ripple-color: if(meta.type-of(inspection.get-theme-color($theme, $palette-name)) == color, rgba(inspection.get-theme-color($theme, $palette-name), $ripple-opacity), inspection.get-theme-color($theme, foreground, base, $ripple-opacity)), button-text-state-layer-color: inspection.get-theme-color($theme, $palette-name), button-tonal-container-color: inspection.get-theme-color($theme, $palette-name, default), button-tonal-label-text-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1), button-tonal-ripple-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 0.1), button-tonal-state-layer-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1), ); } // Tokens that can be configured through Angular Material's typography theming API. @function get-typography-tokens($theme) { $font-family: inspection.get-theme-typography($theme, button, font-family); $font-size: inspection.get-theme-typography($theme, button, font-size); $font-weight: inspection.get-theme-typography($theme, button, font-weight); $letter-spacing: inspection.get-theme-typography($theme, button, letter-spacing); $text-transform: none; @return ( button-filled-label-text-font: $font-family, button-filled-label-text-size: $font-size, button-filled-label-text-tracking: $letter-spacing, button-filled-label-text-transform: none, button-filled-label-text-weight: $font-weight, button-outlined-label-text-font: $font-family, button-outlined-label-text-size: $font-size, button-outlined-label-text-tracking: $letter-spacing, button-outlined-label-text-transform: none, button-outlined-label-text-weight: $font-weight, button-protected-label-text-font: $font-family, button-protected-label-text-size: $font-size, button-protected-label-text-tracking: $letter-spacing, button-protected-label-text-transform: none, button-protected-label-text-weight: $font-weight, button-text-label-text-font: $font-family, button-text-label-text-size: $font-size, button-text-label-text-tracking: $letter-spacing, button-text-label-text-transform: none, button-text-label-text-weight: $font-weight, button-tonal-label-text-font: $font-family, button-tonal-label-text-size: $font-size, button-tonal-label-text-tracking: $letter-spacing, button-tonal-label-text-transform: none, button-tonal-label-text-weight: $font-weight, ); } // Tokens that can be configured through Angular Material's density theming API. @function get-density-tokens($theme) { $density-scale: theming.clamp-density(inspection.get-theme-density($theme), -3); $scale: theming.clamp-density(inspection.get-theme-density($theme), -3); $sizes: ( 0: 36px, -1: 32px, -2: 28px, -3: 24px, ); $height: map.get($sizes, $scale); $touch-target-display: if($scale < -1, none, block); @return ( button-filled-container-height: $height, button-filled-touch-target-display: $touch-target-display, button-outlined-container-height: $height, button-outlined-touch-target-display: $touch-target-display, button-protected-container-height: $height, button-protected-touch-target-display: $touch-target-display, button-text-container-height: $height, button-text-touch-target-display: $touch-target-display, button-tonal-container-height: $height, button-tonal-touch-target-display: $touch-target-display, ); } // Combines the tokens generated by the above functions into a single map with placeholder values. // This is used to create token slots. @function get-token-slots() { @return sass-utils.deep-merge-all( get-unthemable-tokens(), get-color-tokens(m2-utils.$placeholder-color-config), get-typography-tokens(m2-utils.$placeholder-typography-config), get-density-tokens(m2-utils.$placeholder-density-config) ); }