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

feat(style): Runtime theme generation #29104

Open
tanishqmanuja opened this issue May 23, 2024 · 12 comments
Open

feat(style): Runtime theme generation #29104

tanishqmanuja opened this issue May 23, 2024 · 12 comments
Labels
docs This issue is related to documentation P2 The issue is important to a large percentage of users, with a workaround

Comments

@tanishqmanuja
Copy link

Feature Description

The ability to generate theme based on a seed color at runtime instead of compile time.

Use Case

This is very common in native android apps and would also benefit ionic/capacitor user to make their app feel more native

@tanishqmanuja tanishqmanuja added feature This issue represents a new feature or feature request rather than a bug or bug fix needs triage This issue needs to be triaged by the team labels May 23, 2024
@crisbeto
Copy link
Member

It's not properly documented yet, but there's a use-system-variables in the color and typography fields of M3 themes. If you set it to true, you'll be able to theme dynamically by changing a ~10 CSS variables at runtime. Here's how to pass it: https://github.com/angular/components/blob/main/src/dev-app/theme-m3.scss#L15

@crisbeto crisbeto added P2 The issue is important to a large percentage of users, with a workaround docs This issue is related to documentation and removed feature This issue represents a new feature or feature request rather than a bug or bug fix needs triage This issue needs to be triaged by the team labels May 23, 2024
@tanishqmanuja
Copy link
Author

Thanks, this is exactly what I needed. Can you also provide a link to find what CSS Vars are used ?

@crisbeto
Copy link
Member

Below are all the possible ones. You don't need to provide all of them, e.g. if you don't set use-system-variables for the typography, you can skip the whole typography section. We also have the mat.system-level-colors and mat.system-level-typography mixins that you can use to generate the values from a theme.

// Colors
--sys-background
--sys-error
--sys-error-container
--sys-inverse-on-surface
--sys-inverse-primary
--sys-inverse-surface
--sys-on-background
--sys-on-error
--sys-on-error-container
--sys-on-primary
--sys-on-primary-container
--sys-on-primary-fixed
--sys-on-primary-fixed-variant
--sys-on-secondary
--sys-on-secondary-container
--sys-on-secondary-fixed
--sys-on-secondary-fixed-variant
--sys-on-surface
--sys-on-surface-variant
--sys-on-tertiary
--sys-on-tertiary-container
--sys-on-tertiary-fixed
--sys-on-tertiary-fixed-variant
--sys-outline
--sys-outline-variant
--sys-primary
--sys-primary-container
--sys-primary-fixed
--sys-primary-fixed-dim
--sys-scrim
--sys-secondary
--sys-secondary-container
--sys-secondary-fixed
--sys-secondary-fixed-dim
--sys-shadow
--sys-surface
--sys-surface-bright
--sys-surface-container
--sys-surface-container-high
--sys-surface-container-highest
--sys-surface-container-low
--sys-surface-container-lowest
--sys-surface-dim
--sys-surface-tint
--sys-surface-variant
--sys-tertiary
--sys-tertiary-container
--sys-tertiary-fixed
--sys-tertiary-fixed-dim

// Typography
--sys-body-large
--sys-body-large-font
--sys-body-large-line-height
--sys-body-large-size
--sys-body-large-tracking
--sys-body-large-weight
--sys-body-medium
--sys-body-medium-font
--sys-body-medium-line-height
--sys-body-medium-size
--sys-body-medium-tracking
--sys-body-medium-weight
--sys-body-small
--sys-body-small-font
--sys-body-small-line-height
--sys-body-small-size
--sys-body-small-tracking
--sys-body-small-weight
--sys-display-large
--sys-display-large-font
--sys-display-large-line-height
--sys-display-large-size
--sys-display-large-tracking
--sys-display-large-weight
--sys-display-medium
--sys-display-medium-font
--sys-display-medium-line-height
--sys-display-medium-size
--sys-display-medium-tracking
--sys-display-medium-weight
--sys-display-small
--sys-display-small-font
--sys-display-small-line-height
--sys-display-small-size
--sys-display-small-tracking
--sys-display-small-weight
--sys-headline-large
--sys-headline-large-font
--sys-headline-large-line-height
--sys-headline-large-size
--sys-headline-large-tracking
--sys-headline-large-weight
--sys-headline-medium
--sys-headline-medium-font
--sys-headline-medium-line-height
--sys-headline-medium-size
--sys-headline-medium-tracking
--sys-headline-medium-weight
--sys-headline-small
--sys-headline-small-font
--sys-headline-small-line-height
--sys-headline-small-size
--sys-headline-small-tracking
--sys-headline-small-weight
--sys-label-large
--sys-label-large-font
--sys-label-large-line-height
--sys-label-large-size
--sys-label-large-tracking
--sys-label-large-weight
--sys-label-large-weight-prominent
--sys-label-medium
--sys-label-medium-font
--sys-label-medium-line-height
--sys-label-medium-size
--sys-label-medium-tracking
--sys-label-medium-weight
--sys-label-medium-weight-prominent
--sys-label-small
--sys-label-small-font
--sys-label-small-line-height
--sys-label-small-size
--sys-label-small-tracking
--sys-label-small-weight
--sys-title-large
--sys-title-large-font
--sys-title-large-line-height
--sys-title-large-size
--sys-title-large-tracking
--sys-title-large-weight
--sys-title-medium
--sys-title-medium-font
--sys-title-medium-line-height
--sys-title-medium-size
--sys-title-medium-tracking
--sys-title-medium-weight
--sys-title-small
--sys-title-small-font
--sys-title-small-line-height
--sys-title-small-size
--sys-title-small-tracking
--sys-title-small-weight

