88 lines
3.4 KiB
HTML
88 lines
3.4 KiB
HTML
<mat-tab-header #tabHeader
|
|
[selectedIndex]="selectedIndex || 0"
|
|
[disableRipple]="disableRipple"
|
|
[disablePagination]="disablePagination"
|
|
[aria-label]="ariaLabel"
|
|
[aria-labelledby]="ariaLabelledby"
|
|
(indexFocused)="_focusChanged($event)"
|
|
(selectFocusedIndex)="selectedIndex = $event">
|
|
|
|
@for (tab of _tabs; track tab; let i = $index) {
|
|
<div class="mdc-tab mat-mdc-tab mat-focus-indicator"
|
|
#tabNode
|
|
role="tab"
|
|
matTabLabelWrapper
|
|
cdkMonitorElementFocus
|
|
[id]="_getTabLabelId(i)"
|
|
[attr.tabIndex]="_getTabIndex(i)"
|
|
[attr.aria-posinset]="i + 1"
|
|
[attr.aria-setsize]="_tabs.length"
|
|
[attr.aria-controls]="_getTabContentId(i)"
|
|
[attr.aria-selected]="selectedIndex === i"
|
|
[attr.aria-label]="tab.ariaLabel || null"
|
|
[attr.aria-labelledby]="(!tab.ariaLabel && tab.ariaLabelledby) ? tab.ariaLabelledby : null"
|
|
[class.mdc-tab--active]="selectedIndex === i"
|
|
[class]="tab.labelClass"
|
|
[disabled]="tab.disabled"
|
|
[fitInkBarToContent]="fitInkBarToContent"
|
|
(click)="_handleClick(tab, tabHeader, i)"
|
|
(cdkFocusChange)="_tabFocusChanged($event, i)">
|
|
<span class="mdc-tab__ripple"></span>
|
|
|
|
<!-- Needs to be a separate element, because we can't put
|
|
`overflow: hidden` on tab due to the ink bar. -->
|
|
<div
|
|
class="mat-mdc-tab-ripple"
|
|
mat-ripple
|
|
[matRippleTrigger]="tabNode"
|
|
[matRippleDisabled]="tab.disabled || disableRipple"></div>
|
|
|
|
<span class="mdc-tab__content">
|
|
<span class="mdc-tab__text-label">
|
|
<!--
|
|
If there is a label template, use it, otherwise fall back to the text label.
|
|
Note that we don't have indentation around the text label, because it adds
|
|
whitespace around the text which breaks some internal tests.
|
|
-->
|
|
@if (tab.templateLabel) {
|
|
<ng-template [cdkPortalOutlet]="tab.templateLabel"></ng-template>
|
|
} @else {{{tab.textLabel}}}
|
|
</span>
|
|
</span>
|
|
</div>
|
|
}
|
|
</mat-tab-header>
|
|
|
|
<!--
|
|
We need to project the content somewhere to avoid hydration errors. Some observations:
|
|
1. This is only necessary on the server.
|
|
2. We get a hydration error if there aren't any nodes after the `ng-content`.
|
|
3. We get a hydration error if `ng-content` is wrapped in another element.
|
|
-->
|
|
@if (_isServer) {
|
|
<ng-content/>
|
|
}
|
|
|
|
<div
|
|
class="mat-mdc-tab-body-wrapper"
|
|
[class._mat-animation-noopable]="_animationMode === 'NoopAnimations'"
|
|
#tabBodyWrapper>
|
|
@for (tab of _tabs; track tab; let i = $index) {
|
|
<mat-tab-body role="tabpanel"
|
|
[id]="_getTabContentId(i)"
|
|
[attr.tabindex]="(contentTabIndex != null && selectedIndex === i) ? contentTabIndex : null"
|
|
[attr.aria-labelledby]="_getTabLabelId(i)"
|
|
[attr.aria-hidden]="selectedIndex !== i"
|
|
[class.mat-mdc-tab-body-active]="selectedIndex === i"
|
|
[class]="tab.bodyClass"
|
|
[content]="tab.content!"
|
|
[position]="tab.position!"
|
|
[origin]="tab.origin"
|
|
[animationDuration]="animationDuration"
|
|
[preserveContent]="preserveContent"
|
|
(_onCentered)="_removeTabBodyWrapperHeight()"
|
|
(_onCentering)="_setTabBodyWrapperHeight($event)">
|
|
</mat-tab-body>
|
|
}
|
|
</div>
|