Skip to content

Commit

Permalink
refactor(material/fab): change mat-fab to use MDC's token API (#26823)
Browse files Browse the repository at this point in the history
* refactor(material/button): change mat-fab to use MDC's token API

* fixup! refactor(material/button): change mat-fab to use MDC's token API

* fixup! refactor(material/button): change mat-fab to use MDC's token API
  • Loading branch information
wagnermaciel authored Jul 12, 2023
1 parent c973da2 commit cbac7f6
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 54 deletions.
113 changes: 70 additions & 43 deletions src/material/button/_fab-theme.scss
Original file line number Diff line number Diff line change
@@ -1,75 +1,102 @@
@use 'sass:map';
@use '@material/fab/fab' as mdc-fab;
@use '@material/fab/fab-theme' as mdc-fab-theme;
@use '@material/theme/theme-color' as mdc-theme-color;
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;

@use './button-theme-private';
@use '../core/mdc-helpers/mdc-helpers';
@use '../core/theming/theming';
@use '../core/tokens/m2/mdc/fab' as tokens-mdc-fab;
@use '../core/tokens/m2/mdc/extended-fab' as tokens-mdc-extended-fab;
@use '../core/typography/typography';

@mixin _fab-variant($foreground, $background) {
@include mdc-fab-theme.theme((
container-color: $background,
icon-color: $foreground,
));
@mixin _fab-variant($config, $foreground, $background) {
$color-config: map.merge(
$config,
(
primary: (
default: $background,
default-contrast: $foreground,
),
)
);
$color-tokens: tokens-mdc-fab.get-color-tokens($color-config);
@include mdc-fab-theme.theme($color-tokens);

--mat-mdc-fab-color: #{$foreground};
}

@function white-or-black($color, $is-dark) {
@return if(mdc-helpers.variable-safe-contrast-tone($color, $is-dark) == 'dark', #000, #fff);
}

@mixin color($config-or-theme) {
$config: theming.get-color-config($config-or-theme);
@include mdc-helpers.using-mdc-theme($config) {
$on-surface: mdc-theme-color.prop-value(on-surface);
$is-dark: map.get($config, is-dark);

.mat-mdc-fab, .mat-mdc-mini-fab {
$is-dark: map.get($config, is-dark);
$background: map.get($config, background);

$surface: theming.get-color-from-palette($background, card);
$primary: theming.get-color-from-palette(map.get($config, primary));
$accent: theming.get-color-from-palette(map.get($config, accent));
$warn: theming.get-color-from-palette(map.get($config, warn));

$on-surface: white-or-black($surface, $is-dark);
$on-primary: white-or-black($primary, $is-dark);
$on-accent: white-or-black($accent, $is-dark);
$on-warn: white-or-black($warn, $is-dark);

$disabled: rgba($on-surface, 0.12);
$on-disabled: rgba($on-surface, if(map.get($config, is-dark), 0.5, 0.38));

.mat-mdc-fab,
.mat-mdc-mini-fab {
// TODO(wagnermaciel): The ripple-theme-styles mixin depends heavily on
// being wrapped by using-mdc-theme. This workaround needs to be
// revisited w/ a more holistic solution.
@include mdc-helpers.using-mdc-theme($config) {
@include button-theme-private.ripple-theme-styles($config, true);
}

&.mat-unthemed {
@include _fab-variant($on-surface, mdc-theme-color.prop-value(surface));
}

&.mat-primary {
@include _fab-variant(
mdc-theme-color.prop-value(on-primary),
mdc-theme-color.prop-value(primary)
);
}

&.mat-accent {
@include _fab-variant(
mdc-theme-color.prop-value(on-secondary),
mdc-theme-color.prop-value(secondary)
);
}

&.mat-warn {
@include _fab-variant(
mdc-theme-color.prop-value(on-error),
mdc-theme-color.prop-value(error)
);
}

@include button-theme-private.apply-disabled-style() {
@include _fab-variant(
rgba($on-surface, if(map.get($config, is-dark), 0.5, 0.38)),
rgba($on-surface, 0.12)
);
}
@include button-theme-private.apply-disabled-style() {
@include _fab-variant($config, $on-disabled, $disabled);
}

&.mat-unthemed {
@include _fab-variant($config, $on-surface, $surface);
}

&.mat-primary {
@include _fab-variant($config, $on-primary, $primary);
}

&.mat-accent {
@include _fab-variant($config, $on-accent, $accent);
}

&.mat-warn {
@include _fab-variant($config, $on-warn, $warn);
}
}
}

@mixin typography($config-or-theme) {
$config: typography.private-typography-to-2018-config(
theming.get-typography-config($config-or-theme));
theming.get-typography-config($config-or-theme)
);

@include mdc-helpers.using-mdc-typography($config) {
@include mdc-fab.without-ripple($query: mdc-helpers.$mdc-typography-styles-query);
}

$typography-tokens: tokens-mdc-extended-fab.get-typography-tokens($config);
.mat-mdc-extended-fab {
@include mdc-extended-fab-theme.theme($typography-tokens);
}
}

@mixin density($config-or-theme) {}
@mixin density($config-or-theme) {
}

@mixin theme($theme-or-color-config) {
$theme: theming.private-legacy-get-theme($theme-or-color-config);
Expand Down
39 changes: 28 additions & 11 deletions src/material/button/fab.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
@use '@material/fab' as mdc-fab;
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
@use '@material/fab/fab-theme' as mdc-fab-theme;
@use '@material/elevation/elevation-theme' as mdc-elevation-theme;
@use '@material/theme/custom-properties' as mdc-custom-properties;

@use './button-base';
@use '../core/mdc-helpers/mdc-helpers';
@use '../core/style/private' as style-private;
@use '../core/focus-indicators/private' as focus-indicators-private;
@use '../core/tokens/m2/mdc/extended-fab' as m2-mdc-extended-fab;
@use '../core/tokens/m2/mdc/fab' as m2-mdc-fab;

@include mdc-helpers.disable-mdc-fallback-declarations {
@include mdc-fab.without-ripple($query: mdc-helpers.$mdc-base-styles-query);
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
$mdc-fab-token-slots: m2-mdc-fab.get-token-slots();
$mdc-extended-fab-token-slots: m2-mdc-extended-fab.get-token-slots();

// Add the MDC fab static styles.
@include mdc-fab.static-styles();

// Add default values for tokens that aren't outputted by the theming API.
.mat-mdc-fab, .mat-mdc-mini-fab {
// Add the official slots for the MDC fab.
@include mdc-fab-theme.theme-styles($mdc-fab-token-slots);

// Add default values for tokens that aren't outputted by the theming API.
@include mdc-fab-theme.theme(m2-mdc-fab.get-unthemable-tokens());
}

.mat-mdc-extended-fab {
// Add the official slots for the MDC fab.
@include mdc-extended-fab-theme.theme-styles($mdc-extended-fab-token-slots);

// Add default values for tokens that aren't outputted by the theming API.
@include mdc-extended-fab-theme.theme(m2-mdc-extended-fab.get-unthemable-tokens());
}
}

.mat-mdc-fab, .mat-mdc-mini-fab {
Expand All @@ -16,13 +42,6 @@
@include style-private.private-animation-noop();

@include mdc-helpers.disable-mdc-fallback-declarations {
// Theme configuration is copied over from MDC, because it isn't exported
@include mdc-fab.theme-styles(button-base.mat-private-button-remove-ripple((
container-color: transparent,
container-shape: mdc-fab.$shape-radius,
icon-color: inherit,
)));

// TODO(crisbeto): the elevation can be controlled using `container-elevation` in `theme-styles`
// however when it is passed in, MDC throws an error that `container-shadow-color` isn't
// passed in. When `container-shadow-color` is passed in, MDC throws another error, because
Expand Down Expand Up @@ -76,8 +95,6 @@
}

.mat-mdc-extended-fab {
@include mdc-fab.extended_($query: mdc-helpers.$mdc-base-styles-query);

& > .mat-icon,
& > .material-icons { // stylelint-disable-line selector-class-pattern
@include mdc-fab.extended-icon-padding(
Expand Down
88 changes: 88 additions & 0 deletions src/material/core/tokens/m2/mdc/_extended-fab.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
@use '../../../mdc-helpers/mdc-helpers';
@use '../../token-utils';
@use '../../../typography/typography-utils';

@use 'sass:map';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mdc, extended-fab);

@function get-unthemable-tokens() {
@return (
container-color: null,
container-elevation: null,
container-height: null,
container-shadow-color: null,
container-shape: null,
container-surface-tint-layer-color: null,
focus-container-elevation: null,
focus-icon-color: null,
focus-label-text-color: null,
focus-outline-color: null,
focus-outline-width: null,
focus-state-layer-color: null,
focus-state-layer-opacity: null,
hover-container-elevation: null,
hover-icon-color: null,
hover-label-text-color: null,
hover-state-layer-color: null,
hover-state-layer-opacity: null,
icon-color: null,
icon-size: null,
label-text-color: null,
lowered-container-elevation: null,
lowered-focus-container-elevation: null,
lowered-hover-container-elevation: null,
lowered-pressed-container-elevation: null,
pressed-container-elevation: null,
pressed-icon-color: null,
pressed-label-text-color: null,
pressed-ripple-color: null,
pressed-ripple-opacity: null,
pressed-state-layer-color: null,
pressed-state-layer-opacity: null
);
}

// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($config) {
@return ();
}

// Tokens that can be configured through Angular Material's typography theming API.
@function get-typography-tokens($config) {
// TODO(wagnermaciel): The earlier implementation of the snack bar used MDC's APIs to create the
// typography tokens. As a result, we unintentionally allowed `null` typography configs to be
// passed in. Since there a lot of apps that now depend on this pattern, we need this temporary
// fallback.
@if ($config == null) {
$config: mdc-helpers.private-fallback-typography-from-mdc();
}
@return (
label-text-font: typography-utils.font-family($config, button) or
typography-utils.font-family($config),
label-text-size: typography-utils.font-size($config, button),
label-text-tracking: typography-utils.letter-spacing($config, button),
label-text-weight: typography-utils.font-weight($config, button)
);
}

// Tokens that can be configured through Angular Material's density theming API.
@function get-density-tokens($config) {
@return ();
}

// 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 map.merge(
get-unthemable-tokens(),
map.merge(
get-color-tokens(token-utils.$placeholder-color-config),
map.merge(
get-typography-tokens(token-utils.$placeholder-typography-config),
get-density-tokens(token-utils.$placeholder-density-config)
)
)
);
}
89 changes: 89 additions & 0 deletions src/material/core/tokens/m2/mdc/_fab.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
@use '../../../theming/theming';
@use '../../token-utils';

@use 'sass:map';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mdc, fab);

// Tokens that can't be configured through Angular Material's current theming API,
// but may be in a future version of the theming API.
//
// Tokens that are available in MDC, but not used in Angular Material should be mapped to `null`.
// `null` indicates that we are intentionally choosing not to emit a slot or value for the token in
// our CSS.
$height: 56px;
$mini-height: 40px;
$shape-radius: 50%;
$ripple-target: '.mdc-fab__ripple';

@function get-unthemable-tokens() {
@return (
container-shape: 50%,
icon-size: 24px,

container-elevation: null,
container-height: null,
container-shadow-color: null,
container-surface-tint-layer-color: null,
container-width: null,

focus-container-elevation: null,
focus-icon-color: null,
focus-outline-color: null,
focus-outline-width: null,
focus-state-layer-color: null,
focus-state-layer-opacity: null,

hover-container-elevation: null,
hover-icon-color: null,
hover-state-layer-color: null,
hover-state-layer-opacity: null,

lowered-container-elevation: null,
lowered-focus-container-elevation: null,
lowered-hover-container-elevation: null,
lowered-pressed-container-elevation: null,

pressed-container-elevation: null,
pressed-icon-color: null,
pressed-ripple-color: null,
pressed-ripple-opacity: null,
pressed-state-layer-color: null,
pressed-state-layer-opacity: null
);
}

// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($config) {
$primary: map.get($config, primary);
$surface: theming.get-color-from-palette($primary, default);
$on-surface: theming.get-color-from-palette($primary, default-contrast);

@return (container-color: $surface, icon-color: $on-surface);
}

// Tokens that can be configured through Angular Material's typography theming API.
@function get-typography-tokens($config) {
@return ();
}

// Tokens that can be configured through Angular Material's density theming API.
@function get-density-tokens($config) {
@return ();
}

// 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 map.merge(
get-unthemable-tokens(),
map.merge(
get-color-tokens(token-utils.$placeholder-color-config),
map.merge(
get-typography-tokens(token-utils.$placeholder-typography-config),
get-density-tokens(token-utils.$placeholder-density-config)
)
)
);
}
Loading

0 comments on commit cbac7f6

Please sign in to comment.