Skip to content

Commit c7efa56

Browse files
committed
feat(material/stepper): add a prefix section to the horizontal stepper header
Adds a prefix section to the header of the horizontal stepper header.
1 parent 7f56143 commit c7efa56

File tree

4 files changed

+78
-13
lines changed

4 files changed

+78
-13
lines changed

src/material/stepper/stepper.html

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,16 @@
1111
@switch (orientation) {
1212
@case ('horizontal') {
1313
<div class="mat-horizontal-stepper-wrapper">
14-
<div
15-
aria-orientation="horizontal"
16-
class="mat-horizontal-stepper-header-container"
17-
role="tablist">
18-
@for (step of steps; track step) {
19-
<ng-container
20-
[ngTemplateOutlet]="stepTemplate"
21-
[ngTemplateOutletContext]="{step}"/>
22-
@if (!$last) {
23-
<div class="mat-stepper-horizontal-line"></div>
24-
}
25-
}
26-
</div>
14+
@if (headerPrefix()) {
15+
<div class="mat-horizontal-stepper-header-wrapper">
16+
<ng-container [ngTemplateOutlet]="headerPrefix()"/>
17+
<ng-container [ngTemplateOutlet]="horizontalStepsTemplate"
18+
[ngTemplateOutletContext]="{steps}"/>
19+
</div>
20+
} @else {
21+
<ng-container [ngTemplateOutlet]="horizontalStepsTemplate"
22+
[ngTemplateOutletContext]="{steps}"/>
23+
}
2724

2825
<div class="mat-horizontal-content-container">
2926
@for (step of steps; track step) {
@@ -102,3 +99,19 @@
10299
[disableRipple]="disableRipple || !step.isNavigable()"
103100
[color]="step.color || color"/>
104101
</ng-template>
102+
103+
<ng-template #horizontalStepsTemplate let-steps="steps">
104+
<div
105+
aria-orientation="horizontal"
106+
class="mat-horizontal-stepper-header-container"
107+
role="tablist">
108+
@for (step of steps; track step) {
109+
<ng-container
110+
[ngTemplateOutlet]="stepTemplate"
111+
[ngTemplateOutletContext]="{step}"/>
112+
@if (!$last) {
113+
<div class="mat-stepper-horizontal-line"></div>
114+
}
115+
}
116+
</div>
117+
</ng-template>

src/material/stepper/stepper.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ $fallbacks: m3-stepper.get-tokens();
1919
background: token-utils.slot(stepper-container-color, $fallbacks);
2020
}
2121

22+
.mat-horizontal-stepper-header-wrapper {
23+
align-items: center;
24+
display: flex;
25+
}
26+
2227
.mat-horizontal-stepper-header-container {
2328
white-space: nowrap;
2429
display: flex;
2530
align-items: center;
31+
flex-grow: 1;
2632

2733
.mat-stepper-label-position-bottom & {
2834
align-items: flex-start;

src/material/stepper/stepper.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,27 @@ describe('MatStepper', () => {
15611561
expect(fixture.componentInstance.index).toBe(0);
15621562
});
15631563
});
1564+
1565+
describe('stepper with header prefix', () => {
1566+
it('should render the prefix content before the header', () => {
1567+
const fixture = createComponent(HorizontalStepperWithHeaderPrefix);
1568+
fixture.detectChanges();
1569+
1570+
const stepperHeaderWrapper = fixture.nativeElement.querySelector(
1571+
'.mat-horizontal-stepper-header-wrapper',
1572+
);
1573+
1574+
expect(stepperHeaderWrapper.children.length).toBe(2);
1575+
1576+
const stepperHeaderWrapperChildrenTags = Array.from(
1577+
stepperHeaderWrapper.children as HTMLElement[],
1578+
).map((child: HTMLElement) => child.tagName);
1579+
const stepperHeaderPrefix = stepperHeaderWrapper.children[0];
1580+
1581+
expect(stepperHeaderWrapperChildrenTags).toEqual(['H2', 'DIV']);
1582+
expect(stepperHeaderPrefix.textContent).toContain('This is a header prefix');
1583+
});
1584+
});
15641585
});
15651586

15661587
/** Asserts that keyboard interaction works correctly. */
@@ -2258,3 +2279,21 @@ class HorizontalStepperWithDelayedStep {
22582279
class StepperWithTwoWayBindingOnSelectedIndex {
22592280
index: number = 0;
22602281
}
2282+
2283+
@Component({
2284+
template: `
2285+
<mat-stepper [headerPrefix]="stepHeaderPrefix" linear>
2286+
<mat-step label="One"></mat-step>
2287+
<mat-step label="Two"></mat-step>
2288+
<mat-step label="Three"></mat-step>
2289+
</mat-stepper>
2290+
2291+
<ng-template #stepHeaderPrefix>
2292+
<h2>This is a header prefix</h2>
2293+
</ng-template>
2294+
`,
2295+
imports: [MatStepperModule],
2296+
})
2297+
class HorizontalStepperWithHeaderPrefix {
2298+
@ViewChild(MatStepper) stepper: MatStepper;
2299+
}

src/material/stepper/stepper.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
EventEmitter,
1919
inject,
2020
Input,
21+
input,
2122
NgZone,
2223
OnDestroy,
2324
Output,
@@ -187,6 +188,12 @@ export class MatStepper extends CdkStepper implements AfterViewInit, AfterConten
187188
@Input()
188189
headerPosition: 'top' | 'bottom' = 'top';
189190

191+
/**
192+
* The content prefix to use in the stepper header.
193+
* Only applies in the `horizontal` orientation.
194+
*/
195+
readonly headerPrefix = input<TemplateRef<unknown> | null>(null);
196+
190197
/** Consumer-specified template-refs to be used to override the header icons. */
191198
_iconOverrides: Record<string, TemplateRef<MatStepperIconContext>> = {};
192199

0 commit comments

Comments
 (0)