diff --git a/packages/components-dev/tabs/module.ts b/packages/components-dev/tabs/module.ts
index fb2093ed0..8a72ef877 100644
--- a/packages/components-dev/tabs/module.ts
+++ b/packages/components-dev/tabs/module.ts
@@ -3,15 +3,23 @@ import { KbqButtonModule } from '@koobiq/components/button';
import { KbqIconModule } from '@koobiq/components/icon';
import { KbqPopoverModule } from '@koobiq/components/popover';
import { KbqTabChangeEvent, KbqTabsModule } from '@koobiq/components/tabs';
-import { TabsVerticalExample } from 'packages/docs-examples/components/tabs';
+import {
+ TabsAddTabExample,
+ TabsAddTabVerticalExample,
+ TabsVerticalExample
+} from 'packages/docs-examples/components/tabs';
import { DevThemeToggle } from '../theme-toggle';
@Component({
selector: 'dev-examples',
- imports: [TabsVerticalExample],
+ imports: [TabsVerticalExample, TabsAddTabExample, TabsAddTabVerticalExample],
template: `
+
+
+
+
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
diff --git a/packages/components/tabs/tabs.en.md b/packages/components/tabs/tabs.en.md
index 899895396..298aba1da 100644
--- a/packages/components/tabs/tabs.en.md
+++ b/packages/components/tabs/tabs.en.md
@@ -64,6 +64,16 @@ Unlike `KbqTabGroup`, `KbqTabNavBar` is used for navigation between application
+### Creating tabs
+
+Create and delete tabs like in a browser. The create button is located at the end of the list of tabs. When there is scrolling, the button moves to the right to remain visible.
+
+
+
+Vertical tabs
+
+
+
### Hot keys
| Key | Action |
diff --git a/packages/components/tabs/tabs.ru.md b/packages/components/tabs/tabs.ru.md
index 0747c798d..c86847254 100644
--- a/packages/components/tabs/tabs.ru.md
+++ b/packages/components/tabs/tabs.ru.md
@@ -64,6 +64,16 @@
+### Создание вкладок
+
+Создание и удаление как в браузере. Кнопка создания располагается в конце списка вкладок. Когда есть прокрутка, то кнопка перемещается направо, чтобы всегда оставаться видимой.
+
+
+
+Вертикальные вкладки
+
+
+
### Работа с клавиатурой
| Клавиша | Действие |
diff --git a/packages/docs-examples/components/tabs/index.ts b/packages/docs-examples/components/tabs/index.ts
index b23db0b57..bdafd5f69 100644
--- a/packages/docs-examples/components/tabs/index.ts
+++ b/packages/docs-examples/components/tabs/index.ts
@@ -2,6 +2,8 @@ import { NgModule } from '@angular/core';
import { TabsActionbarExample } from './tabs-actionbar/tabs-actionbar-example';
import { TabsActiveTabIdExample } from './tabs-active-tab-id/tabs-active-tab-id-example';
import { TabsActiveTabIndexExample } from './tabs-active-tab-index/tabs-active-tab-index-example';
+import { TabsAddTabVerticalExample } from './tabs-add-tab-vertical/tabs-add-tab-vertical-example';
+import { TabsAddTabExample } from './tabs-add-tab/tabs-add-tab-example';
import { TabsCustomLabelExample } from './tabs-custom-label/tabs-custom-label-example';
import { TabsDisabledExample } from './tabs-disabled/tabs-disabled-example';
import { TabsEmptyLabelExample } from './tabs-empty-label/tabs-empty-label-example';
@@ -18,6 +20,8 @@ export {
TabsActionbarExample,
TabsActiveTabIdExample,
TabsActiveTabIndexExample,
+ TabsAddTabExample,
+ TabsAddTabVerticalExample,
TabsCustomLabelExample,
TabsDisabledExample,
TabsEmptyLabelExample,
@@ -35,6 +39,8 @@ const EXAMPLES = [
TabsActiveTabIdExample,
TabsActiveTabIndexExample,
TabsActionbarExample,
+ TabsAddTabExample,
+ TabsAddTabVerticalExample,
TabsCustomLabelExample,
TabsDisabledExample,
TabsEmptyLabelExample,
diff --git a/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.css b/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.css
new file mode 100644
index 000000000..c44556b5a
--- /dev/null
+++ b/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.css
@@ -0,0 +1,37 @@
+:host {
+ display: flex;
+ width: 100%;
+ max-width: 100%;
+ height: 250px;
+ --tab-nav-selected: var(--kbq-tabs-tab-item-filled-on-background-states-selected-background);
+}
+
+.example-tab-nav-bar {
+ width: 240px;
+}
+
+.example-tab-link {
+ display: inline-block;
+ text-align: left;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.example-tab-close {
+ position: absolute;
+ right: calc(var(--kbq-tabs-size-tab-item-padding-horizontal) - var(--kbq-tabs-size-tab-item-focus-outline-width));
+ top: 0;
+ bottom: 0;
+ width: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ background: linear-gradient(var(--tab-nav-selected), var(--tab-nav-selected)), var(--kbq-background-bg);
+ mask-image: linear-gradient(to right, transparent 0%, black 50%);
+}
+
+.example-tabs-add-tab-vertical__content {
+ flex: 1;
+ padding: var(--kbq-size-m);
+ overflow: auto;
+}
diff --git a/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.ts b/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.ts
new file mode 100644
index 000000000..d7eeefc86
--- /dev/null
+++ b/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.ts
@@ -0,0 +1,61 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { KbqButtonModule } from '@koobiq/components/button';
+import { KbqIconModule } from '@koobiq/components/icon';
+import { KbqTabsModule } from '@koobiq/components/tabs';
+
+/**
+ * @title Tabs add tab vertical
+ */
+@Component({
+ selector: 'tabs-add-tab-vertical-example',
+ imports: [KbqTabsModule, KbqButtonModule, KbqIconModule],
+ template: `
+
+
+
+ Content for {{ activeTab }}
+
+ `,
+ styleUrls: ['./tabs-add-tab-vertical-example.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class TabsAddTabVerticalExample {
+ protected tabs = ['BruteForce', 'Complex Attack', 'DDoS', 'HIPS alert'];
+ protected activeTab = this.tabs[0];
+
+ protected addTab(): void {
+ const newTab = `Tab ${this.tabs.length + 1}`;
+
+ this.tabs = [...this.tabs, newTab];
+ this.activeTab = newTab;
+ }
+
+ protected removeTab(tab: string, event: MouseEvent): void {
+ event.stopPropagation();
+ const index = this.tabs.indexOf(tab);
+
+ this.tabs = this.tabs.filter((t) => t !== tab);
+
+ if (this.tabs.length > 0) {
+ this.activeTab = this.tabs[Math.max(0, index - 1)];
+ }
+ }
+}
diff --git a/packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.css b/packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.css
new file mode 100644
index 000000000..23d95e8fc
--- /dev/null
+++ b/packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.css
@@ -0,0 +1,23 @@
+:host {
+ display: flex;
+ align-items: center;
+ gap: var(--kbq-size-l);
+ --tab-nav-selected: var(--kbq-tabs-tab-item-filled-on-background-states-selected-background);
+}
+
+.example-tab-nav-bar {
+ overflow: hidden;
+}
+
+.example-tab-close {
+ position: absolute;
+ right: calc(var(--kbq-tabs-size-tab-item-padding-horizontal) - var(--kbq-tabs-size-tab-item-focus-outline-width));
+ top: 0;
+ bottom: 0;
+ width: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ background: linear-gradient(var(--tab-nav-selected), var(--tab-nav-selected)), var(--kbq-background-bg);
+ mask-image: linear-gradient(to right, transparent 0%, black 50%);
+}
diff --git a/packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.ts b/packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.ts
new file mode 100644
index 000000000..ccbb4f675
--- /dev/null
+++ b/packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.ts
@@ -0,0 +1,57 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { KbqButtonModule } from '@koobiq/components/button';
+import { KbqIconModule } from '@koobiq/components/icon';
+import { KbqTabsModule } from '@koobiq/components/tabs';
+
+/**
+ * @title Tabs add tab
+ */
+@Component({
+ selector: 'tabs-add-tab-example',
+ imports: [KbqTabsModule, KbqButtonModule, KbqIconModule],
+ template: `
+
+
+ `,
+ styleUrls: ['./tabs-add-tab-example.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class TabsAddTabExample {
+ protected tabs = ['BruteForce', 'Complex Attack', 'DDoS', 'HIPS alert'];
+ protected activeTab = this.tabs[0];
+
+ protected addTab(): void {
+ const newTab = `Tab ${this.tabs.length + 1}`;
+
+ this.tabs = [...this.tabs, newTab];
+ this.activeTab = newTab;
+ }
+
+ protected removeTab(tab: string, event: MouseEvent): void {
+ event.stopPropagation();
+ const index = this.tabs.indexOf(tab);
+
+ this.tabs = this.tabs.filter((t) => t !== tab);
+
+ if (this.tabs.length > 0) {
+ this.activeTab = this.tabs[Math.max(0, index - 1)];
+ }
+ }
+}