src/components/sq-tabs/sq-tabs.component.ts
Represents a tab container component for managing a collection of tabs.
Look the link about the component in original framework and the appearance
See https://css.squidit.com.br/components/tabs
Example :<sq-tabs [lineStyle]="true" (tabChange)="handleTabChange($event)">
<sq-tab [title]="'Tab 1'" (whenOpen)="handleTabOpen()">Tab 1 Content</sq-tab>
<sq-tab [title]="'Tab 2'">Tab 2 Content</sq-tab>
<!-- Add more sq-tab elements as needed -->
</sq-tabs>
AfterViewInit
AfterViewChecked
changeDetection | ChangeDetectionStrategy.OnPush |
selector | sq-tabs |
styleUrls | ./sq-tabs.component.scss |
templateUrl | ./sq-tabs.component.html |
Properties |
Methods |
Inputs |
Outputs |
constructor(cdr: ChangeDetectorRef)
|
||||||||
Constructor for the SqTabs class.
Parameters :
|
customClass | |
Type : string
|
|
Default value : ''
|
|
Custom CSS class for the input element. |
height | |
Type : string
|
|
The height of the tab container. |
hideHtmlForInactives | |
Type : boolean
|
|
Default value : false
|
|
Flag to hide html for inactive tabs. |
lineStyle | |
Type : boolean
|
|
Default value : false
|
|
Flag to indicate whether to display a line-style indicator for the selected tab. |
margin | |
Type : string
|
|
Default value : '0 auto'
|
|
The margin of the tab container. |
maxWidth | |
Type : string
|
|
Default value : 'initial'
|
|
The maximum width of the tab container. |
sm | |
Type : boolean
|
|
Default value : true
|
|
Flag to indicate to use sm class com tabs header. |
tabWidth | |
Type : string
|
|
Default value : ''
|
|
The width of the tab container. |
tabChange | |
Type : EventEmitter<literal type>
|
|
Event emitted when a tab is changed. |
ngAfterViewChecked |
ngAfterViewChecked()
|
Lifecycle hook called after the view has been checked.
Returns :
void
|
Async ngAfterViewInit |
ngAfterViewInit()
|
Lifecycle hook called after the view initialization.
Returns :
any
|
selectTab | ||||||||||||
selectTab(tab: SqTabComponent, index: number)
|
||||||||||||
Selects a tab by making it active.
Parameters :
Returns :
any
|
tabs |
Type : QueryList<SqTabComponent>
|
Default value : [] as unknown as QueryList<SqTabComponent>
|
Decorators :
@ContentChildren(SqTabComponent)
|
A query list of |
tabsPosition |
Type : string
|
Default value : 'initial'
|
The initial position of the tabs. |
total |
Type : number
|
Default value : 1
|
The total number of tabs in the container. |
import { AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, EventEmitter, Input, Output, QueryList } from '@angular/core'
import { useMemo } from '../../helpers/memo.helper'
import { sleep } from '../../helpers/sleep.helper'
import { SqTabComponent } from './sq-tab/sq-tab.component'
/**
* Represents a tab container component for managing a collection of tabs.
*
* Look the link about the component in original framework and the appearance
*
* @see {@link https://css.squidit.com.br/components/tabs}
*
* @example
* <sq-tabs [lineStyle]="true" (tabChange)="handleTabChange($event)">
* <sq-tab [title]="'Tab 1'" (whenOpen)="handleTabOpen()">Tab 1 Content</sq-tab>
* <sq-tab [title]="'Tab 2'">Tab 2 Content</sq-tab>
* <!-- Add more sq-tab elements as needed -->
* </sq-tabs>
*
* @implements {AfterViewInit}
* @implements {AfterViewChecked}
*/
@Component({
selector: 'sq-tabs',
templateUrl: './sq-tabs.component.html',
styleUrls: ['./sq-tabs.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SqTabsComponent implements AfterViewInit, AfterViewChecked {
/**
* A query list of `SqTabComponent` elements representing the tabs.
*/
@ContentChildren(SqTabComponent) tabs: QueryList<SqTabComponent> = [] as unknown as QueryList<SqTabComponent>
/**
* Custom CSS class for the input element.
*/
@Input() customClass = ''
/**
* The height of the tab container.
*/
@Input() height?: string
/**
* The maximum width of the tab container.
*/
@Input() maxWidth = 'initial'
/**
* The margin of the tab container.
*/
@Input() margin = '0 auto'
/**
* Flag to indicate whether to display a line-style indicator for the selected tab.
*/
@Input() lineStyle = false
/**
* The width of the tab container.
*/
@Input() tabWidth = ''
/**
* Flag to indicate to use sm class com tabs header.
*/
@Input() sm = true
/**
* Flag to hide html for inactive tabs.
*/
@Input() hideHtmlForInactives = false
/**
* Event emitted when a tab is changed.
*/
@Output() tabChange: EventEmitter<{ tab: SqTabComponent; index: number }> = new EventEmitter()
/**
* The total number of tabs in the container.
*/
total = 1
/**
* The initial position of the tabs.
*/
tabsPosition = 'initial'
/**
* Constructor for the SqTabs class.
* @param cdr - The change detector reference.
*/
constructor(private cdr: ChangeDetectorRef) {}
/**
* Lifecycle hook called after the view initialization.
*/
async ngAfterViewInit() {
const activeTab = {
tab: this.tabs.find((tab) => tab.active),
index: this.tabs.toArray().findIndex((tab) => tab.active),
}
await sleep(1000)
if (activeTab.tab?.title) {
this.selectTab(activeTab.tab, activeTab.index)
} else if (this.tabs.first) {
this.selectTab(this.tabs.first, 0)
}
this.total = this.tabs.toArray().length || 1
}
/**
* Lifecycle hook called after the view has been checked.
*/
ngAfterViewChecked(): void {
if (this.tabs.toArray().length !== this.total) {
this.total = this.tabs.toArray().length || 1
}
}
/**
* Selects a tab by making it active.
*
* @param {SqTabComponent} tab - The tab to be selected.
* @param {number} index - The index of the selected tab.
*/
selectTab(tab: SqTabComponent, index: number) {
if (tab?.disabled || tab?.loading) {
return null
}
this.tabs.toArray().forEach((tabItem) => (tabItem.active = false))
if (tab) {
this.tabChange.emit({
tab,
index,
})
tab.active = true
tab.hideHtml = false
if (tab.whenOpen) {
tab.whenOpen.emit()
}
}
if (this.hideHtmlForInactives) {
this.tabs.toArray().forEach((tabItem) => {
if (!tabItem.active) {
tabItem.hideHtml = true
}
})
}
this.cdr.detectChanges()
return null
}
/**
* Determines the tab width based on the provided conditions.
*
* @param {string} tabWidth - The width of the tab.
* @param {boolean} lineStyle - A flag to determine if line style is applied.
*
* @returns {string} - Returns 'fit-content' if lineStyle is true.
* Returns the provided tabWidth if it exists.
* Otherwise, returns 'initial'.
*/
memoizedTabWidth = useMemo((tabWidth: string, lineStyle: boolean): string => {
if (tabWidth) {
return tabWidth
}
if (lineStyle) {
return 'fit-content'
}
return 'initial'
})
}
<div class="tabs-squid">
<div class="tabs-container">
<div
class="wrapper {{ customClass }}"
[ngStyle]="{
'width': memoizedTabWidth(tabWidth, lineStyle),
}"
>
<ul
class="tabs-header tabs-center tabs-width"
#tabsHeaderContainer
[ngClass]="{
'line-style': lineStyle
}"
[ngStyle]="{
'max-width': maxWidth,
margin: margin
}"
>
<li
*ngFor="let tab of tabs; let i = index"
(click)="!tab?.disabled ? selectTab(tab, i) : null"
[ngClass]="{
disabled: !tab?.title || tab?.disabled,
loading: tab?.title && tab.loading,
active: tab?.active,
sm: sm
}"
[ngStyle]="{
background: tab?.active && !lineStyle ? tab?.color : null
}"
#thisTab
>
<span
*ngIf="!tab.loading"
[ngStyle]="{
color: tab?.active && !lineStyle ? tab?.textColor : null
}"
[innerHtml]="tab?.title || '' | universalSafe"
></span>
<sq-loader *ngIf="tab.loading"></sq-loader>
</li>
</ul>
</div>
</div>
<ng-content></ng-content>
</div>
./sq-tabs.component.scss
:host {
display: block;
width: 100%;
.wrapper {
position: relative;
justify-content: center;
display: flex;
align-items: center;
}
.tabs-header {
position: relative;
scroll-behavior: smooth;
background: var(--transparent);
li {
min-width: min-content;
}
}
}