fix(ui): declare Material system tokens and migrate dead --mdc overrides (#1775)

This commit is contained in:
4gray authored and GitHub committed 2026-10-01 18:02:50 +02:00
1 parent e4cf48fdc2
commit 572034f3be
28 files changed
+581 -88

No files matched your search

+77 -10
View File
@@ -6,8 +6,16 @@
@include mat.app-background();
// ─── Typography ─────────────────────────────────────────────────────────────
$app-font-stack:
// The stack is declared once on html; every Material typography token and the
// typography hierarchy read it through the variable. Inlined, the 103-char
// stack was copied into ~90 declarations (about 7 KB of the initial CSS).
$app-font-stack-value:
"'DM Sans', 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif";
$app-font-stack: var(--app-font-family);
html {
--app-font-family: #{$app-font-stack-value};
}
$my-typography: mat.m2-define-typography-config(
$font-family: $app-font-stack,
@@ -53,6 +61,17 @@ $dark-theme: mat.define-theme(
html {
@include mat.all-component-themes($light-theme);
// The theme is built with the legacy `define-theme` config, whose
// component mixins emit resolved component tokens but never declare the
// `--mat-sys-*` system variables. App styles reference those variables
// directly, so declare them explicitly for each theme context; without
// this every such reference silently resolves to nothing.
@include mat.system-level-colors($light-theme);
@include mat.system-level-typography($light-theme);
@include mat.system-level-elevation($light-theme);
@include mat.system-level-shape($light-theme);
@include mat.system-level-state($light-theme);
// ── Light theme design tokens ─────────────────────────────────────────
--app-shell-bg: #eef0f3;
--app-rail-bg: #eef0f3;
@@ -130,6 +149,9 @@ html {
.dark-theme {
@include mat.all-component-colors($dark-theme);
// Only the color roles differ per theme: the elevation shadows are
// the same black in both, so html's declarations already apply here.
@include mat.system-level-colors($dark-theme);
// ── Dark graphite theme ────────────────────────────────────────────
// Inspired by both Slack (sidebar distinction) and GitButler (data density)
@@ -228,16 +250,26 @@ $app-refined-input-density: mat.define-theme((
html {
@include mat.form-field-density($app-refined-input-density);
// Declared on the field itself (not on html) so the var(--app-*) values
// resolve inside .dark-theme instead of being inherited as light values.
// The resting and hover outlines keep the theme's outline roles: the app
// hairline tokens fall far under the 3:1 boundary contrast a field needs.
// Labels use the body token, which clears 4.5:1 in both themes.
// Text sizes stay on the theme defaults: this theme leaves the floated
// label's size token undeclared, so it inherits the field's text size and
// scales it to 75%; a 13px field would float a 10px label.
.mat-mdc-form-field {
--mdc-outlined-text-field-outline-color: var(--app-widget-header-border);
--mdc-outlined-text-field-hover-outline-color: var(--app-muted-color);
--mdc-outlined-text-field-focus-outline-color: var(--app-selection-color);
--mdc-outlined-text-field-container-shape: 10px;
--mdc-outlined-text-field-label-text-color: var(--app-muted-color);
--mdc-outlined-text-field-input-text-color: var(--app-heading-color);
--mdc-outlined-text-field-caret-color: var(--app-selection-color);
--mdc-outlined-text-field-label-text-size: 13px;
--mdc-outlined-text-field-input-text-size: 13.5px;
@include mat.form-field-overrides(
(
outlined-focus-outline-color: var(--app-selection-color),
outlined-container-shape: 10px,
outlined-label-text-color: var(--app-body-color),
outlined-hover-label-text-color: var(--app-body-color),
outlined-focus-label-text-color: var(--app-selection-color),
outlined-input-text-color: var(--app-heading-color),
outlined-caret-color: var(--app-selection-color),
)
);
}
// Inputs sit slightly above the surrounding surface. color-mix is inlined
@@ -254,6 +286,41 @@ html {
font-size: 13.5px;
}
// ─── Destructive actions ───────────────────────────────────────────────
// Material only emits `.mat-warn` button colors for M2 themes, so
// `color="warn"` is a no-op with this M3 theme. Buttons that remove or
// discard user data opt in with this class instead; the error tokens are
// declared per theme context above, so light and dark each get their own
// error/on-error pair.
.app-destructive-button {
@include mat.button-overrides(
(
filled-container-color: var(--mat-sys-error),
filled-label-text-color: var(--mat-sys-on-error),
filled-state-layer-color: var(--mat-sys-on-error),
filled-ripple-color:
color-mix(in srgb, var(--mat-sys-on-error) 12%, transparent),
text-label-text-color: var(--mat-sys-error),
text-state-layer-color: var(--mat-sys-error),
text-ripple-color:
color-mix(in srgb, var(--mat-sys-error) 12%, transparent),
outlined-label-text-color: var(--mat-sys-error),
outlined-outline-color: var(--mat-sys-error),
outlined-state-layer-color: var(--mat-sys-error),
outlined-ripple-color:
color-mix(in srgb, var(--mat-sys-error) 12%, transparent),
)
);
@include mat.icon-button-overrides(
(
icon-color: var(--mat-sys-error),
state-layer-color: var(--mat-sys-error),
ripple-color:
color-mix(in srgb, var(--mat-sys-error) 12%, transparent),
)
);
}
.mat-mdc-form-field-subscript-wrapper {
font-size: 11px;
letter-spacing: 0.01em;
+15 -4
View File
@@ -1,3 +1,4 @@
@use '@angular/material' as mat;
@use '../../../libs/ui/components/src/lib/resizable/resizable.scss';
@use './settings-theme';
@use './cover-size';
@@ -163,8 +164,14 @@ textarea,
}
// ─── Dark Theme ───────────────────────────────────────────────────────────────
.dark-theme {
// Only the app host takes the dark surface: components such as the fullscreen
// channel panel and the playback diagnostic's alternative sources carry
// `dark-theme` for its tokens while painting their own surfaces.
body.dark-theme {
background: var(--mat-sys-surface) !important;
}
.dark-theme {
color-scheme: dark;
// Refined scrollbar for dark mode
@@ -236,9 +243,13 @@ textarea,
// Failures (settings could not be saved/loaded) must not read as the usual
// neutral confirmation toast.
.mat-mdc-snack-bar-container.settings-snackbar--error {
--mdc-snackbar-container-color: var(--mat-sys-error-container);
--mdc-snackbar-supporting-text-color: var(--mat-sys-on-error-container);
--mat-snack-bar-button-color: var(--mat-sys-on-error-container);
@include mat.snack-bar-overrides(
(
container-color: var(--mat-sys-error-container),
supporting-text-color: var(--mat-sys-on-error-container),
button-color: var(--mat-sys-on-error-container),
)
);
}
// WCAG-friendly visually-hidden helper — content stays in the