Модуль 3 · урок 8 з 11
Дизайн-токени в Angular
У модулі 1 ти зробив тему на CSS-змінних. Тут вона зустрічається з Angular:
як розкласти токени по рівнях, як стилізувати сторонні компоненти без ::ng-deep
і що робити з Angular Material, якщо на проєкті використовують саме його.
Три рівні токенів
/* 1. Примітиви — сира палітра. Ніде не використовуються напряму. */
:root {
--blue-600: #2563EB;
--slate-900: #0F172A;
--space-2: 8px;
}
/* 2. Семантичні — ролі. Саме їх пишуть у компонентах. */
:root {
--color-accent: var(--blue-600);
--color-ink: var(--slate-900);
--gap-tight: var(--space-2);
}
/* 3. Компонентні — локальні ручки налаштування. */
:host {
--card-padding: 16px;
--card-radius: 10px;
}
Сенс середнього рівня в тому, що тема перевизначає ролі, а не кольори. У темній темі
--color-accent стане іншим, і жоден компонент про це не дізнається — саме тому
в модулі 1 ми домовились називати токени за роллю, а не за кольором.
Компонент із власними ручками
:host {
--card-padding: 16px; /* значення за замовчуванням */
display: block;
padding: var(--card-padding);
border-radius: var(--card-radius, 10px); /* із запасним значенням */
background: var(--color-surface);
}
:host([data-density="compact"]) {
--card-padding: 8px; /* варіант через атрибут */
}
<!-- батько може підкрутити ззовні, не знаючи внутрішньої розмітки -->
<app-task-card style="--card-padding: 4px" />
<app-task-card data-density="compact" />
Замість того, щоб ззовні пробивати ізоляцію й міняти чужі класи, компонент сам оголошує,
що в ньому можна налаштувати. Виходить публічний контракт стилів: список змінних —
така сама частина API компонента, як його input().
Динамічні значення з класу
@Component({
host: {
'[style.--progress]': 'percent()',
},
template: `<div class="bar"></div>`,
})
export class ProgressBar {
percent = input(0);
}
.bar { width: calc(var(--progress) * 1%); }
Прив'язка кастомної властивості — акуратний спосіб передати число в CSS без інлайнових стилів на кожен елемент. Особливо зручно для індикаторів, графіків і всього, де значення змінюється часто.
Angular Material: як стилізувати правильно
Якщо на робочому проєкті використовують Material — а лід згадав його в таблиці — правило одне: налаштовувати через його систему тем, а не перебивати селектори.
// styles.scss
@use '@angular/material' as mat;
html {
@include mat.theme((
color: (
primary: mat.$violet-palette,
theme-type: light,
),
typography: Roboto,
density: 0,
));
}
/* точкове налаштування окремого компонента — через його ж змінні */
.dense-form {
@include mat.form-field-density(-2);
}
- Тема Material через його міксини — в одному місці.
- Свої CSS-змінні для власних компонентів.
- Класи-модифікатори на хості:
data-density,.is-compact. - Глобальні правки для бібліотеки — свідомо, у
styles.scss, з коментарем.
::ng-deep .mat-mdc-*у файлі компонента.!importantпоруч із класами бібліотеки.- Однакові виправлення Material у пʼятьох різних компонентах.
- Стилі, привʼязані до внутрішніх класів бібліотеки, які зміняться в наступній версії.
Де що має лежати
src/styles/
_tokens.scss // примітиви й семантичні токени, обидві теми
_reset.scss
_mixins.scss
_material.scss // тема бібліотеки, якщо вона є
styles.scss // збирає все через @use
// компонентні токени лишаються біля компонента, у його ж .scss
Найпереконливіше — перемкнути тему на демо й показати, що жоден компонент не містить жодного кольору напряму: усе через токени. Це рівно те, чого просить перший пункт таблиці, і водночас доказ, що ти розумієш ізоляцію стилів у Angular.