diff --git a/src/app/shared/doc-viewer/deprecated-tooltip.ts b/src/app/shared/doc-viewer/deprecated-tooltip.ts
new file mode 100644
index 00000000..489d6c46
--- /dev/null
+++ b/src/app/shared/doc-viewer/deprecated-tooltip.ts
@@ -0,0 +1,45 @@
+import {Component, Input} from '@angular/core';
+import {MatTooltipModule} from '@angular/material/tooltip';
+
+/**
+ * This component is responsible for showing the
+ * deprecated fields throughout API from material repo,
+ *
+ * When deprecated docs content is generated like:
+ *
+ *
+ * Deprecated
+ *
+ *
+ * It uses `title` attribute to show information regarding
+ * depreciation and other information regarding depreciation
+ * isnt shown either.
+ *
+ * We are gonna use this component to show deprecation
+ * information using the `material/tooltip`, the information
+ * would contain when the field is being deprecated and what
+ * are the alternatives to it which both are extracted from
+ * `deprecated` and `breaking-change`.
+ */
+@Component({
+ selector: 'deprecated-field',
+ template: `
+ {{ htmlContent }}
+
`,
+ standalone: true,
+ imports: [MatTooltipModule],
+})
+export class DeprecatedFieldComponent {
+ /** Message regarding the deprecation */
+ @Input() message!: string;
+ /** Inner content for our element, it could be either
+ * `Deprecated` which is shown mostly in most of the case
+ * but we can not show class names with just `Deprecated` label
+ * so otherwise the value is going to be name of whatever
+ * is being deprecated, so we can show the deprecation alternative
+ * description on hover */
+ @Input() htmlContent!: string;
+}
diff --git a/src/app/shared/doc-viewer/doc-viewer-module.ts b/src/app/shared/doc-viewer/doc-viewer-module.ts
index 9c3f51c0..36f5a9ad 100644
--- a/src/app/shared/doc-viewer/doc-viewer-module.ts
+++ b/src/app/shared/doc-viewer/doc-viewer-module.ts
@@ -9,6 +9,7 @@ import {PortalModule} from '@angular/cdk/portal';
import {NgModule} from '@angular/core';
import {HeaderLink} from './header-link';
import {CodeSnippet} from '../example-viewer/code-snippet';
+import {DeprecatedFieldComponent} from './deprecated-tooltip';
// ExampleViewer is included in the DocViewerModule because they have a circular dependency.
@@ -23,8 +24,9 @@ import {CodeSnippet} from '../example-viewer/code-snippet';
DocViewer,
ExampleViewer,
HeaderLink,
- CodeSnippet
+ CodeSnippet,
+ DeprecatedFieldComponent
],
- exports: [DocViewer, ExampleViewer, HeaderLink]
+ exports: [DocViewer, ExampleViewer, HeaderLink, DeprecatedFieldComponent]
})
export class DocViewerModule { }
diff --git a/src/app/shared/doc-viewer/doc-viewer.ts b/src/app/shared/doc-viewer/doc-viewer.ts
index 8690fad8..3dafc082 100644
--- a/src/app/shared/doc-viewer/doc-viewer.ts
+++ b/src/app/shared/doc-viewer/doc-viewer.ts
@@ -21,6 +21,7 @@ import {Observable, Subscription} from 'rxjs';
import {shareReplay, take, tap} from 'rxjs/operators';
import {ExampleViewer} from '../example-viewer/example-viewer';
import {HeaderLink} from './header-link';
+import {DeprecatedFieldComponent} from './deprecated-tooltip';
@Injectable({providedIn: 'root'})
class DocFetcher {
@@ -121,6 +122,9 @@ export class DocViewer implements OnDestroy {
this._loadComponents('material-docs-example', ExampleViewer);
this._loadComponents('header-link', HeaderLink);
+ // Create tooltips for the deprecated fields
+ this._createTooltipsForDeprecated();
+
// Resolving and creating components dynamically in Angular happens synchronously, but since
// we want to emit the output if the components are actually rendered completely, we wait
// until the Angular zone becomes stable.
@@ -166,4 +170,37 @@ export class DocViewer implements OnDestroy {
this._clearLiveExamples();
this._documentFetchSubscription?.unsubscribe();
}
+
+ _createTooltipsForDeprecated() {
+ // all of the deprecated markers end with `deprecated-marker`
+ // in their class name
+ const deprecatedElements =
+ this._elementRef.nativeElement.querySelectorAll(`[class$=deprecated-marker]`);
+
+ [...deprecatedElements].forEach((element: Element) => {
+ // the deprecation message, it will include alternative to deprecated item
+ // and breaking change if there is one included.
+ const deprecationTitle = element.getAttribute('depreciation-title');
+ // In case of a class being deprecated we can not just show `Deprecated`
+ // text, this attribute contains the text we need to show tooltip against.
+ const innerText = element.getAttribute('inner-text');
+
+ const elementPortalOutlet = new DomPortalOutlet(
+ element, this._componentFactoryResolver, this._appRef, this._injector);
+
+ const tooltipPortal = new ComponentPortal(DeprecatedFieldComponent, this._viewContainerRef);
+ const tooltipOutlet = elementPortalOutlet.attach(tooltipPortal);
+
+
+ if (deprecationTitle) {
+ tooltipOutlet.instance.message = deprecationTitle;
+ }
+
+ if (innerText) {
+ tooltipOutlet.instance.htmlContent = innerText;
+ }
+
+ this._portalHosts.push(elementPortalOutlet);
+ });
+ }
}
diff --git a/src/styles/_api.scss b/src/styles/_api.scss
index 0fa8b7e7..a088ce3f 100644
--- a/src/styles/_api.scss
+++ b/src/styles/_api.scss
@@ -101,12 +101,13 @@
display: inline-block;
font-weight: bold;
- &[title] {
+ & .deprecated-content {
border-bottom: 1px dotted grey;
cursor: help;
}
}
-.docs-api-deprecated-marker + .docs-api-property-name {
+.docs-api-deprecated-marker + .docs-api-property-name,
+.docs-api-class-deprecated-marker {
text-decoration: line-through;
}