diff --git a/docs/src/app/pages/component-viewer/component-overview.html b/docs/src/app/pages/component-viewer/component-overview.html index 1404d543d260..715e4e126a72 100644 --- a/docs/src/app/pages/component-viewer/component-overview.html +++ b/docs/src/app/pages/component-viewer/component-overview.html @@ -2,9 +2,10 @@

Overview for {{docItem.id}}

- + @if (showToc | async) { diff --git a/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.css b/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.css new file mode 100644 index 000000000000..024ce71a26d8 --- /dev/null +++ b/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.css @@ -0,0 +1,43 @@ +.docs-angular-aria-banner { + display: flex; + align-items: flex-start; + gap: 12px; + padding: 16px; + margin-bottom: 24px; + background-color: color-mix(in srgb, var(--mat-sys-primary) 10%, transparent); + border-left: 4px solid var(--mat-sys-primary); + border-radius: 4px; + font-size: 14px; + line-height: 1.6; +} + +.docs-angular-aria-banner-icon { + font-size: 20px; + flex-shrink: 0; + fill: var(--mat-sys-primary); +} + +.docs-angular-aria-banner-content { + flex: 1; +} + +.docs-angular-aria-banner-content strong { + color: var(--mat-sys-primary); +} + +.docs-angular-aria-banner-content a { + color: var(--mat-sys-primary); + text-decoration: underline; + font-weight: 500; +} + +@media (max-width: 600px) { + .docs-angular-aria-banner { + padding: 12px; + gap: 8px; + } + + .docs-angular-aria-banner-icon { + font-size: 18px; + } +} diff --git a/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.html b/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.html new file mode 100644 index 000000000000..888cf5700406 --- /dev/null +++ b/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.html @@ -0,0 +1,16 @@ +
+ + + + +
+ Now Available in Angular Aria! +
+ The Angular team has introduced a new low-level component library called Angular Aria. + Consider using the + Angular Aria {{ componentName }} + component as an alternative to this CDK component. +
+
diff --git a/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.ts b/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.ts new file mode 100644 index 000000000000..cb4741730a83 --- /dev/null +++ b/docs/src/app/shared/doc-viewer/angular-aria-banner/angular-aria-banner.ts @@ -0,0 +1,36 @@ +/** + * @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.dev/license + */ + +import {Component, Input} from '@angular/core'; + +/** + * Mapping of CDK component names to their Angular Aria documentation URLs. + */ +const ANGULAR_ARIA_LINKS: Record = { + 'listbox': 'https://angular.dev/guide/aria/listbox', + 'tree': 'https://angular.dev/guide/aria/tree', + 'accordion': 'https://angular.dev/guide/aria/accordion', + 'menu': 'https://angular.dev/guide/aria/menu', +}; + +/** + * Banner component that guides users to use the new Angular Aria components for CDK components + * that have equivalent Angular Aria components. + */ +@Component({ + selector: 'angular-aria-banner', + templateUrl: 'angular-aria-banner.html', + styleUrl: 'angular-aria-banner.css', +}) +export class AngularAriaBanner { + @Input() componentName: string = ''; + + get ariaLink(): string { + return ANGULAR_ARIA_LINKS[this.componentName.toLowerCase()] || ''; + } +} diff --git a/docs/src/app/shared/doc-viewer/doc-viewer.ts b/docs/src/app/shared/doc-viewer/doc-viewer.ts index 93eb369c1227..aba8ca165325 100644 --- a/docs/src/app/shared/doc-viewer/doc-viewer.ts +++ b/docs/src/app/shared/doc-viewer/doc-viewer.ts @@ -38,6 +38,7 @@ import {ExampleViewer} from '../example-viewer/example-viewer'; import {HeaderLink} from './header-link'; import {DeprecatedFieldComponent} from './deprecated-tooltip'; import {ModuleImportCopyButton} from './module-import-copy-button'; +import {AngularAriaBanner} from './angular-aria-banner/angular-aria-banner'; @Injectable({providedIn: 'root'}) class DocFetcher { @@ -154,6 +155,9 @@ export class DocViewer implements OnDestroy { this._loadComponents('material-docs-example', ExampleViewer); this._loadComponents('header-link', HeaderLink); + // Inject Angular Aria banner for specific CDK components + this._injectAngularAriaBanner(); + // Create tooltips for the deprecated fields this._createTooltipsForDeprecated(); @@ -267,4 +271,37 @@ export class DocViewer implements OnDestroy { this._portalHosts.push(elementPortalOutlet); }); } + + /** + * Injects the Angular Aria migration banner for specific CDK components. + */ + private _injectAngularAriaBanner() { + const componentName = this.name(); + const componentsWithAriaBanner = ['listbox', 'tree', 'accordion', 'menu']; + + if (!componentName || !componentsWithAriaBanner.includes(componentName.toLowerCase())) { + return; + } + + // Create a container div for the banner at the beginning of the document + const bannerContainer = document.createElement('div'); + bannerContainer.setAttribute('angular-aria-banner', ''); + bannerContainer.setAttribute('componentName', componentName); + + // Insert the banner at the beginning of the document content + const firstChild = this._elementRef.nativeElement.firstChild; + if (firstChild) { + this._elementRef.nativeElement.insertBefore(bannerContainer, firstChild); + } else { + this._elementRef.nativeElement.appendChild(bannerContainer); + } + + // Create and attach the banner component + const portalHost = new DomPortalOutlet(bannerContainer, this._appRef, this._injector); + const bannerPortal = new ComponentPortal(AngularAriaBanner, this._viewContainerRef); + const bannerComponent = portalHost.attach(bannerPortal); + bannerComponent.instance.componentName = componentName; + + this._portalHosts.push(portalHost); + } }