Угловой материал - Глобальные переменные цвета

Глядя на документацию угловых материалов, они рекомендуют использовать -theme файл для компонента, чтобы управлять применением любых связанных с темой стилей к определенному классу.

С моей точки зрения, некоторые недостатки этого подхода:

  • довольно многословный
  • разбивает стиль на две разные локации
  • все ваши разработчики должны понять, как работают цвета Angular Material
  • затрудняет изменение значений (например, мы могли использовать mat-color($primary, 200) для границ цветов и теперь хочу изменить его на mat-color($primary, 300), Это будет повторяться на протяжении всей кодовой базы.

При наличии согласованного языка дизайна будет использоваться только подмножество цветов (например, 4 цвета из основной палитры, 3 из акцентной палитры, несколько разных цветов переднего плана / фона и т. Д.).

Учитывая вышесказанное, не имеет ли смысла иметь _colors.scss который определяет точные цвета, используя тему, а не надеется, что разработчики извлекают правильное значение из темы каждый раз?

например, может быть что-то вроде:

  $clr-primary-default: mat-color($primary);
  $clr-primary-contrast: mat-color($primary, default-contrast);
  $clr-primary-light: mat-color($primary, lighter);
  $clr-primary-dark: mat-color($primary, darker);

  $clr-accent-default: mat-color($accent);
  $clr-accent-light: mat-color($accent, lighter);
  $clr-accent-dark: mat-color($accent, darker);

  $clr-default-text: mat-color($foreground);
  $clr-secondary-text: mat-color($foreground, secondary-text);

  //etc

Тогда вместо создания отдельного -theme файл для каждого компонента, который требует определенных цветов, я могу просто импортировать colors.scss файл и использовать переменные непосредственно в *.component.scss файл.

Просто хотите подтвердить, что все вышесказанное звучит правильно и что я не упускаю ничего очевидного, что может причинить боль в будущем?

Другая сложная часть заключается в том, как на самом деле определить их в отдельном colors Файл эффективно, учитывая, файл будет иметь доступ к данным темы.

2 ответа

Зачем использовать @mixin?

Просто хотите подтвердить, что все вышесказанное звучит правильно и что я не упускаю ничего очевидного, что может причинить боль в будущем?

Единственное, о чем я могу подумать, это то, что вы упустите возможность использовать несколько тем в одном приложении. С подходом из документации углового материала, у вас будет @mixin для каждого компонента, который вы можете @include несколько раз с разными $theme переменные.

Пример с https://medium.com/@tomastrajan/the-complete-guide-to-angular-material-themes-4d165a9d24d1:

.default-theme {
  @include angular-material-theme($theme);
  @include custom-component-theme($theme);
}

.light-theme {
  @include angular-material-theme($light-theme);
  @include custom-component-theme($light-theme);
}

Это не сработает, если вы импортируете цвета как scss-переменные в свои компоненты и используете их там.

Отдельный файл для цветов

Другая сложная часть заключается в том, как эффективно определить их в отдельном файле цветов, учитывая, что файлу потребуется доступ к данным темы.

Это на самом деле довольно просто: у меня есть отдельный файл src/styles/_variables.scss который содержит мои собственные цвета в качестве scss-переменных, а также $theme переменная, которую я использую позже в src/theme.scss,

@import '~@angular/material/theming';
// Theme configuration
$primary: mat-palette($mat-blue, 800, 500, 900);
$accent:  mat-palette($mat-blue, A200, A100, A400);
$warn: mat-palette($mat-red);

$theme: mat-light-theme($primary, $accent, $warn);

// Custom colors
$custom-colors: (
  custom-color-a: mat-color($mat-green, 700),
  custom-color-b: mat-color($mat-red, 400),
);
$theme: map-merge($theme, (custom-colors: $custom-colors));

Чтобы импортировать мой _variables.scss внутри компонента, я должен добавить stylePreprocessorOptions к angular.json файл:

"styles": [
  "src/styles.scss",
  "src/theme.scss"
],
"stylePreprocessorOptions": {
  "includePaths": [
    "src/styles"
  ]
},

Теперь я могу импортировать мои переменные во все scss-файлы моих компонентов:

@import 'variables';

.custom-class-a {
  background-color: map-get($custom-colors, custom-color-a);
  color: map-get($custom-colors, custom-color-b);
}

Почему я использую sass-карту и map-merge?

Как вы заметили, я собираю свои собственные цвета в sass-карте $custom-colors и слить их в мой $theme переменная. Таким образом, я мог либо использовать свои собственные цвета, импортируя их непосредственно в таблицу стилей компонентов (как описано выше), либо использовать их внутри своих компонентов. @mixin как это описано в документации угловых материалов.

@import '~@angular/material/theming';

@mixin custom-component-theme($theme) {
  $custom-colors: map-get($theme, custom-colors);

  .custom-class-a {
    background-color: map-get($custom-colors, custom-color-a);
    color: map-get($custom-colors, custom-color-b);
  }
}

Может быть, эта комбинация - способ, с помощью которого ваши разработчики веб-интерфейса могли бы работать?

Я определил основной, акцентный и предупредительный цвета как пользовательские переменные css в файле styles.css следующим образом:

@import "~@angular/material/theming";
@include mat-core();

$my-primary: mat-palette($mat-blue-grey);
$my-accent: mat-palette($mat-amber, A200, A100, A400);
$my-warn: mat-palette($mat-deep-orange);

$my-2-primary: mat-palette($mat-pink, 400, 200, 600);
$my-2-accent: mat-palette($mat-blue, A200, A100, A400);
$my-2-warn: mat-palette($mat-deep-orange, 500, 300, 700);

.dark-theme {
  $my-theme-dark: mat-dark-theme($my-primary, $my-accent, $my-warn);
  @include angular-material-theme($my-theme-dark);
  $primary: mat-color($my-primary);
  $accent: mat-color($my-accent);
  $warn: mat-color($my-warn);
  $fg_palette:map-get($my-theme-dark, foreground);
  $bg_palette:map-get($my-theme-dark, background);
  $fg:map-get($fg_palette, text);
  $bg:map-get($bg_palette, background);

  --primary: #{$primary};
  --accent: #{$accent};
  --warn: #{$warn};
  --fg: #{$fg};
  --bg: #{$bg};
}

.dark-theme-2 {
  $my-2-theme-dark: mat-dark-theme($my-2-primary, $my-2-accent, $my-2-warn);
  @include angular-material-theme($my-2-theme-dark);
  $primary: mat-color($my-2-primary);
  $accent: mat-color($my-2-accent);
  $warn: mat-color($my-2-warn);
  $fg_palette:map-get($my-2-theme-dark, foreground);
  $bg_palette:map-get($my-2-theme-dark, background);
  $fg:map-get($fg_palette, text);
  $bg:map-get($bg_palette, background);

  --primary: #{$primary};
  --accent: #{$accent};
  --warn: #{$warn};
  --fg: #{$fg};
  --bg: #{$bg};
}

И использовал эти переменные в любом из моих компонентов, например, так:(в my-custom-component.scss)

.some-class {
    color: var(--primary)
}

.another-class {
    background-color: var(--bg)
}

.yet-another-class {
    border-color: var(--accent)
}

Делая так, я могу изменить любое значение, связанное с цветом в любом компоненте, потому что эти переменные являются глобальными (определено в styles.css). Когда я меняю тему, эти цвета также меняются в соответствии с цветом новой темы.

Я работаю над проектом, в котором я использовал Темы Материала 2, и я использовал этот подход, где я использую имя класса и добавляю класс цветов глобально.

Вот что я сделал:

Имя файла: mytheme-sidemenu.scss:

// Import all the tools needed to customize the theme and extract parts of it
@import "~@angular/material/theming";
// Define a mixin that accepts a theme and outputs the color styles for the component.
@mixin mytheme-sidemenu($theme) {
  // Extract whichever individual palettes you need from the theme.
  $primary: map-get($theme, primary);
  $accent: map-get(
    $theme,
    accent
  ); // Use mat-color to extract individual colors from a palette as necessary.

  .col-primary {
    color: mat-color($primary, 500) !important;
  }
  .col-accent {
    color: mat-color($accent, 300) !important;
  }
}

Вот мой основной файл темы: mytheme-theme.scss:

@import '~@angular/material/theming';
@import './variables/helper.scss';
@import './variables/spacemanager.scss';
@import './mytheme-sidemenu.scss';

// Primary theme
@include mat-core();
$mytheme-app-primary: mat-palette($mat-light-blue, 700, 600);
$mytheme-app-accent: mat-palette($mat-pink, A200, 900, A100);
$mytheme-app-warn: mat-palette($mat-deep-orange);
$mytheme-app-theme: mat-light-theme($mytheme-app-primary, $mytheme-app-accent, $mytheme-app-warn);
@include angular-material-theme($mytheme-app-theme);
// Secondary Theme
.mytheme-alt-theme {
    $mytheme-alt-primary: mat-palette($mat-blue-grey, 500);
    $mytheme-alt-accent: mat-palette($mat-pink, 500);
    $mytheme-alt-warn: mat-palette($mat-deep-orange);
    $mytheme-alt-theme: mat-light-theme($mytheme-alt-primary, $mytheme-alt-accent, $mytheme-alt-warn);
    @include angular-material-theme($mytheme-alt-theme);
}
// Using the $theme variable from the pre-built theme you can call the theming function
@include mytheme-sidemenu($mytheme-app-theme);

и в app.module.ts обновите это:

export class AppModule {
  constructor(
    @Inject(OverlayContainer) private overlayContainer: OverlayContainer
  ) {
    this.overlayContainer
      .getContainerElement()
      .classList.add("mytheme-alt-theme"); // this for double theme add to the root css class
  }
}
Другие вопросы по тегам