Skip to content

Commit 71d5907

Browse files
authored
feat(material/sort): add content projection slot for custom icon (#32016)
Adds the `matSortHeaderIcon` content projection slot that users can use to customize the sorting icon. Fixes #32002.
1 parent dfbdec0 commit 71d5907

File tree

8 files changed

+49
-6
lines changed

8 files changed

+49
-6
lines changed

goldens/material/sort/index.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI
113113
start: SortDirection;
114114
_toggleOnInteraction(): void;
115115
// (undocumented)
116-
static ɵcmp: i0.ɵɵComponentDeclaration<MatSortHeader, "[mat-sort-header]", ["matSortHeader"], { "id": { "alias": "mat-sort-header"; "required": false; }; "arrowPosition": { "alias": "arrowPosition"; "required": false; }; "start": { "alias": "start"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "sortActionDescription": { "alias": "sortActionDescription"; "required": false; }; "disableClear": { "alias": "disableClear"; "required": false; }; }, {}, never, ["*"], true, never>;
116+
static ɵcmp: i0.ɵɵComponentDeclaration<MatSortHeader, "[mat-sort-header]", ["matSortHeader"], { "id": { "alias": "mat-sort-header"; "required": false; }; "arrowPosition": { "alias": "arrowPosition"; "required": false; }; "start": { "alias": "start"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "sortActionDescription": { "alias": "sortActionDescription"; "required": false; }; "disableClear": { "alias": "disableClear"; "required": false; }; }, {}, never, ["*", "[matSortHeaderIcon]"], true, never>;
117117
// (undocumented)
118118
static ɵfac: i0.ɵɵFactoryDeclaration<MatSortHeader, never>;
119119
}

src/components-examples/material/sort/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ ng_project(
1818
"//:node_modules/@types/jasmine",
1919
"//src/cdk/testing",
2020
"//src/cdk/testing/testbed",
21+
"//src/material/icon",
2122
"//src/material/sort",
2223
"//src/material/sort/testing",
2324
],
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export {SortOverviewExample} from './sort-overview/sort-overview-example';
22
export {SortHarnessExample} from './sort-harness/sort-harness-example';
3+
export {SortCustomIconExample} from './sort-custom-icon/sort-custom-icon-example';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<table matSort matSortActive="emoji" matSortDirection="asc">
2+
<tr>
3+
<th mat-sort-header="emoji">
4+
Emoji icon
5+
<span matSortHeaderIcon>⬆️</span>
6+
</th>
7+
<th mat-sort-header="material">
8+
Material Icon
9+
<mat-icon matSortHeaderIcon>keyboard_arrow_up</mat-icon>
10+
</th>
11+
</tr>
12+
13+
<tbody>
14+
<tr>
15+
<td>Lorem, ipsum dolor sit amet.</td>
16+
<td>Lorem, ipsum dolor sit amet.</td>
17+
</tr>
18+
</tbody>
19+
</table>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {Component} from '@angular/core';
2+
import {MatIcon} from '@angular/material/icon';
3+
import {MatSortModule} from '@angular/material/sort';
4+
5+
/**
6+
* @title Sort header with a custom icon
7+
*/
8+
@Component({
9+
selector: 'sort-custom-icon-example',
10+
templateUrl: 'sort-custom-icon-example.html',
11+
imports: [MatSortModule, MatIcon],
12+
})
13+
export class SortCustomIconExample {}

src/material/sort/sort-header.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@
3232
<!-- Disable animations while a current animation is running -->
3333
@if (_renderArrow()) {
3434
<div class="mat-sort-header-arrow">
35-
<svg viewBox="0 -960 960 960" focusable="false" aria-hidden="true">
36-
<path d="M440-240v-368L296-464l-56-56 240-240 240 240-56 56-144-144v368h-80Z"/>
37-
</svg>
35+
<ng-content select="[matSortHeaderIcon]">
36+
<svg viewBox="0 -960 960 960" focusable="false" aria-hidden="true">
37+
<path d="M440-240v-368L296-464l-56-56 240-240 240 240-56 56-144-144v368h-80Z"/>
38+
</svg>
39+
</ng-content>
3840
</div>
3941
}
4042
</div>

src/material/sort/sort-header.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ $fallbacks: m3-sort.get-tokens();
114114
animation-duration: 0ms;
115115
}
116116

117-
svg {
117+
> svg, [matSortHeaderIcon] {
118118
// Even though this is 24x24, the actual `path` inside ends up being 12x12.
119119
width: 24px;
120120
height: 24px;

src/material/sort/sort.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ by default it will use the id of the column.
3939

4040
<!-- example(table-sorting) -->
4141

42+
#### Customizing the icon
43+
44+
You can set your own icon for a `mat-sort-header` by projecting in an element with the
45+
`matSortHeaderIcon` attribute.
46+
47+
<!-- example(sort-custom-icon) -->
48+
4249
### Accessibility
4350

4451
When you apply `MatSortHeader` to a header cell element, the component wraps the content of the
@@ -55,4 +62,4 @@ remedy this, use the `matSortChange` event on the `MatSort` directive to announc
5562
updates with the `LiveAnnouncer` service from `@angular/cdk/a11y`.
5663

5764
If your application contains many tables and sort headers, consider creating a custom
58-
directives to consistently apply `sortActionDescription` and announce sort state changes.
65+
directives to consistently apply `sortActionDescription` and announce sort state changes.

0 commit comments

Comments
 (0)