Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { expect, Locator, Page, test } from '@playwright/test';
import { devEnableDarkTheme, devGoToRootPage } from '../utils';

test.describe('KbqSplitButtonModule', () => {
test.describe('DevSplitButtonStateAndStyle', () => {
const getComponent = (page: Page) => page.getByTestId('e2eSplitButtonStateAndStyle');
const togglePrefix = (locator: Locator) => locator.getByTestId('e2eShowPrefixIcon').click();
const toggleTitle = (locator: Locator) => locator.getByTestId('e2eShowTitle').click();
const getScreenshotTarget = (locator: Locator) => locator.getByTestId('e2eScreenshotTarget');

test('split-button with title', async ({ page }) => {
await devGoToRootPage(page);
const locator = getComponent(page);

await expect(getScreenshotTarget(locator)).toHaveScreenshot();
});

test('split-button with icon', async ({ page }) => {
await devGoToRootPage(page);
const locator = getComponent(page);

await togglePrefix(locator);
await toggleTitle(locator);

await expect(getScreenshotTarget(locator)).toHaveScreenshot();
});

test('split-button with title, prefix', async ({ page }) => {
await devGoToRootPage(page);
const locator = getComponent(page);

await togglePrefix(locator);

await expect(getScreenshotTarget(locator)).toHaveScreenshot();
});

test('split-button with title, prefix (dark theme)', async ({ page }) => {
await devGoToRootPage(page);
await devEnableDarkTheme(page);

const locator = getComponent(page);

await togglePrefix(locator);

await expect(getScreenshotTarget(locator)).toHaveScreenshot();
});
});
});
139 changes: 139 additions & 0 deletions packages/components-dev/e2e/components/split-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
import { FormsModule } from '@angular/forms';
import { KbqButtonModule, KbqButtonStyles } from '@koobiq/components/button';
import { KbqCheckboxModule } from '@koobiq/components/checkbox';
import { KbqComponentColors } from '@koobiq/components/core';
import { KbqIconModule } from '@koobiq/components/icon';
import { KbqSplitButtonModule } from '@koobiq/components/split-button';
import { combineLatest } from 'rxjs';

type DevButtonState = Partial<{
title: string;
disabled: boolean;
disabledSecond: boolean;
hover: boolean;
hoverSecond: boolean;
active: boolean;
activeSecond: boolean;
focused?: boolean;
focusedSecond?: boolean;
progress: boolean;
progressSecond: boolean;
}>;

type DevButtonStyle = Partial<{
style: KbqButtonStyles;
color: KbqComponentColors;
}>;

type DevButton = DevButtonState & DevButtonStyle;

