diff --git a/src/material/core/BUILD.bazel b/src/material/core/BUILD.bazel
index 62aa5d436820..36ffe5386c3e 100644
--- a/src/material/core/BUILD.bazel
+++ b/src/material/core/BUILD.bazel
@@ -21,6 +21,7 @@ ng_module(
),
assets = [
":selection/pseudo-checkbox/pseudo-checkbox.css",
+ ":selection/pseudo-checkmark/pseudo-checkmark.css",
":option/option.css",
":option/optgroup.css",
] + glob(["**/*.html"]),
@@ -81,6 +82,12 @@ sass_binary(
deps = [":core_scss_lib"],
)
+sass_binary(
+ name = "pseudo_checkmark_scss",
+ src = "selection/pseudo-checkmark/pseudo-checkmark.scss",
+ deps = [":core_scss_lib"],
+)
+
sass_binary(
name = "option_scss",
src = "option/option.scss",
diff --git a/src/material/core/option/index.ts b/src/material/core/option/index.ts
index 96da5f1c97fc..ad285e9551c5 100644
--- a/src/material/core/option/index.ts
+++ b/src/material/core/option/index.ts
@@ -9,13 +9,19 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {MatRippleModule} from '../ripple/index';
-import {MatPseudoCheckboxModule} from '../selection/index';
+import {MatPseudoCheckboxModule, MatPseudoCheckmarkModule} from '../selection/index';
import {MatCommonModule} from '../common-behaviors/common-module';
import {MatOption} from './option';
import {MatOptgroup} from './optgroup';
@NgModule({
- imports: [MatRippleModule, CommonModule, MatCommonModule, MatPseudoCheckboxModule],
+ imports: [
+ MatRippleModule,
+ CommonModule,
+ MatCommonModule,
+ MatPseudoCheckboxModule,
+ MatPseudoCheckmarkModule,
+ ],
exports: [MatOption, MatOptgroup],
declarations: [MatOption, MatOptgroup],
})
diff --git a/src/material/core/option/option.html b/src/material/core/option/option.html
index cf0210e9cc04..757dcf5cb9a7 100644
--- a/src/material/core/option/option.html
+++ b/src/material/core/option/option.html
@@ -1,6 +1,9 @@
+
+
diff --git a/src/material/core/selection/index.ts b/src/material/core/selection/index.ts
index 102eaefd2bab..7dab94b643bd 100644
--- a/src/material/core/selection/index.ts
+++ b/src/material/core/selection/index.ts
@@ -8,3 +8,5 @@
export * from './pseudo-checkbox/pseudo-checkbox';
export * from './pseudo-checkbox/pseudo-checkbox-module';
+export * from './pseudo-checkmark/pseudo-checkmark';
+export * from './pseudo-checkmark/pseudo-checkmark-module';
diff --git a/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-common.scss b/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-common.scss
new file mode 100644
index 000000000000..4b526b2a4e53
--- /dev/null
+++ b/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-common.scss
@@ -0,0 +1,18 @@
+@use 'sass:math';
+@use '../../style/checkbox-common';
+
+// Padding inside of a pseudo checkmark.
+$padding: checkbox-common.$border-width * 2;
+
+/// Applies the styles that set the size of the pseudo checkmark
+@mixin size($box-size) {
+ .mat-pseudo-checkmark {
+ width: $box-size;
+ height: $box-size;
+ }
+}
+
+/// Applies the legacy size styles to the pseudo-checkmark
+@mixin legacy-size() {
+ @include size(check-common.$legacy-size);
+}
diff --git a/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-theme.import.scss b/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-theme.import.scss
new file mode 100644
index 000000000000..03f9a07e6b53
--- /dev/null
+++ b/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-theme.import.scss
@@ -0,0 +1,8 @@
+@forward '../../density/private/compatibility' as mat-*;
+@forward '../../theming/palette'; // TODO: hide unused colors
+@forward '../../theming/palette' as mat-*; // TODO: hide unused colors
+@forward '../../theming/theming' as mat-*;
+@import '../../theming/theming';
+@forward 'pseudo-checkmark-theme' hide color, theme, typography;
+@forward 'pseudo-checkmark-theme' as mat-pseudo-checkmark-* hide mat-pseudo-checkmark-density;
+
diff --git a/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-theme.scss b/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-theme.scss
new file mode 100644
index 000000000000..d58a8ea4a6ed
--- /dev/null
+++ b/src/material/core/selection/pseudo-checkmark/_pseudo-checkmark-theme.scss
@@ -0,0 +1,35 @@
+@use 'sass:map';
+@use '../../theming/theming';
+
+@mixin color($config-or-theme) {
+ $config: theming.get-color-config($config-or-theme);
+ $is-dark-theme: map.get($config, is-dark);
+ $primary: map.get($config, primary);
+ $accent: map.get($config, accent);
+ $warn: map.get($config, warn);
+
+ // TODO: implement colors
+}
+
+@mixin typography($config-or-theme) {}
+
+@mixin _density($config-or-theme) {}
+
+@mixin theme($theme-or-color-config) {
+ $theme: theming.private-legacy-get-theme($theme-or-color-config);
+ @include theming.private-check-duplicate-theme-styles($theme, 'mat-pseudo-checkmark') {
+ $color: theming.get-color-config($theme);
+ $density: theming.get-density-config($theme);
+ $typography: theming.get-typography-config($theme);
+
+ @if $color != null {
+ @include color($color);
+ }
+ @if $density != null {
+ @include _density($density);
+ }
+ @if $typography != null {
+ @include typography($typography);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/material/core/selection/pseudo-checkmark/pseudo-checkmark-module.ts b/src/material/core/selection/pseudo-checkmark/pseudo-checkmark-module.ts
new file mode 100644
index 000000000000..e91461a7396b
--- /dev/null
+++ b/src/material/core/selection/pseudo-checkmark/pseudo-checkmark-module.ts
@@ -0,0 +1,18 @@
+/**
+ * @license
+ * Copyright Google LLC All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {NgModule} from '@angular/core';
+import {MatPseudoCheckmark} from './pseudo-checkmark';
+import {MatCommonModule} from '../../common-behaviors/common-module';
+
+@NgModule({
+ imports: [MatCommonModule],
+ exports: [MatPseudoCheckmark],
+ declarations: [MatPseudoCheckmark],
+})
+export class MatPseudoCheckmarkModule {}
diff --git a/src/material/core/selection/pseudo-checkmark/pseudo-checkmark.scss b/src/material/core/selection/pseudo-checkmark/pseudo-checkmark.scss
new file mode 100644
index 000000000000..923c152742de
--- /dev/null
+++ b/src/material/core/selection/pseudo-checkmark/pseudo-checkmark.scss
@@ -0,0 +1,30 @@
+// TODO: implement styles
+@use 'sass:math';
+@use '../../style/checkbox-common';
+@use '../../style/private';
+@use '../../style/variables';
+@use './pseudo-checkmark-common';
+
+// TODO: implement a visual checkmark
+.mat-pseudo-checkmark {
+ display: inline-block;
+ box-sizing: border-box;
+ position: relative;
+ flex-shrink: 0;
+ &::after {
+ position: absolute;
+ opacity: 0;
+ font-family: monospace;
+ content: '✔️'; // TODO: draw a checkmark with CSS. this is jsut a placeholder
+ }
+
+ &.mat-pseudo-checkmark-checked::after {
+ opacity: 1;
+ }
+}
+
+.mat-pseudo-checkmark-disabled {
+ cursor: default;
+}
+
+@include pseudo-checkmark-common.size(checkbox-common.$size);
\ No newline at end of file
diff --git a/src/material/core/selection/pseudo-checkmark/pseudo-checkmark.ts b/src/material/core/selection/pseudo-checkmark/pseudo-checkmark.ts
new file mode 100644
index 000000000000..33d0613bd3c6
--- /dev/null
+++ b/src/material/core/selection/pseudo-checkmark/pseudo-checkmark.ts
@@ -0,0 +1,55 @@
+/**
+ * @license
+ * Copyright Google LLC All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {
+ Component,
+ ViewEncapsulation,
+ Input,
+ ChangeDetectionStrategy,
+ Inject,
+ Optional,
+} from '@angular/core';
+import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
+
+export type MatPseudoCheckmarkState = 'unchecked' | 'checked';
+
+/**
+ * Component that shows a simplified checkmark without including any kind of "real" checkmark.
+ * Meant to be used when the checkmark is purely decorative and a large number of them will be
+ * included, such as for the options in a single-select. Uses no SVGs or complex animations.
+ * Note that theming is meant to be handled by the parent element, e.g.
+ * `mat-primary .mat-pseudo-checkmark`.
+ *
+ * Note that this component will be completely invisible to screen-reader users. This is *not*
+ * interchangeable with `` and should *not* be used if the user would directly
+ * interact with the checkmark. The pseudo-checkmark should only be used as an implementation detail
+ * of more complex components that appropriately handle selected / checked state.
+ * @docs-private
+ */
+@Component({
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ selector: 'mat-pseudo-checkmark',
+ styleUrls: ['pseudo-checkmark.css'],
+ template: '',
+ host: {
+ 'class': 'mat-pseudo-checkmark',
+ '[class.mat-pseudo-checkmark-checked]': 'state === "checked"',
+ '[class.mat-pseudo-checkmark-disabled]': 'disabled',
+ '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
+ },
+})
+export class MatPseudoCheckmark {
+ /** Display state of the checkbox. */
+ @Input() state: MatPseudoCheckmarkState = 'unchecked';
+
+ /** Whether the checkbox is disabled. */
+ @Input() disabled: boolean = false;
+
+ constructor(@Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string) {}
+}
diff --git a/tools/public_api_guard/material/core.md b/tools/public_api_guard/material/core.md
index 16d072137fa9..f3895c8a5b79 100644
--- a/tools/public_api_guard/material/core.md
+++ b/tools/public_api_guard/material/core.md
@@ -312,7 +312,7 @@ export class MatOptionModule {
// (undocumented)
static ɵinj: i0.ɵɵInjectorDeclaration;
// (undocumented)
- static ɵmod: i0.ɵɵNgModuleDeclaration;
+ static ɵmod: i0.ɵɵNgModuleDeclaration;
}
// @public
@@ -360,6 +360,32 @@ export class MatPseudoCheckboxModule {
// @public
export type MatPseudoCheckboxState = 'unchecked' | 'checked' | 'indeterminate';
+// @public
+export class MatPseudoCheckmark {
+ constructor(_animationMode?: string | undefined);
+ // (undocumented)
+ _animationMode?: string | undefined;
+ disabled: boolean;
+ state: MatPseudoCheckmarkState;
+ // (undocumented)
+ static ɵcmp: i0.ɵɵComponentDeclaration;
+ // (undocumented)
+ static ɵfac: i0.ɵɵFactoryDeclaration;
+}
+
+// @public (undocumented)
+export class MatPseudoCheckmarkModule {
+ // (undocumented)
+ static ɵfac: i0.ɵɵFactoryDeclaration;
+ // (undocumented)
+ static ɵinj: i0.ɵɵInjectorDeclaration;
+ // (undocumented)
+ static ɵmod: i0.ɵɵNgModuleDeclaration;
+}
+
+// @public (undocumented)
+export type MatPseudoCheckmarkState = 'unchecked' | 'checked';
+
// @public (undocumented)
export class MatRipple implements OnInit, OnDestroy, RippleTarget {
constructor(_elementRef: ElementRef, ngZone: NgZone, platform: Platform, globalOptions?: RippleGlobalOptions, _animationMode?: string | undefined);