Угловой материал - Глобальные переменные цвета
Глядя на документацию угловых материалов, они рекомендуют использовать -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
}
}