From d8072a9686170337c4cdaccaf94069f7337b6271 Mon Sep 17 00:00:00 2001 From: lskramarov Date: Thu, 23 Jul 2026 17:03:25 +0300 Subject: [PATCH 1/3] feat(components): add pressed state to option/tree/dropdown items (#DS-3482) --- .../app-switcher-dropdown-app.scss | 7 ++++++- .../app-switcher-dropdown-site.scss | 7 ++++++- .../kbq-app-switcher-list-item.scss | 12 +++++------ .../components/core/option/_option-theme.scss | 15 +++++++++++++ .../components/dropdown/_dropdown-theme.scss | 10 +++++++++ .../tree-select/_tree-select-theme.scss | 21 +++++++++++++++++++ packages/components/tree/_tree-theme.scss | 21 +++++++++++++++++++ packages/components/tree/e2e.ts | 12 +++++++++-- 8 files changed, 95 insertions(+), 10 deletions(-) diff --git a/packages/components/app-switcher/app-switcher-dropdown-app.scss b/packages/components/app-switcher/app-switcher-dropdown-app.scss index 65d113fda8..07e4354c4d 100644 --- a/packages/components/app-switcher/app-switcher-dropdown-app.scss +++ b/packages/components/app-switcher/app-switcher-dropdown-app.scss @@ -60,7 +60,12 @@ &.kbq-dropdown-item_highlighted, &:hover { - background: var(--kbq-states-background-transparent-active); + background: var(--kbq-list-states-hover-container-background); + } + + &:active, + &.kbq-active { + background: var(--kbq-list-states-active-container-background); } &.cdk-keyboard-focused { diff --git a/packages/components/app-switcher/app-switcher-dropdown-site.scss b/packages/components/app-switcher/app-switcher-dropdown-site.scss index fa4b5a1f7e..2052125621 100644 --- a/packages/components/app-switcher/app-switcher-dropdown-site.scss +++ b/packages/components/app-switcher/app-switcher-dropdown-site.scss @@ -34,7 +34,12 @@ &.kbq-dropdown-item_highlighted, &:hover { - background: var(--kbq-states-background-transparent-active); + background: var(--kbq-list-states-hover-container-background); + } + + &:active, + &.kbq-active { + background: var(--kbq-list-states-active-container-background); } &.cdk-keyboard-focused { diff --git a/packages/components/app-switcher/kbq-app-switcher-list-item.scss b/packages/components/app-switcher/kbq-app-switcher-list-item.scss index 65f4f1d7a4..47fe02c0d5 100644 --- a/packages/components/app-switcher/kbq-app-switcher-list-item.scss +++ b/packages/components/app-switcher/kbq-app-switcher-list-item.scss @@ -130,29 +130,29 @@ &:hover, &.kbq-hover { - background: var(--kbq-states-background-transparent-hover); + background: var(--kbq-list-states-hover-container-background); & .kbq-app-switcher-list-item__toggle { - background: var(--kbq-states-background-transparent-hover); + background: var(--kbq-list-states-hover-container-background); } } &:active, &.kbq-active { - background: var(--kbq-states-background-transparent-active); + background: var(--kbq-list-states-active-container-background); } &.kbq-selected { - background: var(--kbq-background-theme-less); + background: var(--kbq-list-states-selected-container-background); &:hover, &.kbq-hover { - background: var(--kbq-states-background-theme-less-hover); + background: var(--kbq-list-states-selected-hover-container-background); } &:active, &.kbq-active { - background: var(--kbq-states-background-theme-less-active); + background: var(--kbq-list-states-selected-active-container-background); } } diff --git a/packages/components/core/option/_option-theme.scss b/packages/components/core/option/_option-theme.scss index ba3b6c137c..2bd0d06861 100644 --- a/packages/components/core/option/_option-theme.scss +++ b/packages/components/core/option/_option-theme.scss @@ -24,12 +24,22 @@ @include kbq-option(states-hover); } + &:active:not(.kbq-disabled), + &.kbq-pressed:not(.kbq-disabled) { + @include kbq-option(states-active); + } + &.kbq-selected:not(.kbq-disabled) { @include kbq-option(states-selected); &.kbq-active { @include kbq-option(states-selected-hover); } + + &:active, + &.kbq-pressed { + @include kbq-option(states-selected-active); + } } &.kbq-disabled { @@ -54,6 +64,11 @@ &.kbq-active { @include kbq-option(multiple-states-selected-hover); } + + &:active, + &.kbq-pressed { + @include kbq-option(multiple-states-selected-active); + } } } } diff --git a/packages/components/dropdown/_dropdown-theme.scss b/packages/components/dropdown/_dropdown-theme.scss index bfdcfb944e..27a907ce2c 100644 --- a/packages/components/dropdown/_dropdown-theme.scss +++ b/packages/components/dropdown/_dropdown-theme.scss @@ -27,12 +27,22 @@ @include _kbq-dropdown-item-state(states-hover); } + &:active:not(.kbq-disabled), + &.kbq-active:not(.kbq-disabled) { + @include _kbq-dropdown-item-state(states-active); + } + &.kbq-selected { @include _kbq-dropdown-item-state(states-selected); &.cdk-focused:not(.kbq-disabled) { @include _kbq-dropdown-item-state(states-selected-hover); } + + &:active:not(.kbq-disabled), + &.kbq-active:not(.kbq-disabled) { + @include _kbq-dropdown-item-state(states-selected-active); + } } &.kbq-disabled { diff --git a/packages/components/tree-select/_tree-select-theme.scss b/packages/components/tree-select/_tree-select-theme.scss index d39354da66..3af1bf410d 100644 --- a/packages/components/tree-select/_tree-select-theme.scss +++ b/packages/components/tree-select/_tree-select-theme.scss @@ -45,6 +45,13 @@ @include tree-theme.kbq-tree-option(states-hover); } + &:active, + &.kbq-active { + --kbq-option-background: var(--kbq-tree-states-active-container-background); + + background: var(--kbq-tree-states-active-container-background); + } + &.kbq-selected { &:hover:not(.kbq-focused), &.kbq-hovered:not(.kbq-focused) { @@ -54,6 +61,13 @@ &.kbq-focused { @include tree-theme.kbq-tree-option(states-selected-hover); } + + &:active, + &.kbq-active { + --kbq-option-background: var(--kbq-tree-states-selected-active-container-background); + + background: var(--kbq-tree-states-selected-active-container-background); + } } &.kbq-checked:not(.kbq-selected), @@ -66,6 +80,13 @@ &.kbq-focused { background: var(--kbq-tree-multiple-states-selected-hover-container-background); } + + &:active, + &.kbq-active { + --kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background); + + background: var(--kbq-tree-multiple-states-selected-active-container-background); + } } &.kbq-focused:not(.kbq-action-button-focused) { diff --git a/packages/components/tree/_tree-theme.scss b/packages/components/tree/_tree-theme.scss index bb6a14f018..c638bad029 100644 --- a/packages/components/tree/_tree-theme.scss +++ b/packages/components/tree/_tree-theme.scss @@ -37,6 +37,13 @@ @include kbq-tree-option(states-hover); } + &:active, + &.kbq-active { + --kbq-option-background: var(--kbq-tree-states-active-container-background); + + background: var(--kbq-tree-states-active-container-background); + } + &.kbq-selected { @include kbq-tree-option(states-selected); @@ -44,6 +51,13 @@ &.kbq-hovered { @include kbq-tree-option(states-selected-hover); } + + &:active, + &.kbq-active { + --kbq-option-background: var(--kbq-tree-states-selected-active-container-background); + + background: var(--kbq-tree-states-selected-active-container-background); + } } &.kbq-checked:not(.kbq-selected), @@ -58,6 +72,13 @@ background: var(--kbq-tree-multiple-states-selected-hover-container-background); } + + &:active, + &.kbq-active { + --kbq-option-background: var(--kbq-tree-multiple-states-selected-active-container-background); + + background: var(--kbq-tree-multiple-states-selected-active-container-background); + } } } diff --git a/packages/components/tree/e2e.ts b/packages/components/tree/e2e.ts index f3931ce593..53e24843e0 100644 --- a/packages/components/tree/e2e.ts +++ b/packages/components/tree/e2e.ts @@ -31,8 +31,10 @@ const DATA_OBJECT = { States: { Normal: '', Hovered: '', + Active: '', Selected: '', SelectedHovered: '', + SelectedActive: '', Focused: '', Disabled: '' }, @@ -98,7 +100,10 @@ function buildFileTree(value: any, level: number): FileNode[] { *kbqTreeNodeDef="let node" kbqTreeNodePadding [class.kbq-hovered]="node.name === 'Hovered' || node.name === 'SelectedHovered'" - [class.kbq-selected]="node.name === 'Selected' || node.name === 'SelectedHovered'" + [class.kbq-active]="node.name === 'Active' || node.name === 'SelectedActive'" + [class.kbq-selected]=" + node.name === 'Selected' || node.name === 'SelectedHovered' || node.name === 'SelectedActive' + " [class.kbq-focused]="node.name === 'Focused'" > @@ -129,7 +134,10 @@ function buildFileTree(value: any, level: number): FileNode[] { *kbqTreeNodeDef="let node" kbqTreeNodePadding [class.kbq-hovered]="node.name === 'Hovered' || node.name === 'SelectedHovered'" - [class.kbq-selected]="node.name === 'Selected' || node.name === 'SelectedHovered'" + [class.kbq-active]="node.name === 'Active' || node.name === 'SelectedActive'" + [class.kbq-selected]=" + node.name === 'Selected' || node.name === 'SelectedHovered' || node.name === 'SelectedActive' + " [class.kbq-focused]="node.name === 'Focused'" > From 4f56d014465477ab1385bf2f4d1b925bd4a32139 Mon Sep 17 00:00:00 2001 From: lskramarov Date: Fri, 24 Jul 2026 14:00:21 +0300 Subject: [PATCH 2/3] fix: after review --- .../app-switcher/e2e.playwright-spec.ts | 17 ++++++++ .../components/core/option/_option-theme.scss | 7 ++-- .../components/dropdown/_dropdown-theme.scss | 5 ++- packages/components/dropdown/e2e.ts | 4 ++ packages/components/list/_list-theme.scss | 13 ++++-- packages/components/select/e2e.ts | 7 +++- .../tree-select/_tree-select-theme.scss | 13 +++--- .../tree-select/e2e.playwright-spec.ts | 41 +++++++++++++++++++ 8 files changed, 91 insertions(+), 16 deletions(-) diff --git a/packages/components/app-switcher/e2e.playwright-spec.ts b/packages/components/app-switcher/e2e.playwright-spec.ts index 461a2a4af5..dbd4de3093 100644 --- a/packages/components/app-switcher/e2e.playwright-spec.ts +++ b/packages/components/app-switcher/e2e.playwright-spec.ts @@ -14,6 +14,23 @@ test.describe('KbqAppSwitcherModule', () => { await e2eEnableDarkTheme(page); await expect(getScreenshotTarget(locator)).toHaveScreenshot('01-dark.png'); }); + + test('pressed', async ({ page }) => { + await page.goto('/E2eAppSwitcherStates'); + const locator = getComponent(page); + const items = page.locator('.kbq-app-switcher-list-item'); + + await items.first().waitFor(); + // App rows are generated from data, so the pressed class is applied from the spec rather than the + // fixture template (select/dropdown/tree fake `.kbq-active`/`.kbq-pressed` inline instead). + // `.kbq-app-switcher-list-item` has no `.kbq-active` host binding, so the injected class survives. + await items.nth(0).evaluate((el) => el.classList.add('kbq-active')); // selected + pressed + await items.nth(1).evaluate((el) => el.classList.add('kbq-active')); // pressed + + await expect(getScreenshotTarget(locator)).toHaveScreenshot('01-pressed-light.png'); + await e2eEnableDarkTheme(page); + await expect(getScreenshotTarget(locator)).toHaveScreenshot('01-pressed-dark.png'); + }); }); test.describe('E2eAppSwitcherWithSitesStates', () => { diff --git a/packages/components/core/option/_option-theme.scss b/packages/components/core/option/_option-theme.scss index 2bd0d06861..1306ed7f80 100644 --- a/packages/components/core/option/_option-theme.scss +++ b/packages/components/core/option/_option-theme.scss @@ -26,7 +26,8 @@ &:active:not(.kbq-disabled), &.kbq-pressed:not(.kbq-disabled) { - @include kbq-option(states-active); + // the active state defines only a background token; the mixin would emit undefined text/icon/caption color vars + background: var(--kbq-list-states-active-container-background); } &.kbq-selected:not(.kbq-disabled) { @@ -38,7 +39,7 @@ &:active, &.kbq-pressed { - @include kbq-option(states-selected-active); + background: var(--kbq-list-states-selected-active-container-background); } } @@ -67,7 +68,7 @@ &:active, &.kbq-pressed { - @include kbq-option(multiple-states-selected-active); + background: var(--kbq-list-multiple-states-selected-active-container-background); } } } diff --git a/packages/components/dropdown/_dropdown-theme.scss b/packages/components/dropdown/_dropdown-theme.scss index 27a907ce2c..ea060c0d86 100644 --- a/packages/components/dropdown/_dropdown-theme.scss +++ b/packages/components/dropdown/_dropdown-theme.scss @@ -29,7 +29,8 @@ &:active:not(.kbq-disabled), &.kbq-active:not(.kbq-disabled) { - @include _kbq-dropdown-item-state(states-active); + // the active state defines only a background token; the mixin would emit undefined text/icon color vars + background: var(--kbq-list-states-active-container-background); } &.kbq-selected { @@ -41,7 +42,7 @@ &:active:not(.kbq-disabled), &.kbq-active:not(.kbq-disabled) { - @include _kbq-dropdown-item-state(states-selected-active); + background: var(--kbq-list-states-selected-active-container-background); } } diff --git a/packages/components/dropdown/e2e.ts b/packages/components/dropdown/e2e.ts index 2a16041497..1fa88214d7 100644 --- a/packages/components/dropdown/e2e.ts +++ b/packages/components/dropdown/e2e.ts @@ -26,6 +26,10 @@ import { KbqDropdownModule } from './dropdown.module'; + + + +