diff --git a/src/material/datepicker/calendar-body.html b/src/material/datepicker/calendar-body.html
index 98b63b03410a..101ca1c99e5a 100644
--- a/src/material/datepicker/calendar-body.html
+++ b/src/material/datepicker/calendar-body.html
@@ -90,3 +90,9 @@
{{endDateAccessibleName}}
+
+ {{comparisonDateAccessibleName}} {{startDateAccessibleName}}
+
+
+ {{comparisonDateAccessibleName}} {{endDateAccessibleName}}
+
diff --git a/src/material/datepicker/calendar-body.ts b/src/material/datepicker/calendar-body.ts
index 6e67911f0f1d..1a35b9774871 100644
--- a/src/material/datepicker/calendar-body.ts
+++ b/src/material/datepicker/calendar-body.ts
@@ -28,6 +28,7 @@ import {_IdGenerator} from '@angular/cdk/a11y';
import {NgClass} from '@angular/common';
import {_CdkPrivateStyleLoader} from '@angular/cdk/private';
import {_StructuralStylesLoader} from '@angular/material/core';
+import {MatDatepickerIntl} from './datepicker-intl';
/** Extra CSS classes that can be associated with a calendar cell. */
export type MatCalendarCellCssClasses = string | string[] | Set | {[key: string]: any};
@@ -99,6 +100,7 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterView
private _elementRef = inject>(ElementRef);
private _ngZone = inject(NgZone);
private _platform = inject(Platform);
+ private _intl = inject(MatDatepickerIntl);
/**
* Used to skip the next focus event when rendering the preview range.
@@ -204,6 +206,8 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterView
private _injector = inject(Injector);
+ comparisonDateAccessibleName = this._intl.comparisonDateLabel;
+
/**
* Tracking function for rows based on their identity. Ideally we would use some sort of
* key on the row, but that would require a breaking change for the `rows` input. We don't
@@ -467,6 +471,16 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterView
} else if (this.endValue === value) {
return this._endDateLabelId;
}
+
+ if (this.comparisonStart !== null && this.comparisonEnd !== null) {
+ if (value === this.comparisonStart && value === this.comparisonEnd) {
+ return `${this._comparisonStartLabelId}-${this._comparisonEndLabelId}`;
+ } else if (value === this.comparisonStart) {
+ return this._comparisonStartLabelId;
+ } else if (value === this.comparisonEnd) {
+ return this._comparisonEndLabelId;
+ }
+ }
return null;
}
@@ -607,6 +621,16 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterView
return null;
}
+
+ private _id = `mat-calendar-body-${calendarBodyId++}`;
+
+ _startDateLabelId = `${this._id}-start-date`;
+
+ _endDateLabelId = `${this._id}-end-date`;
+
+ _comparisonStartLabelId = `${this._id}-comparison-start-date`;
+
+ _comparisonEndLabelId = `${this._id}-comparison-end-date`;
}
/** Checks whether a node is a table cell element. */
diff --git a/src/material/datepicker/datepicker-intl.ts b/src/material/datepicker/datepicker-intl.ts
index a6b95dc93048..f1a448e1cfb5 100644
--- a/src/material/datepicker/datepicker-intl.ts
+++ b/src/material/datepicker/datepicker-intl.ts
@@ -65,6 +65,12 @@ export class MatDatepickerIntl {
*/
endDateLabel = 'End date';
+ /**
+ * A label used to indicate that the date is part of a selected comparison
+ * sub range of dates (used by screen readers).
+ */
+ comparisonDateLabel = 'Sub range';
+
/** Formats a range of years (used for visuals). */
formatYearRange(start: string, end: string): string {
return `${start} \u2013 ${end}`;