From 09a2cc17e957a2c91aa66002d4aeae7b265fb777 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Wed, 8 Nov 2023 23:58:32 +0000 Subject: [PATCH] feat(material-experimental/theming): add M3 tabs support --- src/dev-app/theme-m3.scss | 3 + .../theming/_custom-tokens.scss | 58 ++++- .../theming/_m3-density.scss | 58 ++--- .../theming/_m3-tokens.scss | 198 ++++++++++-------- src/material/tabs/_tabs-theme.scss | 138 +++++++----- 5 files changed, 277 insertions(+), 178 deletions(-) diff --git a/src/dev-app/theme-m3.scss b/src/dev-app/theme-m3.scss index b0405824e822..c274b8cfbd07 100644 --- a/src/dev-app/theme-m3.scss +++ b/src/dev-app/theme-m3.scss @@ -44,6 +44,7 @@ html { @include mat.slide-toggle-theme($light-theme); @include mat.slider-theme($light-theme); @include mat.snack-bar-theme($light-theme); + @include mat.tabs-theme($light-theme); @include mat.toolbar-theme($light-theme); @include mat.tooltip-theme($light-theme); @include mat.tree-theme($light-theme); @@ -63,6 +64,7 @@ html { @include mat.slide-toggle-color($dark-theme); @include mat.slider-color($dark-theme); @include mat.snack-bar-color($dark-theme); + @include mat.tabs-color($dark-theme); @include mat.toolbar-color($dark-theme); @include mat.tooltip-color($dark-theme); @include mat.tree-color($dark-theme); @@ -81,6 +83,7 @@ html { @include mat.slide-toggle-density($scale-theme); @include mat.slider-density($scale-theme); @include mat.snack-bar-density($scale-theme); + @include mat.tabs-density($scale-theme); @include mat.toolbar-density($scale-theme); @include mat.tooltip-density($scale-theme); @include mat.tree-density($scale-theme); diff --git a/src/material-experimental/theming/_custom-tokens.scss b/src/material-experimental/theming/_custom-tokens.scss index 5e4a317324d7..b407c541e004 100644 --- a/src/material-experimental/theming/_custom-tokens.scss +++ b/src/material-experimental/theming/_custom-tokens.scss @@ -22,11 +22,11 @@ /// @return {Map} A set of custom tokens for the mat-card @function card($systems, $exclude-hardcoded) { @return mat.private-merge-all( - _generate-typography-tokens($systems, title-text, title-large), - _generate-typography-tokens($systems, subtitle-text, title-medium), - ( - subtitle-text-color: map.get($systems, md-sys-color, on-surface) - ) + _generate-typography-tokens($systems, title-text, title-large), + _generate-typography-tokens($systems, subtitle-text, title-medium), + ( + subtitle-text-color: map.get($systems, md-sys-color, on-surface) + ) ); } @@ -36,11 +36,11 @@ /// @return {Map} A set of custom tokens for the mat-toolbar @function toolbar($systems, $exclude-hardcoded) { @return mat.private-merge-all( - _generate-typography-tokens($systems, title-text, title-large), - ( - container-background-color: map.get($systems, md-sys-color, surface), - container-text-color: map.get($systems, md-sys-color, on-surface), - ) + _generate-typography-tokens($systems, title-text, title-large), + ( + container-background-color: map.get($systems, md-sys-color, surface), + container-text-color: map.get($systems, md-sys-color, on-surface), + ) ); } @@ -84,6 +84,44 @@ ); } +/// Generates custom tokens for the mat-tab-header. +/// @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-tab-header +@function tab-header($systems, $exclude-hardcoded) { + @return mat.private-merge-all( + _generate-typography-tokens($systems, label-text, title-small), + ( + disabled-ripple-color: transparent, // TODO(mmalerba): Figure out correct value. + pagination-icon-color: map.get($systems, md-sys-color, on-surface), + inactive-label-text-color: map.get($systems, md-sys-color, on-surface), + active-label-text-color: map.get($systems, md-sys-color, on-surface), + active-ripple-color: map.get($systems, md-sys-color, on-surface), + inactive-ripple-color: map.get($systems, md-sys-color, on-surface), + inactive-focus-label-text-color: map.get($systems, md-sys-color, on-surface), + inactive-hover-label-text-color: map.get($systems, md-sys-color, on-surface), + active-focus-label-text-color: map.get($systems, md-sys-color, primary), + active-hover-label-text-color: map.get($systems, md-sys-color, primary), + active-focus-indicator-color: map.get($systems, md-sys-color, primary), + active-hover-indicator-color: map.get($systems, md-sys-color, primary), + ), + ); +} + +/// Generates custom tokens for the mdc-tab-indicator. (MDC has a tab-indicator 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-tab-indicator +@function tab-indicator($systems, $exclude-hardcoded) { + @return ( + active-indicator-height: 2px, + active-indicator-shape: 0, + active-indicator-color: map.get($systems, md-sys-color, primary), + ); +} + /// Generates custom tokens for the mat-tree. /// @param {Map} $systems The MDC system tokens /// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values diff --git a/src/material-experimental/theming/_m3-density.scss b/src/material-experimental/theming/_m3-density.scss index acab26f8e3c8..a92022e778f3 100644 --- a/src/material-experimental/theming/_m3-density.scss +++ b/src/material-experimental/theming/_m3-density.scss @@ -16,33 +16,39 @@ // TODO(mmalerba): Add density tokens for remaining components. $_density-tokens: ( // MDC tokens - (mdc, checkbox): ( - state-layer-size: (40px, 36px, 32px, 28px), - ), - (mdc, elevated-card): (), - (mdc, outlined-card): (), - (mdc, slider): (), - (mdc, snackbar): (), - (mdc, plain-tooltip): (), - (mdc, circular-progress): (), - (mdc, radio): ( - state-layer-size: (40px, 36px, 32px, 28px), - ), - (mdc, linear-progress): (), - (mdc, switch): (), + (mdc, checkbox): ( + state-layer-size: (40px, 36px, 32px, 28px), + ), + (mdc, elevated-card): (), + (mdc, outlined-card): (), + (mdc, slider): (), + (mdc, snackbar): (), + (mdc, plain-tooltip): (), + (mdc, circular-progress): (), + (mdc, radio): ( + state-layer-size: (40px, 36px, 32px, 28px), + ), + (mdc, linear-progress): (), + (mdc, switch): (), + (mdc, tab): ( + container-height: (48px, 44px, 40px, 36px, 32px) + ), + (mdc, tab-indicator): (), + // Custom Angular Material tokens - (mat, card): (), - (mat, toolbar): ( - standard-height: (64px, 60px, 56px, 52px), - mobile-height: (56px, 52px, 48px, 44px), - ), - (mat, slider): (), - (mat, snack-bar): (), - (mat, radio): (), - (mat, slide-toggle): (), - (mat, tree): ( - node-min-height: (48px, 44px, 40px, 36px, 28px), - ), + (mat, card): (), + (mat, toolbar): ( + standard-height: (64px, 60px, 56px, 52px), + mobile-height: (56px, 52px, 48px, 44px), + ), + (mat, slider): (), + (mat, snack-bar): (), + (mat, radio): (), + (mat, slide-toggle): (), + (mat, tab-header): (), + (mat, tree): ( + node-min-height: (48px, 44px, 40px, 36px, 28px), + ), ); /// Gets the value for the given density scale from the given set of density values. diff --git a/src/material-experimental/theming/_m3-tokens.scss b/src/material-experimental/theming/_m3-tokens.scss index 382854498439..a2f92802e6a1 100644 --- a/src/material-experimental/theming/_m3-tokens.scss +++ b/src/material-experimental/theming/_m3-tokens.scss @@ -168,97 +168,113 @@ // TODO(mmalerba): Fill in remaining tokens. $result: mat.private-merge-all( // Add the system color & typography tokens (so we can give users access via an API). - ( - (mdc, theme): map.get($systems, md-sys-color), - (mdc, typography): map.get($systems, md-sys-typescale), - ), - // Get the official MDC component tokens - _namespace-tokens( - (mdc, checkbox), - _fix-checkbox-tokens(mdc-tokens.md-comp-checkbox-values($systems, $exclude-hardcoded)), - $token-slots - ), - _namespace-tokens( - (mdc, elevated-card), - mdc-tokens.md-comp-elevated-card-values($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mdc, outlined-card), - mdc-tokens.md-comp-outlined-card-values($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mdc, slider), - mdc-tokens.md-comp-slider-values($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mdc, snackbar), - mdc-tokens.md-comp-snackbar-values($systems, $exclude-hardcoded), - $token-slots, - ), - _namespace-tokens( - (mdc, switch), - mdc-tokens.md-comp-switch-values($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mdc, plain-tooltip), - mdc-tokens.md-comp-plain-tooltip-values($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mdc, circular-progress), - mdc-tokens.md-comp-circular-progress-indicator-values($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mdc, radio), - mdc-tokens.md-comp-radio-button-values($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mdc, linear-progress), - mdc-tokens.md-comp-linear-progress-indicator-values($systems, $exclude-hardcoded), - $token-slots), - // Choose values for our made up tokens based on MDC system tokens or sensible hardcoded - // values. - _namespace-tokens( - (mat, card), - custom-tokens.card($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mat, toolbar), - custom-tokens.toolbar($systems, $exclude-hardcoded), - $token-slots, - ), - _namespace-tokens( - (mat, slide-toggle), - custom-tokens.slide-toggle($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mat, slider), - custom-tokens.slider($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mat, snack-bar), - custom-tokens.snack-bar($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mat, radio), - custom-tokens.radio($systems, $exclude-hardcoded), - $token-slots - ), - _namespace-tokens( - (mat, tree), - custom-tokens.tree($systems, $exclude-hardcoded), - $token-slots - ), + ( + (mdc, theme): map.get($systems, md-sys-color), + (mdc, typography): map.get($systems, md-sys-typescale), + ), + // Get the official MDC component tokens + _namespace-tokens( + (mdc, checkbox), + _fix-checkbox-tokens(mdc-tokens.md-comp-checkbox-values($systems, $exclude-hardcoded)), + $token-slots + ), + _namespace-tokens( + (mdc, elevated-card), + mdc-tokens.md-comp-elevated-card-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, outlined-card), + mdc-tokens.md-comp-outlined-card-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, slider), + mdc-tokens.md-comp-slider-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, snackbar), + mdc-tokens.md-comp-snackbar-values($systems, $exclude-hardcoded), + $token-slots, + ), + _namespace-tokens( + (mdc, switch), + mdc-tokens.md-comp-switch-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, plain-tooltip), + mdc-tokens.md-comp-plain-tooltip-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, circular-progress), + mdc-tokens.md-comp-circular-progress-indicator-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, radio), + mdc-tokens.md-comp-radio-button-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, linear-progress), + mdc-tokens.md-comp-linear-progress-indicator-values($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mdc, tab), + mdc-tokens.md-comp-secondary-navigation-tab-values($systems, $exclude-hardcoded), + $token-slots + ), + // Choose values for our made up tokens based on MDC system tokens or sensible hardcoded + // values. + _namespace-tokens( + (mdc, tab-indicator), + custom-tokens.tab-indicator($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mat, card), + custom-tokens.card($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mat, toolbar), + custom-tokens.toolbar($systems, $exclude-hardcoded), + $token-slots, + ), + _namespace-tokens( + (mat, slide-toggle), + custom-tokens.slide-toggle($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mat, slider), + custom-tokens.slider($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mat, snack-bar), + custom-tokens.snack-bar($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mat, radio), + custom-tokens.radio($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mat, tab-header), + custom-tokens.tree($systems, $exclude-hardcoded), + $token-slots + ), + _namespace-tokens( + (mat, tree), + custom-tokens.tree($systems, $exclude-hardcoded), + $token-slots + ), ); // Strip out tokens that are systemized by our made up density system. diff --git a/src/material/tabs/_tabs-theme.scss b/src/material/tabs/_tabs-theme.scss index eea4b3414588..0729baf88198 100644 --- a/src/material/tabs/_tabs-theme.scss +++ b/src/material/tabs/_tabs-theme.scss @@ -1,3 +1,4 @@ +@use 'sass:map'; @use '@material/tab-indicator/tab-indicator-theme' as mdc-tab-indicator-theme; @use '@material/tab/tab-theme' as mdc-tab-theme; @use '../core/style/sass-utils'; @@ -11,40 +12,50 @@ @use '../core/tokens/token-utils'; @mixin base($theme) { - @include sass-utils.current-selector-or-root() { - @include mdc-tab-indicator-theme.theme(tokens-mdc-tab-indicator.get-unthemable-tokens()); - @include mdc-tab-theme.secondary-navigation-tab-theme(tokens-mdc-tab.get-unthemable-tokens()); - @include token-utils.create-token-values( - tokens-mat-tab-header.$prefix, tokens-mat-tab-header.get-unthemable-tokens()); - @include token-utils.create-token-values( - tokens-mat-tab-header-with-background.$prefix, - tokens-mat-tab-header-with-background.get-unthemable-tokens() - ); + @if inspection.get-theme-version($theme) == 1 { + @include _theme-from-tokens(inspection.get-theme-tokens($theme, base)); + } + @else { + @include sass-utils.current-selector-or-root() { + @include mdc-tab-indicator-theme.theme(tokens-mdc-tab-indicator.get-unthemable-tokens()); + @include mdc-tab-theme.secondary-navigation-tab-theme(tokens-mdc-tab.get-unthemable-tokens()); + @include token-utils.create-token-values( + tokens-mat-tab-header.$prefix, tokens-mat-tab-header.get-unthemable-tokens()); + @include token-utils.create-token-values( + tokens-mat-tab-header-with-background.$prefix, + tokens-mat-tab-header-with-background.get-unthemable-tokens() + ); + } } } @mixin color($theme) { - .mat-mdc-tab-group, .mat-mdc-tab-nav-bar { - @include _palette-styles($theme, primary); + @if inspection.get-theme-version($theme) == 1 { + @include _theme-from-tokens(inspection.get-theme-tokens($theme, color)); + } + @else { + .mat-mdc-tab-group, .mat-mdc-tab-nav-bar { + @include _palette-styles($theme, primary); - &.mat-accent { - @include _palette-styles($theme, accent); - } + &.mat-accent { + @include _palette-styles($theme, accent); + } - &.mat-warn { - @include _palette-styles($theme, warn); - } + &.mat-warn { + @include _palette-styles($theme, warn); + } - &.mat-background-primary { - @include _background-styles($theme, primary); - } + &.mat-background-primary { + @include _background-styles($theme, primary); + } - &.mat-background-accent { - @include _background-styles($theme, accent); - } + &.mat-background-accent { + @include _background-styles($theme, accent); + } - &.mat-background-warn { - @include _background-styles($theme, warn); + &.mat-background-warn { + @include _background-styles($theme, warn); + } } } } @@ -64,43 +75,68 @@ } @mixin typography($theme) { - .mat-mdc-tab-header { - @include mdc-tab-theme.secondary-navigation-tab-theme( - tokens-mdc-tab.get-typography-tokens($theme)); - @include mdc-tab-indicator-theme.theme( - tokens-mdc-tab-indicator.get-typography-tokens($theme)); - @include token-utils.create-token-values(tokens-mat-tab-header.$prefix, - tokens-mat-tab-header.get-typography-tokens($theme)); - @include token-utils.create-token-values(tokens-mat-tab-header-with-background.$prefix, - tokens-mat-tab-header-with-background.get-typography-tokens($theme)); + @if inspection.get-theme-version($theme) == 1 { + @include _theme-from-tokens(inspection.get-theme-tokens($theme, typography)); + } + @else { + .mat-mdc-tab-header { + @include mdc-tab-theme.secondary-navigation-tab-theme( + tokens-mdc-tab.get-typography-tokens($theme)); + @include mdc-tab-indicator-theme.theme( + tokens-mdc-tab-indicator.get-typography-tokens($theme)); + @include token-utils.create-token-values(tokens-mat-tab-header.$prefix, + tokens-mat-tab-header.get-typography-tokens($theme)); + @include token-utils.create-token-values(tokens-mat-tab-header-with-background.$prefix, + tokens-mat-tab-header-with-background.get-typography-tokens($theme)); + } } } @mixin density($theme) { - .mat-mdc-tab-header { - @include mdc-tab-theme.secondary-navigation-tab-theme( - tokens-mdc-tab.get-density-tokens($theme)); - @include mdc-tab-indicator-theme.theme( - tokens-mdc-tab-indicator.get-density-tokens($theme)); - @include token-utils.create-token-values(tokens-mat-tab-header.$prefix, - tokens-mat-tab-header.get-density-tokens($theme)); - @include token-utils.create-token-values(tokens-mat-tab-header-with-background.$prefix, - tokens-mat-tab-header-with-background.get-density-tokens($theme)); + @if inspection.get-theme-version($theme) == 1 { + @include _theme-from-tokens(inspection.get-theme-tokens($theme, density)); + } + @else { + .mat-mdc-tab-header { + @include mdc-tab-theme.secondary-navigation-tab-theme( + tokens-mdc-tab.get-density-tokens($theme)); + @include mdc-tab-indicator-theme.theme( + tokens-mdc-tab-indicator.get-density-tokens($theme)); + @include token-utils.create-token-values(tokens-mat-tab-header.$prefix, + tokens-mat-tab-header.get-density-tokens($theme)); + @include token-utils.create-token-values(tokens-mat-tab-header-with-background.$prefix, + tokens-mat-tab-header-with-background.get-density-tokens($theme)); + } } } @mixin theme($theme) { @include theming.private-check-duplicate-theme-styles($theme, 'mat-tabs') { - @include base($theme); - @if inspection.theme-has($theme, color) { - @include color($theme); - } - @if inspection.theme-has($theme, density) { - @include density($theme); + @if inspection.get-theme-version($theme) == 1 { + @include _theme-from-tokens(inspection.get-theme-tokens($theme)); } - @if inspection.theme-has($theme, typography) { - @include typography($theme); + @else { + @include base($theme); + @if inspection.theme-has($theme, color) { + @include color($theme); + } + @if inspection.theme-has($theme, density) { + @include density($theme); + } + @if inspection.theme-has($theme, typography) { + @include typography($theme); + } } } } +@mixin _theme-from-tokens($tokens) { + @if ($tokens != ()) { + @include mdc-tab-theme.secondary-navigation-tab-theme( + map.get($tokens, tokens-mdc-tab.$prefix)); + @include mdc-tab-indicator-theme.theme( + map.get($tokens, tokens-mdc-tab-indicator.$prefix)); + @include token-utils.create-token-values( + tokens-mat-tab-header.$prefix, map.get($tokens, tokens-mat-tab-header.$prefix)); + } +}