diff --git a/src/dev-app/BUILD.bazel b/src/dev-app/BUILD.bazel
index bfff3ac9479a..187cabcd0107 100644
--- a/src/dev-app/BUILD.bazel
+++ b/src/dev-app/BUILD.bazel
@@ -83,6 +83,7 @@ ng_project(
"//src/dev-app/slider",
"//src/dev-app/snack-bar",
"//src/dev-app/stepper",
+ "//src/dev-app/system",
"//src/dev-app/table",
"//src/dev-app/table-scroll-container",
"//src/dev-app/tabs",
diff --git a/src/dev-app/dev-app/dev-app-layout.ts b/src/dev-app/dev-app/dev-app-layout.ts
index 87243e6b4985..378922ef62f4 100644
--- a/src/dev-app/dev-app/dev-app-layout.ts
+++ b/src/dev-app/dev-app/dev-app-layout.ts
@@ -111,6 +111,7 @@ export class DevAppLayout {
{name: 'Slider', route: '/slider'},
{name: 'Snack Bar', route: '/snack-bar'},
{name: 'Stepper', route: '/stepper'},
+ {name: 'System', route: '/system'},
{name: 'Table Scroll Container', route: '/table-scroll-container'},
{name: 'Table', route: '/table'},
{name: 'Tabs', route: '/tabs'},
diff --git a/src/dev-app/routes.ts b/src/dev-app/routes.ts
index 51026dea8205..b17cfc1e3254 100644
--- a/src/dev-app/routes.ts
+++ b/src/dev-app/routes.ts
@@ -235,6 +235,10 @@ export const DEV_APP_ROUTES: Routes = [
path: 'stepper',
loadComponent: () => import('./stepper/stepper-demo').then(m => m.StepperDemo),
},
+ {
+ path: 'system',
+ loadComponent: () => import('./system/system-demo').then(m => m.SystemDemo),
+ },
{
path: 'table',
loadComponent: () => import('./table/table-demo').then(m => m.TableDemo),
diff --git a/src/dev-app/system/BUILD.bazel b/src/dev-app/system/BUILD.bazel
new file mode 100644
index 000000000000..521cff42886f
--- /dev/null
+++ b/src/dev-app/system/BUILD.bazel
@@ -0,0 +1,22 @@
+load("//tools:defaults.bzl", "ng_project", "sass_binary")
+
+package(default_visibility = ["//visibility:public"])
+
+ng_project(
+ name = "system",
+ srcs = glob(["**/*.ts"]),
+ assets = [
+ "system-demo.html",
+ "system_demo_scss",
+ ],
+ deps = [
+ "//:node_modules/@angular/common",
+ "//:node_modules/@angular/core",
+ "//src/material/card",
+ ],
+)
+
+sass_binary(
+ name = "system_demo_scss",
+ src = "system-demo.scss",
+)
diff --git a/src/dev-app/system/system-demo.html b/src/dev-app/system/system-demo.html
new file mode 100644
index 000000000000..0dbc3eba9f91
--- /dev/null
+++ b/src/dev-app/system/system-demo.html
@@ -0,0 +1,21 @@
+@for (group of colorGroups; track $index) {
+
{{group.name}}
+
+ @for (role of group.roles; track $index) {
+ @let titleColorRole = role.titleColorRole || role.foregroundColors[0];
+
+ @for (backgroundColor of role.backgroundColors; track $index) {
+
+
+ {{backgroundColor}}
+
+ @for (foregroundColor of role.foregroundColors; track $index) {
+
+ {{foregroundColor}}
+
+ }
+
+ }
+
+ }
+}
diff --git a/src/dev-app/system/system-demo.scss b/src/dev-app/system/system-demo.scss
new file mode 100644
index 000000000000..62395b2b064f
--- /dev/null
+++ b/src/dev-app/system/system-demo.scss
@@ -0,0 +1,29 @@
+mat-card {
+ font: var(--mat-sys-body-medium);
+ display: inline-flex;
+ flex-direction: column;
+ margin: 1rem;
+ overflow: hidden;
+ min-height: 16rem;
+}
+
+.example-background {
+ width: 16rem;
+ flex-grow: 1;
+ padding: 1rem 0.5rem 1rem 0;
+}
+
+.example-foreground {
+ padding-inline-start: 2rem;
+}
+
+.example-role-title {
+ font: var(--mat-sys-title-small);
+ padding-inline-start: 1rem;
+ margin-bottom: 1rem;
+}
+
+section {
+ margin-inline: 3rem;
+ max-width: 75px;
+}
diff --git a/src/dev-app/system/system-demo.ts b/src/dev-app/system/system-demo.ts
new file mode 100644
index 000000000000..ba611cda5fbd
--- /dev/null
+++ b/src/dev-app/system/system-demo.ts
@@ -0,0 +1,119 @@
+import {CommonModule} from '@angular/common';
+import {ChangeDetectionStrategy, Component} from '@angular/core';
+import {MatCardModule} from '@angular/material/card';
+
+interface RoleCategory {
+ /** Display name of a category for grouping related roles. */
+ name: string;
+ roles: ColorGroup[];
+}
+
+interface ColorGroup {
+ /** List of role names used for background colors in this group. */
+ backgroundColors: string[];
+
+ /** List of role names used for foreground colors in this group. */
+ foregroundColors: string[];
+
+ /**
+ * Optional color role name to use for displaying titles. If not specified,
+ * the first foreground color is used.
+ */
+ titleColorRole?: string;
+}
+
+/**
+ * Demo showing color swatches for Material Color Roles in the default GM3 and
+ * Angular Material color palettes.
+ */
+@Component({
+ selector: 'system-demo',
+ templateUrl: 'system-demo.html',
+ styleUrls: ['system-demo.css'],
+ imports: [CommonModule, MatCardModule],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class SystemDemo {
+ /**
+ * Color roles grouped into categories for display. Each role group is
+ * rendered into a card showing the background colors for that role, with text
+ * labels written in the foreground colors for that role.
+ */
+ protected readonly colorGroups: RoleCategory[] = [
+ {
+ name: 'Primary',
+ roles: [
+ {
+ backgroundColors: ['primary'],
+ foregroundColors: ['on-primary'],
+ },
+ {
+ backgroundColors: ['primary-container'],
+ foregroundColors: ['on-primary-container'],
+ },
+ {
+ backgroundColors: ['primary-fixed', 'primary-fixed-dim'],
+ foregroundColors: ['on-primary-fixed', 'on-primary-fixed-variant'],
+ },
+ ],
+ },
+ {
+ name: 'Secondary',
+ roles: [
+ {
+ backgroundColors: ['secondary'],
+ foregroundColors: ['on-secondary'],
+ },
+ {
+ backgroundColors: ['secondary-container'],
+ foregroundColors: ['on-secondary-container'],
+ },
+ {
+ backgroundColors: ['secondary-fixed', 'secondary-fixed-dim'],
+ foregroundColors: ['on-secondary-fixed', 'on-secondary-fixed-variant'],
+ },
+ ],
+ },
+ {
+ name: 'Surface',
+ roles: [
+ {
+ backgroundColors: ['surface-bright', 'surface', 'surface-dim'],
+ foregroundColors: ['on-surface', 'on-surface-variant'],
+ },
+ {
+ backgroundColors: [
+ 'surface-container-lowest',
+ 'surface-container-low',
+ 'surface-container',
+ 'surface-container-high',
+ 'surface-container-highest',
+ ],
+ foregroundColors: ['on-surface', 'on-surface-variant'],
+ },
+ {
+ backgroundColors: ['inverse-surface'],
+ foregroundColors: ['inverse-on-surface', 'inverse-primary'],
+ },
+ ],
+ },
+ {
+ name: 'Utility',
+ roles: [
+ {
+ backgroundColors: ['error'],
+ foregroundColors: ['on-error'],
+ },
+ {
+ backgroundColors: ['error-container'],
+ foregroundColors: ['on-error-container'],
+ },
+ {
+ backgroundColors: ['outline', 'outline-variant', 'scrim', 'shadow'],
+ foregroundColors: [],
+ titleColorRole: 'on-primary',
+ },
+ ],
+ },
+ ];
+}
diff --git a/src/material/core/tokens/m2/_md-sys-color.scss b/src/material/core/tokens/m2/_md-sys-color.scss
index a4c37db77bc5..c6b6f61505ec 100644
--- a/src/material/core/tokens/m2/_md-sys-color.scss
+++ b/src/material/core/tokens/m2/_md-sys-color.scss
@@ -28,9 +28,9 @@
on-primary-container: map.get($palettes, primary, default-contrast),
on-primary-fixed: map.get($palettes, primary, default-contrast),
on-primary-fixed-variant: map.get($palettes, primary, default-contrast),
- on-secondary-container: map.get($palettes, accent, default),
- on-secondary-fixed: map.get($palettes, accent, default),
- on-secondary-fixed-variant: map.get($palettes, accent, default),
+ on-secondary-container: map.get($palettes, accent, default-contrast),
+ on-secondary-fixed: map.get($palettes, accent, default-contrast),
+ on-secondary-fixed-variant: map.get($palettes, accent, default-contrast),
on-tertiary: map.get($palettes, accent, default-contrast),
on-tertiary-container: map.get($palettes, accent, default-contrast),
on-tertiary-fixed: map.get($palettes, accent, default-contrast),
@@ -39,9 +39,9 @@
primary-fixed: map.get($palettes, primary, default),
primary-fixed-dim: map.get($palettes, primary, default),
scrim: black,
- secondary-container: map.get($palettes, accent, default-contrast),
- secondary-fixed: map.get($palettes, accent, default-contrast),
- secondary-fixed-dim: map.get($palettes, accent, default-contrast),
+ secondary-container: map.get($palettes, accent, default),
+ secondary-fixed: map.get($palettes, accent, default),
+ secondary-fixed-dim: map.get($palettes, accent, default),
surface-bright: map.get(palette.$grey-palette, 800),
surface-container: map.get(palette.$grey-palette, 800),
surface-container-high: map.get(palette.$grey-palette, 800),
@@ -84,9 +84,9 @@
on-primary-container: map.get($palettes, primary, default-contrast),
on-primary-fixed: map.get($palettes, primary, default-contrast),
on-primary-fixed-variant: map.get($palettes, primary, default-contrast),
- on-secondary-container: map.get($palettes, accent, default),
- on-secondary-fixed: map.get($palettes, accent, default),
- on-secondary-fixed-variant: map.get($palettes, accent, default),
+ on-secondary-container: map.get($palettes, accent, default-contrast),
+ on-secondary-fixed: map.get($palettes, accent, default-contrast),
+ on-secondary-fixed-variant: map.get($palettes, accent, default-contrast),
on-tertiary: map.get($palettes, accent, default-contrast),
on-tertiary-container: map.get($palettes, accent, default-contrast),
on-tertiary-fixed: map.get($palettes, accent, default-contrast),
@@ -95,17 +95,17 @@
primary-fixed: map.get($palettes, primary, default),
primary-fixed-dim: map.get($palettes, primary, default),
scrim: black,
- secondary-container: map.get($palettes, accent, default-contrast),
- secondary-fixed: map.get($palettes, accent, default-contrast),
- secondary-fixed-dim: map.get($palettes, accent, default-contrast),
- surface-bright: map.get(palette.$grey-palette, 800),
- surface-container: map.get(palette.$grey-palette, 800),
- surface-container-high: map.get(palette.$grey-palette, 800),
- surface-container-highest: map.get(palette.$grey-palette, 800),
- surface-container-low: map.get(palette.$grey-palette, 800),
- surface-container-lowest: map.get(palette.$grey-palette, 800),
- surface-dim: map.get(palette.$grey-palette, 800),
- surface-tint: map.get(palette.$grey-palette, 800),
+ secondary-container: map.get($palettes, accent, default),
+ secondary-fixed: map.get($palettes, accent, default),
+ secondary-fixed-dim: map.get($palettes, accent, default),
+ surface-bright: white,
+ surface-container: white,
+ surface-container-high: white,
+ surface-container-highest: white,
+ surface-container-low: white,
+ surface-container-lowest: white,
+ surface-dim: white,
+ surface-tint: white,
tertiary: map.get($palettes, accent, default),
tertiary-container: map.get($palettes, accent, default),
tertiary-fixed: map.get($palettes, accent, default),