Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs-bug(*): Missing migration guide to v19 #30055

Open
martinboue opened this issue Nov 20, 2024 · 16 comments
Open

docs-bug(*): Missing migration guide to v19 #30055

martinboue opened this issue Nov 20, 2024 · 16 comments
Assignees
Labels
docs This issue is related to documentation needs: discussion Further discussion with the team is needed before proceeding

Comments

@martinboue
Copy link

martinboue commented Nov 20, 2024

Documentation Feedback

I'm struggling to migrate from Angular Material v18 (with MD3) to v19. I did not find any migration guide and the new guides do not explain the basics as deeply as in the previous version.

Here are the most important use cases that I don't know how to deal with:

Note: I'm trying to remove the old $theme = mat.define-theme(...) to use the new @include mat.theme mixins

Styling custom components

Before

.my-component {
   background-color: mat.get-theme-color(theme.$theme, neutral, 98)
}

After

I cannot use mat.get-theme-color because I don't have a $theme anymore (previously from mat.define-theme). How can I do that?

Material 3 theme setup

Before

@include mat.core();
:root {
   @include mat.core-theme(theme.$light-theme);
}

After

It has been automatically replaced to:

@include mat.elevation-classes();
@include mat.app-background();
:root {
   @include mat.elevation-classes();
   @include mat.app-background();
}

What is it for? Why isn't it present if I create a new application with Angular Material? Should it be duplicated? I don't see any documentation mentioning those mixins.

Customising material components

Before

I could do this:

@include mat.chips-color(theme.$theme, $color-variant: primary);
@include mat.form-field-density(-3);

After

How to do the same? Do I need to use the new overrides mixins and set each color tokens? For example, that would be 25 colors for the chip component.

Affected documentation page

https://material.angular.io/guide/theming

@martinboue martinboue added docs This issue is related to documentation needs triage This issue needs to be triaged by the team labels Nov 20, 2024
@X-Celcius
Copy link

This is not only an issue when you want to migrate to the new mat.theme and override mixins. According to the comment in _core.scss, mat.core() is deprecated and doesn't do anything in v19. It took us some time to find out why .mat-app-background was no longer being defined when updating to v19.
If this is a breaking change it should at least be mentioned in the Changelog, but I can't find mat.core being mentioned there either.

@X-Celcius
Copy link

And while this is not related to documentation, may I also suggest to keep the scss in mat.core as it was and just add the deprecation annotation / warning rather than immediately changing the behavior and adding a comment that it is going to be removed in v21? Because if you already have to modify your code to get the old behavior why keep an empty mixin around?

@andrewseguin
Copy link
Contributor

Thanks for the feedback. Our previous theme config system was fairly complex and required a deep guide on its mechanics. We're hoping this new system is more straightforward with how it operates, but this means the guide might feel more lightweight than before.

Styling custom components

In the same pattern of system CSS variables, I'd recommend simply creating a top-level CSS variable for colors you want to use within your application. E.g.

--my-app-theme-neutral98: map.get($my-palette, neutral, 98);

This bypasses the need to create a separate mixin in your component styles that accepts a theme config, and allows you to just put the style directly in your component style.

If you want to continue using the mixin concept, you can pass it the palette or color directly.

Otherwise, you can always continue creating a theme config that can be passed around, in parallel to using mat.theme.

Material 3 theme setup

mat.core was replaced by elevation-classes and app-background since those styles were previously included in its old implementation. However, mat.core-theme should not have been replaced. If that happened in the update schematic, it should be filed as a bug.

For a new app, we don't really recommend using elevation-classes or app-background anymore. Elevation can be applied using the system level variables instead. And the app background can be set yourself if necessary (this is pointed out in the theming guide), which has the benefit of being explicit rather than a black-box mixin.

Customizing material components

What are you trying to achieve in the line for chips-color? Isn't the default going to be primary?

If you are trying to set it with a different color, you can write a selector that targets your mat-chips and redefine the theme as described in https://material.angular.io/guide/theming#context-specific-themes

