From 2b8194d5232a7bf6f697d730111240b356faed87 Mon Sep 17 00:00:00 2001 From: Ruslan Lekhman Date: Thu, 8 Oct 2026 01:48:27 -0600 Subject: [PATCH] fix(material/sort): show start direction as hover hint on unsorted headers The hover hint arrow on an unsorted header used the table's active sort direction instead of the direction the header would sort in when clicked (its start direction). close #33933 Signed-off-by: Ruslan Lekhman --- goldens/material/sort/index.api.md | 1 + src/material/sort/sort-header.html | 4 ++-- src/material/sort/sort-header.ts | 9 +++++++++ src/material/sort/sort.spec.ts | 30 ++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/goldens/material/sort/index.api.md b/goldens/material/sort/index.api.md index 78aaf8ae73d4..e12711d38ed4 100644 --- a/goldens/material/sort/index.api.md +++ b/goldens/material/sort/index.api.md @@ -73,6 +73,7 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI disableClear: boolean; disabled: boolean; _getAriaSortAttribute(): "ascending" | "descending" | "none"; + _getArrowDirection(): SortDirection; // (undocumented) _handleKeydown(event: KeyboardEvent): void; id: string; diff --git a/src/material/sort/sort-header.html b/src/material/sort/sort-header.html index 9cc1c26493a7..090dd526326a 100644 --- a/src/material/sort/sort-header.html +++ b/src/material/sort/sort-header.html @@ -11,8 +11,8 @@
{ expect(sortHeaderElement.getAttribute('aria-sort')).toBe('none'); }); + it('should show the start direction as hint for unsorted headers', () => { + // Sort defaultA descending so the table's active direction is `desc`. + component.sort('defaultA'); + component.sort('defaultA'); + fixture.detectChanges(); + expect(component.matSort.active).toBe('defaultA'); + expect(component.matSort.direction).toBe('desc'); + + // Sorted header follows the active direction. + const sortedContainer = fixture.nativeElement.querySelector( + '#defaultA .mat-sort-header-container', + ); + expect(sortedContainer.classList.contains('mat-sort-header-descending')).toBe(true); + expect(sortedContainer.classList.contains('mat-sort-header-ascending')).toBe(false); + + // Unsorted header with default start (`asc`) hints `asc`, not the table's `desc`. + const unsortedContainer = fixture.nativeElement.querySelector( + '#defaultB .mat-sort-header-container', + ); + expect(unsortedContainer.classList.contains('mat-sort-header-ascending')).toBe(true); + expect(unsortedContainer.classList.contains('mat-sort-header-descending')).toBe(false); + + // Unsorted header with `start="desc"` hints `desc`. + const descStartContainer = fixture.nativeElement.querySelector( + '#overrideStart .mat-sort-header-container', + ); + expect(descStartContainer.classList.contains('mat-sort-header-descending')).toBe(true); + expect(descStartContainer.classList.contains('mat-sort-header-ascending')).toBe(false); + }); + it('should not render the arrow if sorting is disabled for that column', async () => { const sortHeaderElement = fixture.nativeElement.querySelector('#defaultA');