--- /dev/null
+import { PageHeaderPageHelper } from './page-header.po';
+
+describe('Page header component', () => {
+ const pageHeader = new PageHeaderPageHelper();
+
+ beforeEach(() => {
+ cy.login();
+ pageHeader.navigateToCephfsMirroring();
+ });
+
+ it('should display the page header on CephFS Mirroring page', () => {
+ pageHeader.getPageHeader().should('be.visible');
+ });
+
+ it('should show the expected title in the page header', () => {
+ pageHeader.getHeaderTitle().then((text) => {
+ expect(text.trim()).to.equal('CephFS Mirroring');
+ });
+ });
+
+ it('should show the expected description in the page header', () => {
+ pageHeader.getHeaderDescription().then((text) => {
+ expect(text.trim()).to.equal('Centralised view of all CephFS Mirroring relationships.');
+ });
+ });
+});
--- /dev/null
+import { PageHelper } from '../page-helper.po';
+
+const pages = {
+ cephfsMirroring: { url: '#/cephfs/mirroring', id: 'cd-cephfs-mirroring-list' }
+};
+
+export class PageHeaderPageHelper extends PageHelper {
+ pages = pages;
+
+ navigateToCephfsMirroring() {
+ cy.visit(pages.cephfsMirroring.url);
+ cy.get(pages.cephfsMirroring.id, { timeout: 10000 });
+ }
+
+ getPageHeader() {
+ return cy.get('[data-testid="page-header"]');
+ }
+
+ getHeaderTitle() {
+ return this.getPageHeader().find('.cds--type-heading-04').invoke('text');
+ }
+
+ getHeaderDescription() {
+ return this.getPageHeader().find('.cds--type-body-01').invoke('text');
+ }
+}
+<cd-page-header
+ i18n-title
+ title="CephFS Mirroring"
+ i18n-description
+ description="Centralised view of all CephFS Mirroring relationships.">
+</cd-page-header>
+
<ng-container *ngIf="daemonStatus$ | async as daemonStatus">
<cd-table
[data]="daemonStatus"
import CloseIcon from '@carbon/icons/es/close/16';
import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.component';
import { ProductiveCardComponent } from './productive-card/productive-card.component';
+import { PageHeaderComponent } from './page-header/page-header.component';
@NgModule({
imports: [
ToastComponent,
TearsheetComponent,
TearsheetStepComponent,
- ProductiveCardComponent
+ ProductiveCardComponent,
+ PageHeaderComponent
],
providers: [provideCharts(withDefaultRegisterables())],
exports: [
ToastComponent,
TearsheetComponent,
TearsheetStepComponent,
- ProductiveCardComponent
+ ProductiveCardComponent,
+ PageHeaderComponent
]
})
export class ComponentsModule {
--- /dev/null
+<header data-testid="page-header">
+ <div>
+ <cds-tile class="border-top padding-inline-0">
+ <p class="cds--type-heading-04">{{ title }}</p>
+ @if(description) {
+ <p class="cds--type-body-01">{{ description }}</p>
+ }
+ </cds-tile>
+ </div>
+</header>
--- /dev/null
+@use '../../../../styles/vendor/variables' as vv;
+
+cd-page-header {
+ /* Extend to viewport edges so top border goes full width */
+ .border-top.padding-inline-0 {
+ margin-left: calc(-1 * vv.$grid-gutter-width);
+ margin-right: calc(-1 * vv.$grid-gutter-width);
+ width: calc(100% + 2 * vv.$grid-gutter-width);
+
+ /* Restore horizontal padding so content stays aligned with rest of page */
+ padding-inline: vv.$grid-gutter-width;
+ }
+
+ .border-top {
+ border-top: 1px solid var(--cds-border-subtle-01);
+ }
+}
--- /dev/null
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PageHeaderComponent } from './page-header.component';
+
+describe('PageHeaderComponent', () => {
+ let component: PageHeaderComponent;
+ let fixture: ComponentFixture<PageHeaderComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [PageHeaderComponent],
+ schemas: [NO_ERRORS_SCHEMA]
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(PageHeaderComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, Input, ViewEncapsulation } from '@angular/core';
+
+/**
+ * Page header component inspired by the Carbon Design System Page Header react component.
+ * @see https://ibm-products.carbondesignsystem.com/?path=/docs/components-pageheader--overview
+ *
+ * Usage:
+ * <cd-page-header title="Page title" description="Optional description">
+ * </cd-page-header>
+ */
+@Component({
+ selector: 'cd-page-header',
+ templateUrl: './page-header.component.html',
+ styleUrls: ['./page-header.component.scss'],
+ encapsulation: ViewEncapsulation.None,
+ standalone: false
+})
+export class PageHeaderComponent {
+ @Input({ required: true }) title: string;
+ @Input() description: string = '';
+}