diff --git a/src/components-examples/material/card/card-overview/card-overview-example.html b/src/components-examples/material/card/card-overview/card-overview-example.html
index 6805d4fb8214..e91eecb2db93 100644
--- a/src/components-examples/material/card/card-overview/card-overview-example.html
+++ b/src/components-examples/material/card/card-overview/card-overview-example.html
@@ -1,3 +1,11 @@
+
+ Elevated
+
+
- Simple card
+ Outlined
+
+
+ Filled
+
\ No newline at end of file
diff --git a/src/dev-app/card/BUILD.bazel b/src/dev-app/card/BUILD.bazel
index 28a377317c5d..b013cb719a60 100644
--- a/src/dev-app/card/BUILD.bazel
+++ b/src/dev-app/card/BUILD.bazel
@@ -12,7 +12,7 @@ ng_module(
deps = [
"//src/material/button",
"//src/material/card",
- "//src/material/checkbox",
+ "//src/material/radio",
],
)
diff --git a/src/dev-app/card/card-demo.html b/src/dev-app/card/card-demo.html
index 3ad6e6dd97a9..89f66ceca18b 100644
--- a/src/dev-app/card/card-demo.html
+++ b/src/dev-app/card/card-demo.html
@@ -1,5 +1,9 @@
- Use outlined cards
+
+ Raised
+ Outlined
+ Filled
+
diff --git a/src/dev-app/card/card-demo.scss b/src/dev-app/card/card-demo.scss
index 6038ba0385ae..945be0598362 100644
--- a/src/dev-app/card/card-demo.scss
+++ b/src/dev-app/card/card-demo.scss
@@ -16,3 +16,7 @@
text-transform: uppercase;
}
}
+
+mat-radio-group {
+ margin-bottom: 10px;
+}
diff --git a/src/dev-app/card/card-demo.ts b/src/dev-app/card/card-demo.ts
index 2dce2b2bb196..191463e12563 100644
--- a/src/dev-app/card/card-demo.ts
+++ b/src/dev-app/card/card-demo.ts
@@ -10,7 +10,7 @@ import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/co
import {FormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatCardAppearance, MatCardModule} from '@angular/material/card';
-import {MatCheckboxModule} from '@angular/material/checkbox';
+import {MatRadioModule} from '@angular/material/radio';
@Component({
selector: 'card-demo',
@@ -18,7 +18,7 @@ import {MatCheckboxModule} from '@angular/material/checkbox';
styleUrl: 'card-demo.css',
encapsulation: ViewEncapsulation.None,
standalone: true,
- imports: [MatCardModule, MatButtonModule, MatCheckboxModule, FormsModule],
+ imports: [MatCardModule, MatButtonModule, MatRadioModule, FormsModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CardDemo {
@@ -29,7 +29,4 @@ export class CardDemo {
As of some one gently rapping, rapping at my chamber door.
“’Tis some visitor,” I muttered, “tapping at my chamber door—
Only this and nothing more.”`;
- toggleAppearance() {
- this.appearance = this.appearance == 'raised' ? 'outlined' : 'raised';
- }
}
diff --git a/src/material/card/_card-theme.scss b/src/material/card/_card-theme.scss
index c8c4a7f59311..3fca8c52a651 100644
--- a/src/material/card/_card-theme.scss
+++ b/src/material/card/_card-theme.scss
@@ -8,6 +8,7 @@
@use '../core/tokens/m2/mat/card' as tokens-mat-card;
@use '../core/tokens/m2/mdc/elevated-card' as tokens-mdc-elevated-card;
@use '../core/tokens/m2/mdc/outlined-card' as tokens-mdc-outlined-card;
+@use '../core/tokens/m2/mdc/filled-card' as tokens-mdc-filled-card;
@mixin base($theme) {
@if inspection.get-theme-version($theme) == 1 {
@@ -22,6 +23,10 @@
tokens-mdc-outlined-card.$prefix,
tokens-mdc-outlined-card.get-unthemable-tokens()
);
+ @include token-utils.create-token-values(
+ tokens-mdc-filled-card.$prefix,
+ tokens-mdc-filled-card.get-unthemable-tokens()
+ );
@include token-utils.create-token-values(
tokens-mat-card.$prefix,
tokens-mat-card.get-unthemable-tokens()
@@ -43,6 +48,10 @@
tokens-mdc-outlined-card.$prefix,
tokens-mdc-outlined-card.get-color-tokens($theme)
);
+ @include token-utils.create-token-values(
+ tokens-mdc-filled-card.$prefix,
+ tokens-mdc-filled-card.get-color-tokens($theme)
+ );
@include token-utils.create-token-values(
tokens-mat-card.$prefix,
tokens-mat-card.get-color-tokens($theme)
@@ -64,6 +73,10 @@
tokens-mdc-outlined-card.$prefix,
tokens-mdc-outlined-card.get-typography-tokens($theme)
);
+ @include token-utils.create-token-values(
+ tokens-mdc-filled-card.$prefix,
+ tokens-mdc-filled-card.get-typography-tokens($theme)
+ );
@include token-utils.create-token-values(
tokens-mat-card.$prefix,
tokens-mat-card.get-typography-tokens($theme)
@@ -85,6 +98,10 @@
tokens-mdc-outlined-card.$prefix,
tokens-mdc-outlined-card.get-density-tokens($theme)
);
+ @include token-utils.create-token-values(
+ tokens-mdc-filled-card.$prefix,
+ tokens-mdc-filled-card.get-density-tokens($theme)
+ );
@include token-utils.create-token-values(
tokens-mat-card.$prefix,
tokens-mat-card.get-density-tokens($theme)
@@ -109,6 +126,11 @@
namespace: tokens-mdc-outlined-card.$prefix,
tokens: tokens-mdc-outlined-card.get-token-slots(),
prefix: 'outlined-',
+ ),
+ (
+ namespace: tokens-mdc-filled-card.$prefix,
+ tokens: tokens-mdc-filled-card.get-token-slots(),
+ prefix: 'filled-',
)
);
}
@@ -145,6 +167,10 @@
tokens-mdc-outlined-card.$prefix,
map.get($tokens, tokens-mdc-outlined-card.$prefix)
);
+ @include token-utils.create-token-values(
+ tokens-mdc-filled-card.$prefix,
+ map.get($tokens, tokens-mdc-filled-card.$prefix)
+ );
@include token-utils.create-token-values(
tokens-mat-card.$prefix,
map.get($tokens, tokens-mat-card.$prefix)
diff --git a/src/material/card/card.scss b/src/material/card/card.scss
index 21ae1ee38b42..032373d74a33 100644
--- a/src/material/card/card.scss
+++ b/src/material/card/card.scss
@@ -2,6 +2,7 @@
@use '../core/tokens/m2/mat/card' as tokens-mat-card;
@use '../core/tokens/m2/mdc/elevated-card' as tokens-mdc-elevated-card;
@use '../core/tokens/m2/mdc/outlined-card' as tokens-mdc-outlined-card;
+@use '../core/tokens/m2/mdc/filled-card' as tokens-mdc-filled-card;
// Size of the `mat-card-header` region custom to Angular Material.
$mat-card-header-size: 40px !default;
@@ -68,6 +69,17 @@ $mat-card-default-padding: 16px !default;
}
}
+.mat-mdc-card-filled {
+ @include token-utils.use-tokens(
+ tokens-mdc-filled-card.$prefix,
+ tokens-mdc-filled-card.get-token-slots()
+ ) {
+ @include token-utils.create-token-slot(background-color, container-color);
+ @include token-utils.create-token-slot(border-radius, container-shape);
+ @include token-utils.create-token-slot(box-shadow, container-elevation);
+ }
+}
+
.mdc-card__media {
position: relative;
box-sizing: border-box;
diff --git a/src/material/card/card.ts b/src/material/card/card.ts
index 2a9b89fb4765..7f03f437a333 100644
--- a/src/material/card/card.ts
+++ b/src/material/card/card.ts
@@ -16,7 +16,7 @@ import {
inject,
} from '@angular/core';
-export type MatCardAppearance = 'outlined' | 'raised';
+export type MatCardAppearance = 'outlined' | 'raised' | 'filled';
/** Object that can be used to configure the default options for the card module. */
export interface MatCardConfig {
@@ -41,6 +41,8 @@ export const MAT_CARD_CONFIG = new InjectionToken('MAT_CARD_CONFI
'class': 'mat-mdc-card mdc-card',
'[class.mat-mdc-card-outlined]': 'appearance === "outlined"',
'[class.mdc-card--outlined]': 'appearance === "outlined"',
+ '[class.mat-mdc-card-filled]': 'appearance === "filled"',
+ '[class.mdc-card--filled]': 'appearance === "filled"',
},
exportAs: 'matCard',
encapsulation: ViewEncapsulation.None,
diff --git a/src/material/core/tokens/m2/_index.scss b/src/material/core/tokens/m2/_index.scss
index 85c8c7195b50..9875b56cd44c 100644
--- a/src/material/core/tokens/m2/_index.scss
+++ b/src/material/core/tokens/m2/_index.scss
@@ -70,6 +70,7 @@
@use './mdc/switch' as tokens-mdc-switch;
@use './mdc/secondary-navigation-tab' as tokens-mdc-secondary-navigation-tab;
@use './mdc/tab-indicator' as tokens-mdc-tab-indicator;
+@use './mdc/filled-card' as tokens-mdc-filled-card;
@use '../../theming/inspection';
/// Gets the tokens for the given theme, m2 tokens module, and theming system.
@@ -182,6 +183,7 @@
_get-tokens-for-module($theme, tokens-mdc-switch),
_get-tokens-for-module($theme, tokens-mdc-tab-indicator),
_get-tokens-for-module($theme, tokens-mdc-secondary-navigation-tab),
- _get-tokens-for-module($theme, tokens-mdc-text-button)
+ _get-tokens-for-module($theme, tokens-mdc-text-button),
+ _get-tokens-for-module($theme, tokens-mdc-filled-card),
);
}
diff --git a/src/material/core/tokens/m2/mdc/_filled-card.scss b/src/material/core/tokens/m2/mdc/_filled-card.scss
new file mode 100644
index 000000000000..61579153466f
--- /dev/null
+++ b/src/material/core/tokens/m2/mdc/_filled-card.scss
@@ -0,0 +1,81 @@
+@use '../../../style/elevation';
+@use '../../../theming/inspection';
+@use '../../../style/sass-utils';
+@use '../../token-definition';
+
+// The prefix used to generate the fully qualified name for tokens in this file.
+$prefix: (mdc, filled-card);
+
+// Tokens that can't be configured through Angular Material's current theming API,
+// but may be in a future version of the theming API.
+//
+// Tokens that are available in MDC, but not used in Angular Material should be mapped to `null`.
+// `null` indicates that we are intentionally choosing not to emit a slot or value for the token in
+// our CSS.
+@function get-unthemable-tokens() {
+ @return (
+ // The border-radius of the card.
+ container-shape: 4px,
+ // =============================================================================================
+ // = TOKENS NOT USED IN ANGULAR MATERIAL =
+ // =============================================================================================
+ // Angular Material's card is not an interactive element, and therefore does not support states.
+ disabled-container-elevation: null,
+ disabled-outline-color: null,
+ disabled-outline-opacity: null,
+ dragged-container-elevation: null,
+ dragged-outline-color: null,
+ dragged-state-layer-color: null,
+ dragged-state-layer-opacity: null,
+ focus-container-elevation: null,
+ focus-outline-color: null,
+ focus-state-layer-color: null,
+ focus-state-layer-opacity: null,
+ hover-container-elevation: null,
+ hover-outline-color: null,
+ hover-state-layer-color: null,
+ hover-state-layer-opacity: null,
+ pressed-container-elevation: null,
+ pressed-outline-color: null,
+ pressed-state-layer-color: null,
+ pressed-state-layer-opacity: null,
+ container-shadow-color: null,
+ // Angular Material does not currently support surface tint.
+ container-surface-tint-layer-color: null,
+ // MDC does not seem to use these tokens.
+ icon-color: null,
+ icon-size: null,
+ );
+}
+
+// Tokens that can be configured through Angular Material's color theming API.
+@function get-color-tokens($theme) {
+ $elevation: inspection.get-theme-color($theme, foreground, elevation);
+
+ @return (
+ // The background color of the card.
+ container-color: inspection.get-theme-color($theme, background, card),
+ container-elevation: elevation.get-box-shadow(0),
+ );
+}
+
+// Tokens that can be configured through Angular Material's typography theming API.
+@function get-typography-tokens($theme) {
+ @return ();
+}
+
+// Tokens that can be configured through Angular Material's density theming API.
+@function get-density-tokens($theme) {
+ @return ();
+}
+
+// Combines the tokens generated by the above functions into a single map with placeholder values.
+// This is used to create token slots.
+@function get-token-slots() {
+ @return sass-utils.deep-merge-all(
+ get-unthemable-tokens(),
+ get-color-tokens(token-definition.$placeholder-color-config),
+ get-typography-tokens(token-definition.$placeholder-typography-config),
+ get-density-tokens(token-definition.$placeholder-density-config)
+ );
+}
diff --git a/src/material/core/tokens/m3/_index.scss b/src/material/core/tokens/m3/_index.scss
index 4d85b20f002a..4763e83b9467 100644
--- a/src/material/core/tokens/m3/_index.scss
+++ b/src/material/core/tokens/m3/_index.scss
@@ -68,6 +68,7 @@
@use './mdc/switch' as tokens-mdc-switch;
@use './mdc/secondary-navigation-tab' as tokens-mdc-secondary-navigation-tab;
@use './mdc/tab-indicator' as tokens-mdc-tab-indicator;
+@use './mdc/filled-card' as tokens-mdc-filled-card;
$_module-names: (
// Custom tokens
@@ -140,7 +141,8 @@ $_module-names: (
tokens-mdc-snack-bar,
tokens-mdc-switch,
tokens-mdc-secondary-navigation-tab,
- tokens-mdc-tab-indicator
+ tokens-mdc-tab-indicator,
+ tokens-mdc-filled-card,
);
/// Gets the full set of M3 tokens for the given theme object.
diff --git a/src/material/core/tokens/m3/mdc/_filled-card.scss b/src/material/core/tokens/m3/mdc/_filled-card.scss
new file mode 100644
index 000000000000..888b06d69d28
--- /dev/null
+++ b/src/material/core/tokens/m3/mdc/_filled-card.scss
@@ -0,0 +1,22 @@
+@use 'sass:map';
+@use '../../../style/elevation';
+@use '../../token-definition';
+
+// The prefix used to generate the fully qualified name for tokens in this file.
+$prefix: (mdc, filled-card);
+
+/// Generates the tokens for MDC filled-card
+/// @param {Map} $systems The MDC system tokens
+/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
+/// @param {Map} $token-slots Possible token slots
+/// @return {Map} A set of tokens for the MDC filled-card
+@function get-tokens($systems, $exclude-hardcoded, $token-slots) {
+ $tokens: token-definition.get-mdc-tokens('filled-card', $systems, $exclude-hardcoded);
+ $elevation: map.get($tokens, container-elevation);
+
+ @if ($elevation != null) {
+ $tokens: map.set($tokens, container-elevation, elevation.get-box-shadow($elevation));
+ }
+
+ @return token-definition.namespace-tokens($prefix, $tokens, $token-slots);
+}
diff --git a/tools/public_api_guard/material/card.md b/tools/public_api_guard/material/card.md
index 576c88722df2..4938d3c17587 100644
--- a/tools/public_api_guard/material/card.md
+++ b/tools/public_api_guard/material/card.md
@@ -33,7 +33,7 @@ export class MatCardActions {
}
// @public (undocumented)
-export type MatCardAppearance = 'outlined' | 'raised';
+export type MatCardAppearance = 'outlined' | 'raised' | 'filled';
// @public
export class MatCardAvatar {