+
+
+
+ `,
+ props: { ...args },
+});
+
+export const Tabs: StoryObj = {
+ render: tabsTemplate,
+};
+
+export const VerticalTabs: StoryObj = {
+ render: tabsTemplate,
+ args: {
+ tabsActionsPosition: 'left',
+ clrLayout: TabsLayout.VERTICAL,
+ },
+};
+
+export const TabsResponsive: StoryObj = {
+ render: tabsTemplate,
+ parameters: {
+ viewport: {
+ defaultViewport: 'large',
+ },
+ },
+};
+
+export const TabsActionsLeft: StoryObj = {
+ render: tabsTemplate,
+ args: {
+ tabsActionsPosition: 'left',
+ },
+};
diff --git a/projects/angular/clarity.api.md b/projects/angular/clarity.api.md
index 90ebcdbe62..c4c1b358c9 100644
--- a/projects/angular/clarity.api.md
+++ b/projects/angular/clarity.api.md
@@ -96,9 +96,9 @@ export class ClarityModule {
// Warning: (ae-forgotten-export) The symbol "i8_6" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i9_2" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i10_4" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "i11_4" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i11_3" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i12_3" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "i13_3" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i13_4" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i14_2" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i15_2" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i16_2" needs to be exported by the entry point index.d.ts
@@ -106,7 +106,7 @@ export class ClarityModule {
// Warning: (ae-forgotten-export) The symbol "i18_2" needs to be exported by the entry point index.d.ts
//
// (undocumented)
- static ɵmod: i0.ɵɵNgModuleDeclaration;
+ static ɵmod: i0.ɵɵNgModuleDeclaration;
}
// @public (undocumented)
@@ -3886,10 +3886,10 @@ export class ClrStepperModule {
// Warning: (ae-forgotten-export) The symbol "i3_27" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i4_18" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i5_14" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "i8_8" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i8_9" needs to be exported by the entry point index.d.ts
//
// (undocumented)
- static ɵmod: i0.ɵɵNgModuleDeclaration;
+ static ɵmod: i0.ɵɵNgModuleDeclaration;
}
// @public (undocumented)
@@ -3953,6 +3953,14 @@ export class ClrTab {
static ɵfac: i0.ɵɵFactoryDeclaration;
}
+// @public (undocumented)
+export class ClrTabAction {
+ // (undocumented)
+ static ɵdir: i0.ɵɵDirectiveDeclaration;
+ // (undocumented)
+ static ɵfac: i0.ɵɵFactoryDeclaration;
+}
+
// @public (undocumented)
export class ClrTabContent implements OnDestroy {
constructor(ifActiveService: IfActiveService, id: number, tabsService: TabsService);
@@ -4065,6 +4073,8 @@ export class ClrTabs implements AfterContentInit, OnDestroy {
// (undocumented)
set tabOverflowEl(value: ElementRef);
// (undocumented)
+ tabsActions: QueryList;
+ // (undocumented)
tabsId: number;
// (undocumented)
tabsService: TabsService;
@@ -4075,11 +4085,24 @@ export class ClrTabs implements AfterContentInit, OnDestroy {
// (undocumented)
toggleService: ClrPopoverToggleService;
// (undocumented)
- static ɵcmp: i0.ɵɵComponentDeclaration;
+ static ɵcmp: i0.ɵɵComponentDeclaration;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration;
}
+// @public (undocumented)
+export class ClrTabsActions {
+ // (undocumented)
+ position: ClrTabsActionsPosition;
+ // (undocumented)
+ static ɵcmp: i0.ɵɵComponentDeclaration;
+ // (undocumented)
+ static ɵfac: i0.ɵɵFactoryDeclaration;
+}
+
+// @public (undocumented)
+export type ClrTabsActionsPosition = 'left' | 'right';
+
// @public (undocumented)
export class ClrTabsModule {
constructor();
@@ -4094,10 +4117,12 @@ export class ClrTabsModule {
// Warning: (ae-forgotten-export) The symbol "i5_11" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i6_8" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i7_7" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "i11_3" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i8_7" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i9_6" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i13_3" needs to be exported by the entry point index.d.ts
//
// (undocumented)
- static ɵmod: i0.ɵɵNgModuleDeclaration;
+ static ɵmod: i0.ɵɵNgModuleDeclaration;
}
// @public (undocumented)
@@ -4683,13 +4708,13 @@ export class ClrWizardModule {
// Warning: (ae-forgotten-export) The symbol "i5_13" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i6_9" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i7_8" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "i8_7" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "i9_6" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i8_8" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i9_7" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i10_5" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "i11_5" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "i11_4" needs to be exported by the entry point index.d.ts
//
// (undocumented)
- static ɵmod: i0.ɵɵNgModuleDeclaration;
+ static ɵmod: i0.ɵɵNgModuleDeclaration;
}
// @public
diff --git a/projects/angular/src/layout/tabs/_tabs.clarity.scss b/projects/angular/src/layout/tabs/_tabs.clarity.scss
index 3ea34ea79f..c7b722ffcc 100644
--- a/projects/angular/src/layout/tabs/_tabs.clarity.scss
+++ b/projects/angular/src/layout/tabs/_tabs.clarity.scss
@@ -46,101 +46,112 @@
[data-hidden='true'] {
display: none;
}
-}
-
-button.nav-link {
- border-radius: 0;
- text-transform: capitalize;
- min-width: 0;
-}
+ button.nav-link {
+ border-radius: 0;
+ text-transform: capitalize;
+ min-width: 0;
+ }
-.tabs-overflow {
- position: relative;
+ .tabs-overflow {
+ position: relative;
- .nav-item {
- margin-right: 0;
+ .nav-item {
+ margin-right: 0;
+ }
}
-}
-.tab-content {
- display: inline;
-}
-
-@include mixins.fixForIE11AndUp {
.tab-content {
- display: inline-block;
- width: 100%;
+ display: inline;
}
-}
-.tabs-vertical {
- display: flex;
-
- // Must be direct child, so horizontal tabs can be nested in vertical tabs
- & > .nav {
- height: auto;
- box-shadow: none;
- flex-direction: column;
- align-items: stretch;
- margin-right: variables.$clr_baselineRem_1;
- overflow: auto;
- flex-shrink: 0;
- padding: variables.$clr_baselineRem_4px;
- width: variables.$clr_baselineRem_10;
- min-width: variables.$clr_baselineRem_2;
-
- @include mixins.css-var(gap, clr-nav-vertical-gap-size, 0, variables.$clr-use-custom-properties);
-
- // ATM - remove
- .nav-item {
- @include mixins.css-var(
- margin-right,
- clr-nav-item-margin-right,
- variables.$clr_baselineRem_1,
- variables.$clr-use-custom-properties
- );
+ @include mixins.fixForIE11AndUp {
+ .tab-content {
+ display: inline-block;
+ width: 100%;
}
+ }
- .nav-link {
- text-align: left;
- @include mixins.css-var(
- padding,
- clr-nav-vertical-link-padding,
- 0 variables.$clr_baselineRem_0_5,
- variables.$clr-use-custom-properties
- );
- border: none;
+ .tabs-vertical {
+ display: flex;
+
+ // Must be direct child, so horizontal tabs can be nested in vertical tabs
+ & > .nav {
+ height: auto;
+ box-shadow: none;
+ flex-direction: column;
+ align-items: stretch;
+ margin-right: variables.$clr_baselineRem_1;
+ overflow: auto;
flex-shrink: 0;
- margin-top: 0;
- margin-left: 0;
- width: 100%;
+ padding: variables.$clr_baselineRem_4px;
+ width: variables.$clr_baselineRem_10;
+ min-width: variables.$clr_baselineRem_2;
- // ATM - remove
- &.btn {
- margin-bottom: variables.$clr_baselineRem_1px;
- }
+ @include mixins.css-var(gap, clr-nav-vertical-gap-size, 0, variables.$clr-use-custom-properties);
- &.active,
- &:hover {
- @include nav-link-border-appearence('left');
- }
- &:not(:active).active {
+ // ATM - remove
+ .nav-item {
@include mixins.css-var(
- background-color,
- clr-nav-selected-bg-color,
- variables.$clr-global-selection-color,
+ margin-right,
+ clr-nav-item-margin-right,
+ variables.$clr_baselineRem_1,
variables.$clr-use-custom-properties
);
}
- &:not(.active):hover {
+ .nav-link {
+ text-align: left;
@include mixins.css-var(
- background-color,
- clr-nav-hover-bg-color,
- tabs-variables.$clr-nav-hover-bg-color,
+ padding,
+ clr-nav-vertical-link-padding,
+ 0 variables.$clr_baselineRem_0_5,
variables.$clr-use-custom-properties
);
+ border: none;
+ flex-shrink: 0;
+ margin-top: 0;
+ margin-left: 0;
+ width: 100%;
+
+ // ATM - remove
+ &.btn {
+ margin-bottom: variables.$clr_baselineRem_1px;
+ }
+
+ &.active,
+ &:hover {
+ @include nav-link-border-appearence('left');
+ }
+ &:not(:active).active {
+ @include mixins.css-var(
+ background-color,
+ clr-nav-selected-bg-color,
+ variables.$clr-global-selection-color,
+ variables.$clr-use-custom-properties
+ );
+ }
+
+ &:not(.active):hover {
+ @include mixins.css-var(
+ background-color,
+ clr-nav-hover-bg-color,
+ tabs-variables.$clr-nav-hover-bg-color,
+ variables.$clr-use-custom-properties
+ );
+ }
}
}
}
+
+ .tabs-actions {
+ display: inline-flex;
+ width: 100%;
+
+ &[position~='left'] {
+ justify-content: start;
+ }
+ &[position~='right'] {
+ justify-content: end;
+ }
+ }
}
diff --git a/projects/angular/src/layout/tabs/index.ts b/projects/angular/src/layout/tabs/index.ts
index 4ace03ce07..9dc6b5946f 100644
--- a/projects/angular/src/layout/tabs/index.ts
+++ b/projects/angular/src/layout/tabs/index.ts
@@ -6,10 +6,12 @@
*/
export * from './tabs';
+export * from './tabs-actions';
export * from './tab';
export * from './tab-content';
export * from './tab-overflow-content';
export * from './tab-link.directive';
+export * from './tab-action.directive';
export * from './tabs.module';
export { TabsWillyWonka as ÇlrTabsWillyWonka } from './chocolate/tabs-willy-wonka';
diff --git a/projects/angular/src/layout/tabs/tab-action.directive.spec.ts b/projects/angular/src/layout/tabs/tab-action.directive.spec.ts
new file mode 100644
index 0000000000..684b55980e
--- /dev/null
+++ b/projects/angular/src/layout/tabs/tab-action.directive.spec.ts
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016-2024 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+ * This software is released under MIT license.
+ * The full license information can be found in LICENSE in the root directory of this project.
+ */
+
+import { Component, ElementRef, QueryList, ViewChildren } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ClrTabAction } from './tab-action.directive';
+import { ClrTabsModule } from './tabs.module';
+
+@Component({
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+ `,
+})
+class TestComponent {
+ @ViewChildren(ClrTabAction, { read: ElementRef }) tabsActions: QueryList;
+}
+
+describe('TabAction Directive', () => {
+ let fixture: ComponentFixture;
+ let instance: any;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [ClrTabsModule],
+ declarations: [TestComponent],
+ providers: [],
+ });
+
+ fixture = TestBed.createComponent(TestComponent);
+ fixture.detectChanges();
+ instance = fixture.componentInstance;
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ });
+
+ it('has the correct tabIndex value', () => {
+ const tabsActions: QueryList = instance.tabsActions;
+ expect(tabsActions.length).toBe(1);
+ expect(tabsActions.get(0).nativeElement.tabIndex).toBe(0);
+ });
+});
diff --git a/projects/angular/src/layout/tabs/tab-action.directive.ts b/projects/angular/src/layout/tabs/tab-action.directive.ts
new file mode 100644
index 0000000000..bd24511b15
--- /dev/null
+++ b/projects/angular/src/layout/tabs/tab-action.directive.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2016-2024 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+ * This software is released under MIT license.
+ * The full license information can be found in LICENSE in the root directory of this project.
+ */
+
+import { Directive } from '@angular/core';
+
+@Directive({
+ selector: '[clrTabAction]',
+ host: {
+ tabindex: '0',
+ },
+})
+export class ClrTabAction {}
diff --git a/projects/angular/src/layout/tabs/tabs-actions.spec.ts b/projects/angular/src/layout/tabs/tabs-actions.spec.ts
new file mode 100644
index 0000000000..e839e06621
--- /dev/null
+++ b/projects/angular/src/layout/tabs/tabs-actions.spec.ts
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016-2024 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+ * This software is released under MIT license.
+ * The full license information can be found in LICENSE in the root directory of this project.
+ */
+
+import { Component } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+
+import { ClrTabsActions } from './tabs-actions';
+import { ClrTabsModule } from './tabs.module';
+
+@Component({
+ template: `Hello world`,
+})
+class TestComponent {}
+
+describe('TabsActions', () => {
+ let fixture: ComponentFixture;
+ let compiled: any;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [ClrTabsModule],
+ declarations: [TestComponent],
+ providers: [],
+ });
+ fixture = TestBed.createComponent(TestComponent);
+ compiled = fixture.nativeElement;
+ fixture.detectChanges();
+ });
+
+ it('projects content', () => {
+ expect(compiled.textContent.trim()).toMatch('Hello world');
+ });
+
+ it('adds a .tabs-actions class on the host element', () => {
+ const tabsActionsElement = fixture.debugElement.query(By.directive(ClrTabsActions)).nativeElement;
+ expect(tabsActionsElement.classList.contains('tabs-actions')).toBe(true);
+ });
+});
diff --git a/projects/angular/src/layout/tabs/tabs-actions.ts b/projects/angular/src/layout/tabs/tabs-actions.ts
new file mode 100644
index 0000000000..431dc93c06
--- /dev/null
+++ b/projects/angular/src/layout/tabs/tabs-actions.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016-2024 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+ * This software is released under MIT license.
+ * The full license information can be found in LICENSE in the root directory of this project.
+ */
+
+import { Component, HostBinding, Input } from '@angular/core';
+
+export type ClrTabsActionsPosition = 'left' | 'right';
+
+@Component({
+ selector: 'clr-tabs-actions',
+ template: `
+
+
+
+ `,
+ host: {
+ '[class.tabs-actions]': 'true',
+ },
+})
+export class ClrTabsActions {
+ @Input()
+ @HostBinding('attr.position')
+ position: ClrTabsActionsPosition = 'right';
+}
diff --git a/projects/angular/src/layout/tabs/tabs.module.ts b/projects/angular/src/layout/tabs/tabs.module.ts
index ec9125c971..b95d8254fa 100644
--- a/projects/angular/src/layout/tabs/tabs.module.ts
+++ b/projects/angular/src/layout/tabs/tabs.module.ts
@@ -16,10 +16,12 @@ import { ClrTemplateRefModule } from '../../utils/template-ref/template-ref.modu
import { ActiveOompaLoompa } from './chocolate/active-oompa-loompa';
import { TabsWillyWonka } from './chocolate/tabs-willy-wonka';
import { ClrTab } from './tab';
+import { ClrTabAction } from './tab-action.directive';
import { ClrTabContent } from './tab-content';
import { ClrTabLink } from './tab-link.directive';
import { ClrTabOverflowContent } from './tab-overflow-content';
import { ClrTabs } from './tabs';
+import { ClrTabsActions } from './tabs-actions';
export const CLR_TABS_DIRECTIVES: Type[] = [
ClrTabContent,
@@ -27,6 +29,8 @@ export const CLR_TABS_DIRECTIVES: Type[] = [
ClrTabs,
ClrTabOverflowContent,
ClrTabLink,
+ ClrTabAction,
+ ClrTabsActions,
TabsWillyWonka,
ActiveOompaLoompa,
];
diff --git a/projects/angular/src/layout/tabs/tabs.ts b/projects/angular/src/layout/tabs/tabs.ts
index d5bbc0a1bb..7f9195e243 100644
--- a/projects/angular/src/layout/tabs/tabs.ts
+++ b/projects/angular/src/layout/tabs/tabs.ts
@@ -29,6 +29,7 @@ import { ClrPopoverToggleService } from '../../utils/popover/providers/popover-t
import { TabsLayout } from './enums/tabs-layout.enum';
import { TabsService } from './providers/tabs.service';
import { ClrTab } from './tab';
+import { ClrTabAction } from './tab-action.directive';
import { ClrTabLink } from './tab-link.directive';
import { ClrTabOverflowContent } from './tab-overflow-content';
import { TABS_ID, TABS_ID_PROVIDER } from './tabs-id.provider';
@@ -91,6 +92,7 @@ import { TABS_ID, TABS_ID_PROVIDER } from './tabs-id.provider';
+
`,
@@ -106,6 +108,7 @@ export class ClrTabs implements AfterContentInit, OnDestroy {
@ViewChild(ClrKeyFocus, { static: true }) keyFocus: ClrKeyFocus;
+ @ContentChildren(ClrTabAction, { read: ElementRef, descendants: true }) tabsActions: QueryList;
@ContentChildren(ClrTab) private tabs: QueryList;
private subscriptions: Subscription[] = [];
@@ -178,6 +181,7 @@ export class ClrTabs implements AfterContentInit, OnDestroy {
ngAfterContentInit() {
this.subscriptions.push(this.listenForTabLinkChanges());
+ this.subscriptions.push(this.listedForTabsActionsChanges());
if (typeof this.ifActiveService.current === 'undefined' && this.tabLinkDirectives[0]) {
this.tabLinkDirectives[0].activate();
@@ -252,7 +256,14 @@ export class ClrTabs implements AfterContentInit, OnDestroy {
// This is because we have another handler on the tabOverflowTrigger element itself.
// As this handler method is on the document level so the event bubbles up to it and conflicts
// with the tabOverflowTrigger handler resulting in opening the tab overflow and closing it right away consecutively.
- if (event.target === tabOverflowTrigger || tabOverflowTrigger.contains(event.target as HTMLElement)) {
+ const isTabsAction = this.tabsActions.some(action =>
+ (action.nativeElement as HTMLElement).contains(event.target as HTMLElement)
+ );
+ if (
+ event.target === tabOverflowTrigger ||
+ tabOverflowTrigger.contains(event.target as HTMLElement) ||
+ isTabsAction
+ ) {
return;
}
@@ -262,10 +273,21 @@ export class ClrTabs implements AfterContentInit, OnDestroy {
}
}
+ private setTabLinkElements() {
+ this._tabLinkDirectives = this.tabs.map(tab => tab.tabLink);
+ this.tabLinkElements = this._tabLinkDirectives.map(tab => tab.el.nativeElement);
+ if (this.tabsActions && this.tabsActions) {
+ this.tabLinkElements.push(...this.tabsActions.map(action => action.nativeElement));
+ }
+ }
+
private listenForTabLinkChanges() {
- return this.tabs.changes.pipe(startWith(this.tabs.map(tab => tab.tabLink))).subscribe(() => {
- this._tabLinkDirectives = this.tabs.map(tab => tab.tabLink);
- this.tabLinkElements = this._tabLinkDirectives.map(tab => tab.el.nativeElement);
- });
+ return this.tabs.changes
+ .pipe(startWith(this.tabs.map(tab => tab.tabLink)))
+ .subscribe(() => this.setTabLinkElements());
+ }
+
+ private listedForTabsActionsChanges() {
+ return this.tabsActions.changes.subscribe(() => this.setTabLinkElements());
}
}
diff --git a/projects/demo/src/app/tabs/tabs-actions-angular.demo.html b/projects/demo/src/app/tabs/tabs-actions-angular.demo.html
new file mode 100644
index 0000000000..b7c28fa997
--- /dev/null
+++ b/projects/demo/src/app/tabs/tabs-actions-angular.demo.html
@@ -0,0 +1,85 @@
+
+
+
+
Action after the last tab
+
+
+
+
+
+
+
+
+
+
+
{{ tab.content }}
+
+
+
+
+
Action at the end
+
+
+
+
+
+
+
+
{{ tab.content }}
+
+
+
+
+
Vertical Action at the end
+
+
+
+
+
+
+
+
{{ tab.content }}
+
+
+
+
+
With overflow tabs
+
+
+
+
+
+
+
+
{{ tab.content }}
+
+
+
+
+
diff --git a/projects/demo/src/app/tabs/tabs-actions-angular.ts b/projects/demo/src/app/tabs/tabs-actions-angular.ts
new file mode 100644
index 0000000000..17c1c1efd8
--- /dev/null
+++ b/projects/demo/src/app/tabs/tabs-actions-angular.ts
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016-2024 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+ * This software is released under MIT license.
+ * The full license information can be found in LICENSE in the root directory of this project.
+ */
+
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'clr-modal-tabs-actions-angular',
+ styleUrls: ['./tabs.demo.scss'],
+ templateUrl: './tabs-actions-angular.demo.html',
+})
+export class TabsActionsAngularDemo {
+ layout = 'vertical';
+ inOverflow = false;
+ tabs = [
+ {
+ title: 'Dashboard',
+ content: `Content for Dashboard tab. Here is a link that can be accessed via clicking or
+ through keyboard via tabbing.`,
+ },
+ {
+ title: 'Management',
+ content: 'Content for Management tab.',
+ },
+ ];
+
+ addTab() {
+ this.tabs.push({
+ title: `Inserted Tab ${this.tabs.length + 1}`,
+ content: `Content for Inserted Tab ${this.tabs.length + 1}`,
+ });
+ }
+
+ removeTab(index) {
+ this.tabs.splice(index, 1);
+ }
+}
diff --git a/projects/demo/src/app/tabs/tabs.demo.html b/projects/demo/src/app/tabs/tabs.demo.html
index 7f4ca29b61..b46dfb88f9 100644
--- a/projects/demo/src/app/tabs/tabs.demo.html
+++ b/projects/demo/src/app/tabs/tabs.demo.html
@@ -10,6 +10,7 @@