This applies for density as well - you can target the form field and call mat.theme((density: -3)); or otherwise call the form field's overrides mixin and directly customize the tokens, e.g.

  @include mat.form-field-overrides((
    container-height: 44px,
    container-vertical-padding: 10px,
    filled-with-label-container-padding-top: 10px,
    filled-with-label-container-padding-bottom: 10px,
  ));

However, the density mixin still exists and you can continue calling mat.form-field-density(-3)

@andrewseguin
Copy link
Contributor

This is not only an issue when you want to migrate to the new mat.theme and override mixins. According to the comment in _core.scss, mat.core() is deprecated and doesn't do anything in v19. It took us some time to find out why .mat-app-background was no longer being defined when updating to v19. If this is a breaking change it should at least be mentioned in the Changelog, but I can't find mat.core being mentioned there either.

mat.core should have been replaced through the schematic to be:

@include mat.elevation-classes();
@include mat.app-background();

If this wasn't the case, it'd be helpful to have an issue filed. Our intention is to keep the same behavior/styling preserved for applications in the update process

@martinboue
Copy link
Author

Thanks @andrewseguin for your response, it has helped me a lot, but I still have a few issues:

Styling custom components

For color, replacing mat.get-theme-color(theme.$theme, neutral, 98) by map.get(theme.$palettes, neutral, 98) works great. Just one comment, I think it could be documented under Theming > Using Theme Styles

And for other styles, for example typography, I was used to do:

.my-component {
   font: mat.get-theme-typography(theme.$theme, label-large, font);
}

and now I should do the following (as described here)

.my-component {
   font: var(--mat-sys-label-large);
}

Am I right?

It is regrettable that reading theme styles does not follow the same rule as overriding styles, such as:

Angular strongly discourages, and does not directly support, overriding component CSS outside the theming APIs described above. Component DOM structure and CSS classes are considered private implementation details that may change at any time. CSS variables used by the Angular Material components should be defined through the overrides API instead of defined explicitly.

It would be great to have public APIs to rely on instead of CSS variables that cannot be checked during compilation.

Material 3 theme setup

I'll file a new issue for @include mat.core-theme(theme.$light-theme); being replaced to @include mat.elevation-classes(); and @include mat.app-background();

Customizing material components

Note: for chips, secondary color is actually the default one. It's documented here on v18. I was indeed changing the color from secondary to primary.

What you suggested do not work for me. I have:

// Theme setup, previously generated in v18
$palettes: (
   primary: (...),
   secondary: (...),
   ...
);
$_rest: (
   secondary: map.get($palettes, secondary),
   neutral: map.get($palettes, neutral),
   neutral-variant: map.get($palettes, neutral-variant),
   error: map.get($palettes, error),
);
$primary-palette: map.merge(map.get($palettes, primary), $_rest);

// Here I am trying to change the default color for all mat-chip
mat-chip-row {
   @include mat.theme((
      color: theme.$primary-palette,
   ));
}

It has no effect, no CSS properties have beean generated.

mat.theme((density: -3)) works great but compared to v18 it generates useless/unrelated CSS:

mat-chip-row {
   --mdc-checkbox-state-layer-size: 28px;
   --mdc-chip-container-height: 24px; // <====== I only need this one I guess
   --mdc-text-button-container-height: 28px;
   --mdc-protected-button-container-height: 28px;
   --mdc-filled-button-container-height: 28px;
   --mdc-outlined-button-container-height: 28px;
   --mdc-icon-button-state-layer-size: 28px;
   --mdc-list-list-item-one-line-container-height: 36px;
   --mdc-list-list-item-two-line-container-height: 52px;
   --mdc-list-list-item-three-line-container-height: 76px;
   --mdc-radio-state-layer-size: 28px;
   --mdc-secondary-navigation-tab-container-height: 36px;
   --mat-checkbox-touch-target-display: none;
   --mat-expansion-header-collapsed-state-height: 36px;
   --mat-expansion-header-expanded-state-height: 48px;
   --mat-fab-touch-target-display: none;
   --mat-form-field-container-height: 44px;
   --mat-form-field-filled-label-display: none;
   --mat-form-field-container-vertical-padding: 10px;
   --mat-form-field-filled-with-label-container-padding-top: 10px;
   --mat-form-field-filled-with-label-container-padding-bottom: 10px;
   --mat-icon-button-touch-target-display: none;
   --mat-list-list-item-leading-icon-start-space: 4px;
   --mat-list-list-item-leading-icon-end-space: 4px;
   --mat-text-button-touch-target-display: none;
   --mat-protected-button-touch-target-display: none;
   --mat-filled-button-touch-target-display: none;
   --mat-outlined-button-touch-target-display: none;
   --mat-paginator-container-size: 40px;
   --mat-paginator-form-field-container-height: 40px;
   --mat-paginator-form-field-container-vertical-padding: 8px;
   --mat-paginator-touch-target-display: none;
   --mat-radio-touch-target-display: none;
   --mat-select-arrow-transform: none;
   --mat-standard-button-toggle-height: 36px;
   --mat-stepper-header-height: 60px;
   --mat-table-header-container-height: 44px;
   --mat-table-footer-container-height: 40px;
   --mat-table-row-item-container-height: 40px;
   --mat-toolbar-standard-height: 52px;
   --mat-toolbar-mobile-height: 44px;
   --mat-tree-node-min-height: 36px;
}