@Component({
standalone: true,
imports: [KbqButtonModule, KbqIconModule, FormsModule, KbqCheckboxModule, KbqSplitButtonModule],
selector: 'dev-split-button-state-and-style',
host: {
'data-testid': 'e2eSplitButtonStateAndStyle'
},
template: `
<div class="dev-options">
<kbq-checkbox data-testid="e2eShowPrefixIcon" [(ngModel)]="showPrefixIcon">show prefix icon</kbq-checkbox>
<kbq-checkbox data-testid="e2eShowTitle" [disabled]="!showPrefixIcon()" [(ngModel)]="showTitle">
show title
</kbq-checkbox>
</div>

<table data-testid="e2eScreenshotTarget">
@for (buttons of rows; track buttons) {
<tr>
@for (button of buttons; track button.title) {
<td>
<kbq-split-button [color]="button.color!" [kbqStyle]="button.style!">
<button
kbq-button
[class.cdk-keyboard-focused]="button.focused"
[class.kbq-active]="button.active"
[class.kbq-hover]="button.hover"
[class.kbq-progress]="button.progress"
[disabled]="button.disabled"
>
@if (showPrefixIcon()) {
<i kbq-icon="kbq-play_16"></i>
}
@if (showTitle()) {
{{ button.title }}
}
</button>
<button
kbq-button
[class.cdk-keyboard-focused]="button.focusedSecond"
[class.kbq-active]="button.activeSecond"
[class.kbq-hover]="button.hoverSecond"
[class.kbq-progress]="button.progressSecond"
[disabled]="button.disabledSecond"
>
<i kbq-icon="kbq-chevron-down-s_16"></i>
</button>
</kbq-split-button>
</td>
}
</tr>
}
</table>
`,
styles: `
.dev-options {
display: flex;
gap: var(--kbq-size-m);
margin-bottom: var(--kbq-size-l);
padding: var(--kbq-size-xxs);
}

table {
border-spacing: 0;
}

td {
padding: var(--kbq-size-xxs);
}
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DevSplitButtonStateAndStyle {
readonly showPrefixIcon = model(false);
readonly showTitle = model(true);

private readonly states: DevButtonState[] = [
{ title: 'disabled', disabled: true },
{ title: 'disabledSecond', disabledSecond: true },
{ title: 'completelyDisabled', disabledSecond: true, disabled: true },
{ title: 'normal' },
{ title: 'hover', hover: true },
{ title: 'hoverSecond', hoverSecond: true },
{ title: 'active', active: true },
{ title: 'activeSecond', activeSecond: true },
{ title: 'focus', focused: true },
{ title: 'focusSecond', focusedSecond: true },
{ title: 'progress', progress: true },
{ title: 'progressSecond', progressSecond: true },
{ title: 'progressAll', progress: true, progressSecond: true }];

private readonly styles: DevButtonStyle[] = [
{},
{ color: KbqComponentColors.Contrast },
{ color: KbqComponentColors.ThemeFade, style: KbqButtonStyles.Outline },
{ color: KbqComponentColors.ContrastFade, style: KbqButtonStyles.Outline },
{ color: KbqComponentColors.Theme, style: KbqButtonStyles.Transparent },
{ color: KbqComponentColors.Contrast, style: KbqButtonStyles.Transparent }];

readonly rows: DevButton[][] = this.styles.map((style) => this.states.map((state) => ({ ...state, ...style })));

constructor() {
combineLatest([toObservable(this.showPrefixIcon)])
.pipe(takeUntilDestroyed())
.subscribe((args) => {
if (args.every((a) => a === false)) this.showTitle.set(true);
});
}
}
2 changes: 2 additions & 0 deletions packages/components-dev/e2e/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DevThemeToggle } from '../theme-toggle';
import { DevActionsPanelWithOverlayContainer } from './components/actions-panel';
import { DevButtonStateAndStyle } from './components/button';
import { DevFileUploadStateAndStyle } from './components/file-upload';
import { DevSplitButtonStateAndStyle } from './components/split-button';
import { DevTagEditable, DevTagStateAndStyle } from './components/tag';
import { DevToggleStateAndStyle, DevToggleWithTextAndCaption } from './components/toggle';

Expand All @@ -11,6 +12,7 @@ import { DevToggleStateAndStyle, DevToggleWithTextAndCaption } from './component
imports: [
DevThemeToggle,
DevButtonStateAndStyle,
DevSplitButtonStateAndStyle,
DevFileUploadStateAndStyle,
DevActionsPanelWithOverlayContainer,
DevTagStateAndStyle,
Expand Down
4 changes: 4 additions & 0 deletions packages/components-dev/e2e/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@

<hr />

<dev-split-button-state-and-style />

<hr />

<!-- Should be last for correct screenshot test -->
<dev-actions-panel-with-overlay-container />
4 changes: 3 additions & 1 deletion packages/components-dev/split-button/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { KbqLocaleServiceModule } from '@koobiq/components/core';
import { KbqIconModule } from '@koobiq/components/icon';
import { KbqSplitButtonModule } from '@koobiq/components/split-button';
import { SplitButtonExamplesModule } from '../../docs-examples/components/split-button';
import { DevSplitButtonStateAndStyle } from '../e2e/components/split-button';

@Component({
standalone: true,
Expand Down Expand Up @@ -35,7 +36,8 @@ export class DevExamples {}
KbqSplitButtonModule,
DevExamples,
KbqButtonModule,
KbqIconModule
KbqIconModule,
DevSplitButtonStateAndStyle
],
selector: 'dev-app',
templateUrl: './template.html',
Expand Down
25 changes: 14 additions & 11 deletions packages/components-dev/split-button/template.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
<dev-examples />

<kbq-split-button [color]="'contrast'" [kbqStyle]="'outline'">
<button kbq-button>
<dev-split-button-state-and-style />

<kbq-split-button>
<button kbq-button [disabled]="true">
<i kbq-icon="kbq-plus_16"></i>
</button>
<button kbq-button>
<i kbq-icon="kbq-chevron-down-s_16"></i>
</button>
</kbq-split-button>

<!--<br />-->
<br />
<br />

<!--<kbq-split-button [color]="'contrast'" [kbqStyle]="'outline'">-->
<!-- <button kbq-button>-->
<!-- <i kbq-icon="kbq-plus_16"></i>-->
<!-- </button>-->
<!-- <button kbq-button>-->
<!-- <i kbq-icon="kbq-chevron-down-s_16"></i>-->
<!-- </button>-->
<!--</kbq-split-button>-->
<kbq-split-button [color]="'contrast-fade'" [kbqStyle]="'outline'">
<button kbq-button>
<i kbq-icon="kbq-plus_16"></i>
</button>
<button kbq-button>
<i kbq-icon="kbq-chevron-down-s_16"></i>
</button>
</kbq-split-button>
2 changes: 0 additions & 2 deletions packages/components/button-toggle/button-toggle.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@use '../core/styles/common';

@use '../core/styles/common/tokens' as *;

@use './button-toggle-theme' as *;
Expand Down
6 changes: 3 additions & 3 deletions packages/components/button/button.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div #kbqTitleText class="kbq-button-wrapper" (cdkObserveContent)="projectContentChanged()">
<span #kbqTitleText class="kbq-button-wrapper" (cdkObserveContent)="projectContentChanged()">
<ng-content />
</div>
<div class="kbq-button-overlay" (click)="haltDisabledEvents($event)"></div>
</span>
<span class="kbq-button-overlay" (click)="haltDisabledEvents($event)"></span>
5 changes: 5 additions & 0 deletions packages/components/button/button.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Directive,
ElementRef,
forwardRef,
inject,
Input,
numberAttribute,
OnDestroy,
Expand Down Expand Up @@ -129,6 +130,8 @@ export class KbqButtonCssStyler implements AfterContentInit {
{ provide: KBQ_TITLE_TEXT_REF, useExisting: KbqButton }]
})
export class KbqButton extends KbqColorDirective implements OnDestroy, AfterViewInit, KbqTitleTextRef {
private readonly changeDetectorRef = inject(ChangeDetectorRef);

hasFocus: boolean = false;

@ViewChild('kbqTitleText', { static: false }) textElement: ElementRef;
Expand All @@ -140,6 +143,8 @@ export class KbqButton extends KbqColorDirective implements OnDestroy, AfterView

set kbqStyle(value: string | KbqButtonStyles) {
this._kbqStyle = value || KbqButtonStyles.Filled;

this.changeDetectorRef.markForCheck();
}

private _kbqStyle: string | KbqButtonStyles = KbqButtonStyles.Filled;
Expand Down
15 changes: 8 additions & 7 deletions packages/components/dropdown/dropdown-item.scss
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
@use '../core/styles/common';
@use '../core/styles/common/list';
@use '../core/styles/common/vendor-prefixes';

.kbq-dropdown-item {
width: 100%;
border-radius: var(--kbq-dropdown-item-border-radius);

@include common.user-select(none);
@include common.kbq-list-item-base();
@include vendor-prefixes.user-select(none);
@include list.kbq-list-item-base();

&:not(.kbq-disabled) {
cursor: pointer;
Expand All @@ -29,7 +30,7 @@
}

.kbq-dropdown-item__text {
@include common.kbq-list-text();
@include list.kbq-list-text();
}

.kbq-dropdown-item-overlay {
Expand All @@ -44,11 +45,11 @@
}

.kbq-dropdown__group-header {
@include common.user-select(none);
@include common.kbq-list-header-base();
@include vendor-prefixes.user-select(none);
@include list.kbq-list-header-base();

// @deprecated, use <kbq-optgroup label="Label" /> instead. Will be removed in the next major release
&.kbq-dropdown__group-header_small {
@include common.kbq-list-subheading-base();
@include list.kbq-list-subheading-base();
}
}
Loading