mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 14:16:16 -08:00
fix(ui): declare Material system tokens and migrate dead --mdc overrides (#1775)
This commit is contained in:
1 parent
e4cf48fdc2
commit
572034f3be
28 files changed
+581
-88
No files matched your search
+77
-10
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user