From 87e2459100590abfb25b4cbea08c352d1ad12bd1 Mon Sep 17 00:00:00 2001 From: Artem Belik Date: Thu, 9 Jul 2026 14:22:22 +0300 Subject: [PATCH 1/3] chore: added add-tab-example's (#DS-5231) --- packages/components-dev/tabs/module.ts | 12 +++- packages/components/tabs/tabs.en.md | 10 +++ packages/components/tabs/tabs.ru.md | 10 +++ .../docs-examples/components/tabs/index.ts | 6 ++ .../tabs-add-tab-vertical-example.css | 43 +++++++++++++ .../tabs-add-tab-vertical-example.ts | 62 +++++++++++++++++++ .../tabs-add-tab/tabs-add-tab-example.css | 20 ++++++ .../tabs/tabs-add-tab/tabs-add-tab-example.ts | 57 +++++++++++++++++ 8 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.css create mode 100644 packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.ts create mode 100644 packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.css create mode 100644 packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.ts diff --git a/packages/components-dev/tabs/module.ts b/packages/components-dev/tabs/module.ts index fb2093ed07..8a72ef8774 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 8998953965..298aba1da0 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 0747c798d8..c868472546 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 b23db0b573..bdafd5f696 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 0000000000..b9e6bc68bd --- /dev/null +++ b/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.css @@ -0,0 +1,43 @@ +:host { + display: flex; + width: 100%; + max-width: 100%; + height: 300px; + --tab-nav-selected: var(--kbq-tabs-tab-item-filled-on-background-states-selected-background); +} + +.example-tab-nav-bar { + width: 240px; +} + +.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; + display: flex; + align-items: center; +} + +.example-tab-close .kbq-icon-button { + display: flex; + background: linear-gradient(var(--tab-nav-selected), var(--tab-nav-selected)), var(--kbq-background-bg); +} + +.example-tab-close__gradient { + width: var(--kbq-size-3xl); + height: 100%; + margin-right: calc(var(--kbq-size-xs) * -1); + background: var(--kbq-background-bg); + mask-image: linear-gradient(to right, transparent, black); +} + +.kbq-tab-nav-bar .example-tab-close__gradient { + background: linear-gradient(var(--tab-nav-selected), var(--tab-nav-selected)), var(--kbq-background-bg); +} + +.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 0000000000..759175633f --- /dev/null +++ b/packages/docs-examples/components/tabs/tabs-add-tab-vertical/tabs-add-tab-vertical-example.ts @@ -0,0 +1,62 @@ +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 0000000000..c483d8b1ad --- /dev/null +++ b/packages/docs-examples/components/tabs/tabs-add-tab/tabs-add-tab-example.css @@ -0,0 +1,20 @@ +: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; + display: flex; + align-items: center; + background: linear-gradient(to left, transparent 0%, var(--tab-nav-selected) 70%); +} 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 0000000000..ccbb4f6758 --- /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)]; + } + } +} From bd30a5f895e7a1bc602b3fe86a78e29f089225f9 Mon Sep 17 00:00:00 2001 From: Artem Belik Date: Thu, 9 Jul 2026 23:37:30 +0300 Subject: [PATCH 2/3] refactor: styles --- .../tabs-add-tab-vertical-example.css | 27 +++++++------------ .../tabs-add-tab-vertical-example.ts | 3 +-- .../tabs-add-tab/tabs-add-tab-example.css | 5 +++- 3 files changed, 15 insertions(+), 20 deletions(-) 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 index b9e6bc68bd..4d147e9ca0 100644 --- 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 @@ -2,7 +2,7 @@ display: flex; width: 100%; max-width: 100%; - height: 300px; + height: 250px; --tab-nav-selected: var(--kbq-tabs-tab-item-filled-on-background-states-selected-background); } @@ -10,30 +10,23 @@ width: 240px; } +.example-tab-link { + display: inline-block; + 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; -} - -.example-tab-close .kbq-icon-button { - display: flex; - background: linear-gradient(var(--tab-nav-selected), var(--tab-nav-selected)), var(--kbq-background-bg); -} - -.example-tab-close__gradient { - width: var(--kbq-size-3xl); - height: 100%; - margin-right: calc(var(--kbq-size-xs) * -1); - background: var(--kbq-background-bg); - mask-image: linear-gradient(to right, transparent, black); -} - -.kbq-tab-nav-bar .example-tab-close__gradient { + 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 { 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 index 759175633f..d7eeefc863 100644 --- 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 @@ -12,11 +12,10 @@ import { KbqTabsModule } from '@koobiq/components/tabs'; template: `