Is there any way to generate only component related properties?

Also, now I need to specify every kind of chips (mat-chip, mat-chip-row and mat-chip-option) and rely on private CSS class or material host tag, both of which can change in the future and are not checked at compile time. Is there any other solution?

@rars
Copy link

rars commented Nov 21, 2024

It's not obvious to me how to handle typography for non-component styles. The default styles of h1, h2 etc. don't seem to look very nice with just the @include mat.theme(...) approach (I think the mixin doesn't touch the styles on these tags). I used to include the typography-hierarchy mixin and use the classes listed in type scale levels. I couldn't find relevant documentation and if it's missing, I think the documentation would benefit from touching on this subject.

@X-Celcius
Copy link

If this wasn't the case, it'd be helpful to have an issue filed. Our intention is to keep the same behavior/styling preserved for applications in the update process

Thanks, I wasn't aware of an update schematic. My colleague updated the Angular core libraries using ng update before the cdk & materials packages were available in v19. A day later, he updated the material packages directly without running ng update. I retried going v18 to v19 from scratch and everything updated automatically so this is actually working fine.
Still - please consider adding this change to CHANGELOG.md as I consider this to be a breaking change and it is not mentioned there. Automatic migrations are nice if they work but knowing what and why something will change is also essential when upgrading.

@martinboue
Copy link
Author

martinboue commented Nov 25, 2024

Because some of my comments on this issue goes beyond the scope "Migrating v18 to v19", I have created a specific request on "how to get theme values without relying on private APIs", see #30083

My main concern now is: How to migrate v18 mat.<component>-color mixins to v19?

If the solution is using the new mat.<component>-overrides mixin, could you consider adding a new mixin to easily change color for a single component without specifying every color tokens?

@crisbeto crisbeto added needs: discussion Further discussion with the team is needed before proceeding and removed needs triage This issue needs to be triaged by the team labels Nov 26, 2024
@martinboue
Copy link
Author

martinboue commented Nov 27, 2024

For context, here is a before/after comparison on how to change the chip component color:

Before in v18:

@include mat.chips-color(theme.$theme, $color-variant: primary);

After in v19:

@include mat.chips-overrides((
   elevated-selected-container-color: map.get(theme.$palettes, primary, 90),
   selected-label-text-color: map.get(theme.$palettes, primary, 10),
   selected-trailing-icon-color: map.get(theme.$palettes, primary, 10),
   selected-hover-state-layer-color: map.get(theme.$palettes, primary, 10),
   selected-trailing-action-state-layer-color: map.get(theme.$palettes, primary, 10),
   selected-focus-state-layer-color: map.get(theme.$palettes, primary, 10),
   with-icon-selected-icon-color: map.get(theme.$palettes, primary, 10)
));

It's much more complicated now, and if we want to keep the same level of contrast (here tones 10 and 90) we have to inspect the generated code and find the equivalent in the new palette.

Proposed solution

In v18 we had to pick a color from our theme, which wasn't very flexible. An ideal solution would be:

@include mat.chips-color(#FF0000); // <== We could pass any color here and the mixin would compute the tones

If not doable, then the same behavior as v18 would be good enough:

@include mat.chips-color(theme.$palettes, primary);
// or
$primary-palette: map.get(theme.$palettes, primary);
@include mat.chips-color($primary-palette);

EDIT : this specfic proposal as now its own issue here: #30241

@edvinv
Copy link

edvinv commented Nov 28, 2024

For example in 18 you can define:

.secondary-button {
  @include mat.button-color($theme, $color-variant: secondary);
}

In 19 you have :

.secondary-button {
   @include mat.button-overrides((
    filled-container-color: orange,
    filled-label-text-color: red,
    ....
  ));
}

For some control like icon, it is easy because there is single color, but for other it may be quite complicated. For now, as a workaround I have just done:

.secondary-button {
    --mat-sys-primary: var(--mat-sys-secondary);
  }

This works but it is just temporally solution. IMO mat.{component}-overrides should support changing color with single input parameter (for controls that are based on single color) like:

.secondary-button {
   @include mat.button-overrides((
    primary-color: var(--mat-sys-secondary),
  ));
}

@andrewseguin
Copy link
Contributor

It would be great to have public APIs to rely on instead of CSS variables that cannot be checked during compilation."

@martinboue The system level variables should be considered part of the public API. Any changes made to them in the future will be considered breaking and I'd expect us to build schematics to auto-update folks (e.g. renaming or removing variables)

Is there any way to generate only component related properties?

@martinboue You can use the component mixins like mat.chip-density(-3) to output only chip-related density tokens

Also, now I need to specify every kind of chips (mat-chip, mat-chip-row and mat-chip-option) and rely on private CSS class or material host tag, both of which can change in the future and are not checked at compile time. Is there any other solution?

@martinboue You shouldn't need to target a specific selector, just include that in your html or wherever you want that CSS variable definition to apply

It's not obvious to me how to handle typography for non-component styles.

@rars The typography hierarchy was a Material 2 typography spec, but that is no longer defined for Material 3. We did our best to mimic a reasonable hierarchy, but since it's not part of the spec I think it makes more sense for clients to set it themselves. You can use this as a reference and modify it if needed:

h1 {
    font: var(--mat-sys-display-large);
}

h2 {
    font: var(--mat-sys-display-medium);
}

h3 {
    font: var(--mat-sys-display-small);
}

h4 {
    font: var(--mat-sys-headline-large);
}

h5 {
    font: var(--mat-sys-headline-medium);
}

h6 {
    font: var(--mat-sys-headline-small);
}

@martinboue
Copy link
Author

@andrewseguin

The system level variables should be considered part of the public API. Any changes made to them in the future will be considered breaking and I'd expect us to build schematics to auto-update folks (e.g. renaming or removing variables)

From my understanding, system variables are useful for changing global styles or reusing it for non-material components but are not ideal for customizing material components.

You can use the component mixins like mat.chip-density(-3) to output only chip-related density tokens

Yes it works for density, but what about color? It's a very common use case to change a material component color but there is no way to do it easily like we used to with mat.<component>-color mixin.

Could you please give us an example in v19 of how to change the color of a chip where the result is the equivalent of the mat.chip-color mixin in v18?

@yusufakg
Copy link

yusufakg commented Dec 8, 2024

Expanding on @andrewseguin input. For anyone that is updating to the new mat.theme and used typography-hierachy before here is what I did to get the same effect.

theme-typography.scss:

@mixin my-typography-hierarchy {
  // Display styles
  h1 {
    font: var(--mat-sys-display-large);
    letter-spacing: var(--mat-sys-display-large-tracking);
    margin: 0 0 16px;
  }

  h2 {
    font: var(--mat-sys-display-medium);
    letter-spacing: var(--mat-sys-display-medium-tracking);
    margin: 0 0 16px;
  }

  h3 {
    font: var(--mat-sys-display-small);
    letter-spacing: var(--mat-sys-display-small-tracking);
    margin: 0 0 16px;
  }

  // Headline styles
  h4 {
    font: var(--mat-sys-headline-large);
    letter-spacing: var(--mat-sys-headline-large-tracking);
    margin: 0 0 16px;
  }

  h5 {
    font: var(--mat-sys-headline-medium);
    letter-spacing: var(--mat-sys-headline-medium-tracking);
    margin: 0 0 12px;
  }

  h6 {
    font: var(--mat-sys-headline-small);
    letter-spacing: var(--mat-sys-headline-small-tracking);
    margin: 0 0 12px;
  }

  // Body styles
  body {
    font: var(--mat-sys-body-large);
    letter-spacing: var(--mat-sys-body-large-tracking);

    p {
      margin: 0 0 12px;
    }
  }

  // Additional body classes
  .body-small {
    font: var(--mat-sys-body-small);
    letter-spacing: var(--mat-sys-body-small-tracking);
  }

  .body-medium {
    font: var(--mat-sys-body-medium);
    letter-spacing: var(--mat-sys-body-medium-tracking);
  }

  .body-large {
    font: var(--mat-sys-body-large);
    letter-spacing: var(--mat-sys-body-large-tracking);
  }

  // Additional display classes
  .display-small {
    font: var(--mat-sys-display-small);
    letter-spacing: var(--mat-sys-display-small-tracking);
  }

  .display-medium {
    font: var(--mat-sys-display-medium);
    letter-spacing: var(--mat-sys-display-medium-tracking);
  }

  .display-large {
    font: var(--mat-sys-display-large);
    letter-spacing: var(--mat-sys-display-large-tracking);
  }

  // Additional headline classes
  .headline-small {
    font: var(--mat-sys-headline-small);
    letter-spacing: var(--mat-sys-headline-small-tracking);
  }

  .headline-medium {
    font: var(--mat-sys-headline-medium);
    letter-spacing: var(--mat-sys-headline-medium-tracking);
  }

  .headline-large {
    font: var(--mat-sys-headline-large);
    letter-spacing: var(--mat-sys-headline-large-tracking);
  }

  // Additional label classes
  .label-small {
    font: var(--mat-sys-label-small);
    letter-spacing: var(--mat-sys-label-small-tracking);
  }

  .label-medium {
    font: var(--mat-sys-label-medium);
    letter-spacing: var(--mat-sys-label-medium-tracking);
  }

  .label-large {
    font: var(--mat-sys-label-large);
    letter-spacing: var(--mat-sys-label-large-tracking);
  }

  // Additional title classes
  .title-small {
    font: var(--mat-sys-title-small);
    letter-spacing: var(--mat-sys-title-small-tracking);
  }

  .title-medium {
    font: var(--mat-sys-title-medium);
    letter-spacing: var(--mat-sys-title-medium-tracking);
  }

  .title-large {
    font: var(--mat-sys-title-large);
    letter-spacing: var(--mat-sys-title-large-tracking);
  }
}

And then i use it in styles.scss:

...
@use "./theme-typography.scss" as m3-theme-typography;

html {
  @include mat.theme((
    ...
  ));

  @include m3-theme-typography.my-typography-hierarchy;
}

I do find this slightly better mainly because of future discoverability/maintainability and while I understand the reasoning, I just wished it was mentioned somewhere without searching through issues.

@floinay
Copy link

floinay commented Dec 10, 2024

Recently, I spent several days figuring out how to style a theme in Material 18, including working with use-system-variables, system-variables-prefix, density, and typography, because the documentation is very superficial.

Now, I need to do all of this again with Material 19. Additionally, the old API is not fully supported, but the code does not throw any errors, even though my theme no longer works as expected after migration.

You really need to improve the documentation and include more examples with links to various templates on GitHub. Perhaps it’s worth considering hiring someone specifically to handle this aspect.

@JoepKockelkorn
Copy link
Contributor

I've recently investigated how to use Material 18 and thought I had it all figured out. Now, when actually starting the project and using Material 19 I find out the typography mixin is now missing. When/where was that communicated? I inspected the CHANGELOG but can't seem to find the moment in time or a related reference.

@martinboue
Copy link
Author

As there are several subjects in this issue, I have a created a specific feature request on "How to change a material component color" which sums up the original problem I had, here: #30241

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs This issue is related to documentation needs: discussion Further discussion with the team is needed before proceeding
Projects
None yet
Development

No branches or pull requests

9 participants