@tanishqmanuja
Copy link
Author

That's awesome, they are the same as material-web style tokens with just different prefix --md-sys <-> --sys. With material-color-utilities npm package, it should be super simple to provide these.

@tanishqmanuja
Copy link
Author

AFAIK material-color-utilities don't inject surface tokens as of now, here's a snippet if anyone needs it.

import { hexFromArgb, Theme } from "@material/material-color-utilities";

export function applySurfaceStyles(
  theme: Theme,
  { dark }: { dark: boolean },
): void {
  if (dark) {
    const elevationProps = {
      "--md-sys-color-surface-dim": theme.palettes.neutral.tone(6),
      "--md-sys-color-surface-bright": theme.palettes.neutral.tone(24),
      "--md-sys-color-surface-container-lowest": theme.palettes.neutral.tone(4),
      "--md-sys-color-surface-container-low": theme.palettes.neutral.tone(10),
      "--md-sys-color-surface-container": theme.palettes.neutral.tone(12),
      "--md-sys-color-surface-container-high": theme.palettes.neutral.tone(17),
      "--md-sys-color-surface-container-highest":
        theme.palettes.neutral.tone(22),
    };

    for (const [property, argbColor] of Object.entries(elevationProps)) {
      document.body.style.setProperty(property, hexFromArgb(argbColor));
    }
  } else {
    const elevationProps = {
      "--md-sys-color-surface-dim": theme.palettes.neutral.tone(87),
      "--md-sys-color-surface-bright": theme.palettes.neutral.tone(98),
      "--md-sys-color-surface-container-lowest":
        theme.palettes.neutral.tone(100),
      "--md-sys-color-surface-container-low": theme.palettes.neutral.tone(96),
      "--md-sys-color-surface-container": theme.palettes.neutral.tone(94),
      "--md-sys-color-surface-container-high": theme.palettes.neutral.tone(92),
      "--md-sys-color-surface-container-highest":
        theme.palettes.neutral.tone(90),
    };

    for (const [property, argbColor] of Object.entries(elevationProps)) {
      document.body.style.setProperty(property, hexFromArgb(argbColor));
    }
  }
}

Change the prefix as per requirement 🤞🏻

@konstantindenerz
Copy link
Contributor

konstantindenerz commented Jul 9, 2024

There is a new option to configure the prefix of system variables.

Read more about this in my article, which includes a live demo: https://konstantin-denerz.com/angular-material-3-theming-design-tokens-and-system-variables/

@tanishqmanuja
Copy link
Author

Offtopic - Your site looks really amazing, I have mostly seen bottom navs (on mobile view) with icons but your text based bottom nav is 🔥

@tanishqmanuja
Copy link
Author

tanishqmanuja commented Aug 10, 2024

First attempt after reading @konstantindenerz article https://github.com/tanishqmanuja/demo.ng-material-dynamic-theme

Is this inline with the best practices suggested by angular-material ?

PS:
I am still confused about how to inject typography tokens

@shhdharmen
Copy link

For one of my article, I used applyTheme from @material/material-color-utilities, and it generated all the needed colors. You can read the article with demo at https://angular-material.dev/articles/angular-material-theming-css-vars

@tanishqmanuja
Copy link
Author

tanishqmanuja commented Sep 13, 2024

Is there a way to do this at component level easily.

image
image

The double inheritance problem, Why this wont work for individual components? - lit playground

Also this is a very common use-case, suppose i want to display multiple color schemes option at once to a user.

PRACTICAL NEED:
Suppose I make a theme service that applies the dynamically generated css vars like --md-sys-* etc to the host component where the service is provided, the service depends on a minimal injection token SOURCE_COLOR for generating the color scheme. Now the problem arises because even though every thing should work in theory, as it works with lit based material components (which are now on maintenance mode, and the docs reads "use angular material for angular framework" ), but due to inherited css vars used in angular-material components, there is no way to make such a thing work with angular-material. Any thoughts ?

@shhdharmen
Copy link

shhdharmen commented Sep 13, 2024

At component level angular material uses lots of internal variables. But, with Angular Material 18, team have introduced overrides API, you can use it like below, of course, for runtime changes you will still need to figure out all of CSS (--mat-* and --mdc-*) the variables.

button {
    @include mat.button-overrides((
        ripple-color: red
    ))
}

@tanishqmanuja
Copy link
Author

figuring out all those without docs doesnt sound too good either. So that's a no for sure :(

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 P2 The issue is important to a large percentage of users, with a workaround
Projects
None yet
Development

No branches or pull requests

4 participants