diff --git a/packages/components/inline-edit/__screenshots__/01-dark.png b/packages/components/inline-edit/__screenshots__/01-dark.png
index 4b7df1a52..77813ecbb 100644
Binary files a/packages/components/inline-edit/__screenshots__/01-dark.png and b/packages/components/inline-edit/__screenshots__/01-dark.png differ
diff --git a/packages/components/inline-edit/__screenshots__/01-light.png b/packages/components/inline-edit/__screenshots__/01-light.png
index cf2bdcb65..dc2a8b4c9 100644
Binary files a/packages/components/inline-edit/__screenshots__/01-light.png and b/packages/components/inline-edit/__screenshots__/01-light.png differ
diff --git a/packages/components/inline-edit/__screenshots__/07-dark.png b/packages/components/inline-edit/__screenshots__/07-dark.png
new file mode 100644
index 000000000..4e5d37946
Binary files /dev/null and b/packages/components/inline-edit/__screenshots__/07-dark.png differ
diff --git a/packages/components/inline-edit/__screenshots__/07-light.png b/packages/components/inline-edit/__screenshots__/07-light.png
new file mode 100644
index 000000000..71804e221
Binary files /dev/null and b/packages/components/inline-edit/__screenshots__/07-light.png differ
diff --git a/packages/components/inline-edit/e2e.playwright-spec.ts b/packages/components/inline-edit/e2e.playwright-spec.ts
index 76f94fb5b..fcacf3fbc 100644
--- a/packages/components/inline-edit/e2e.playwright-spec.ts
+++ b/packages/components/inline-edit/e2e.playwright-spec.ts
@@ -64,6 +64,27 @@ test.describe('KbqInlineEdit', () => {
});
});
+ test.describe('E2eInlineEditActionButtons', () => {
+ const getContainer = (page: Page) => page.getByTestId('e2eInlineEditActionButtonsContainer');
+ const openEdit = (page: Page) => page.getByTestId('e2eInlineEditActionButtonsOpen').click();
+ const getSaveButton = (page: Page) =>
+ page.locator('.kbq-inline-edit__action-buttons .kbq-inline-edit__action-button').first().locator('button');
+
+ test('invalid state on save attempt', async ({ page }) => {
+ await page.goto('/E2eInlineEditActionButtons');
+
+ await openEdit(page);
+ await page.getByRole('textbox').clear();
+ await getSaveButton(page).click();
+
+ const screenshotTarget = getContainer(page);
+
+ await expect(screenshotTarget).toHaveScreenshot('07-light.png');
+ await e2eEnableDarkTheme(page);
+ await expect(screenshotTarget).toHaveScreenshot('07-dark.png');
+ });
+ });
+
test.describe('E2eInlineEditMenuButton', () => {
const getComponent = (page: Page) => page.getByTestId('e2eInlineEditMenuButton');
const getContainer = (page: Page) => page.getByTestId('e2eInlineEditMenuButtonContainer');
diff --git a/packages/components/inline-edit/e2e.ts b/packages/components/inline-edit/e2e.ts
index 4723c1c5c..8f1f5f4e4 100644
--- a/packages/components/inline-edit/e2e.ts
+++ b/packages/components/inline-edit/e2e.ts
@@ -1,11 +1,12 @@
import { NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, viewChildren } from '@angular/core';
-import { FormsModule } from '@angular/forms';
+import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { KbqButtonModule } from '@koobiq/components/button';
import { kbqInjectNativeElement } from '@koobiq/components/core';
import { KbqDropdownModule } from '@koobiq/components/dropdown';
import { KbqIconModule } from '@koobiq/components/icon';
import { KbqInputModule } from '@koobiq/components/input';
+import { KbqTextareaModule } from '@koobiq/components/textarea';
import { KbqInlineEdit } from './inline-edit';
import { KbqInlineEditModule } from './module';
@@ -212,3 +213,41 @@ export class E2eInlineEditTruncation {}
}
})
export class E2eInlineEditMenuButton {}
+
+@Component({
+ selector: 'e2e-inline-edit-action-buttons',
+ imports: [
+ ReactiveFormsModule,
+ KbqInlineEditModule,
+ KbqTextareaModule,
+ KbqButtonModule
+ ],
+ template: `
+
+
+
+
+ {{ control.value || 'empty' }}
+
+
+ @if (textareaInlineEdit.modeAsReadonly() === 'edit') {
+
+
+
+ }
+
+
+
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: {
+ class: 'layout-margin-top-l layout-column layout-gap-m',
+ style: 'max-width: 400px',
+ 'data-testid': 'e2eInlineEditActionButtons'
+ }
+})
+export class E2eInlineEditActionButtons {
+ readonly control = new FormControl('Initial value', Validators.required);
+}
diff --git a/packages/components/inline-edit/inline-edit.html b/packages/components/inline-edit/inline-edit.html
index f6027d28b..f9589ab2b 100644
--- a/packages/components/inline-edit/inline-edit.html
+++ b/packages/components/inline-edit/inline-edit.html
@@ -50,12 +50,17 @@
@if (showActions()) {
}
diff --git a/packages/components/inline-edit/inline-edit.scss b/packages/components/inline-edit/inline-edit.scss
index cfdf93df8..852956e2e 100644
--- a/packages/components/inline-edit/inline-edit.scss
+++ b/packages/components/inline-edit/inline-edit.scss
@@ -176,10 +176,6 @@
.kbq-inline-edit__panel {
width: 100%;
- .kbq-inline-edit__control-container {
- border-radius: var(--kbq-size-border-radius);
- }
-
.kbq-inline-edit__action-buttons {
position: absolute;
left: calc(-1 * var(--kbq-inline-edit-padding-horizontal));
@@ -190,7 +186,9 @@
}
.kbq-inline-edit__control-container,
- .kbq-inline-edit__action-buttons > .kbq-button-icon {
+ .kbq-inline-edit__action-button {
box-shadow: var(--kbq-shadow-popup);
+ background-color: var(--kbq-background-bg);
+ border-radius: var(--kbq-size-border-radius);
}
}
diff --git a/packages/components/inline-edit/inline-edit.spec.ts b/packages/components/inline-edit/inline-edit.spec.ts
index 37a5e430d..3605fd3d9 100644
--- a/packages/components/inline-edit/inline-edit.spec.ts
+++ b/packages/components/inline-edit/inline-edit.spec.ts
@@ -14,6 +14,7 @@ import {
TAB
} from '@koobiq/components/core';
import { KbqDropdownModule } from '@koobiq/components/dropdown';
+import { KbqFormFieldModule } from '@koobiq/components/form-field';
import { KbqIconModule } from '@koobiq/components/icon';
import { KbqInputModule } from '@koobiq/components/input';
import { KbqSelectModule } from '@koobiq/components/select';
@@ -37,6 +38,7 @@ const componentCssClasses = {
panel: '.kbq-inline-edit__panel',
focusContainer: '.kbq-inline-edit',
terminalButtons: '.kbq-inline-edit__action-buttons',
+ terminalButtonItem: '.kbq-inline-edit__action-button',
menuMask: '.kbq-inline-edit__menu-mask',
menu: '.kbq-inline-edit__menu',
overlay: '.cdk-overlay-pane',
@@ -176,9 +178,9 @@ describe('KbqInlineEdit', () => {
inlineEditDebugElement.nativeElement.click();
fixture.detectChanges();
- const saveButtonHTMLElement = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.firstElementChild as HTMLButtonElement | null;
+ const saveButtonHTMLElement = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelector('button') as HTMLButtonElement | null;
saveButtonHTMLElement?.click();
@@ -213,9 +215,9 @@ describe('KbqInlineEdit', () => {
inlineEditDebugElement.nativeElement.click();
fixture.detectChanges();
- const cancelButtonHTMLElement = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.lastElementChild as HTMLButtonElement | null;
+ const cancelButtonHTMLElement = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelectorAll('button')[1] as HTMLButtonElement | null;
cancelButtonHTMLElement?.click();
@@ -251,9 +253,9 @@ describe('KbqInlineEdit', () => {
fixture.detectChanges();
await fixture.whenStable();
- const cancelButtonHTMLElement = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.lastElementChild as HTMLButtonElement | null;
+ const cancelButtonHTMLElement = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelectorAll('button')[1] as HTMLButtonElement | null;
const control = getOverlayElement()!.querySelector('input');
@@ -333,9 +335,9 @@ describe('KbqInlineEdit', () => {
componentInstance.control.updateValueAndValidity();
fixture.detectChanges();
- const saveButtonHTMLElement = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.firstElementChild as HTMLButtonElement | null;
+ const saveButtonHTMLElement = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelector('button') as HTMLButtonElement | null;
saveButtonHTMLElement?.click();
@@ -404,9 +406,9 @@ describe('KbqInlineEdit', () => {
fixture.detectChanges();
await fixture.whenStable();
- const saveButton = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.firstElementChild as HTMLButtonElement;
+ const saveButton = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelector('button') as HTMLButtonElement;
saveButton.click();
@@ -430,9 +432,9 @@ describe('KbqInlineEdit', () => {
componentInstance.form.controls.firstName.updateValueAndValidity();
fixture.detectChanges();
- const saveButton = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.firstElementChild as HTMLButtonElement;
+ const saveButton = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelector('button') as HTMLButtonElement;
saveButton.click();
@@ -456,9 +458,9 @@ describe('KbqInlineEdit', () => {
componentInstance.form.controls.lastName.updateValueAndValidity();
fixture.detectChanges();
- const saveButton = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.firstElementChild as HTMLButtonElement;
+ const saveButton = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelector('button') as HTMLButtonElement;
saveButton.click();
@@ -485,9 +487,9 @@ describe('KbqInlineEdit', () => {
inputs[1].dispatchEvent(new Event('input'));
fixture.detectChanges();
- const cancelButton = document.querySelector(
- `${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`
- )!.lastElementChild as HTMLButtonElement;
+ const cancelButton = document
+ .querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
+ .querySelectorAll('button')[1] as HTMLButtonElement;
cancelButton.click();
@@ -570,10 +572,16 @@ describe('KbqInlineEdit', () => {
};
const clickSave = () => {
- (
- document.querySelector(`${componentCssClasses.panel} ${componentCssClasses.terminalButtons}`)!
- .firstElementChild as HTMLButtonElement
- ).click();
+ const terminalButtonList = document.querySelectorAll(
+ `${componentCssClasses.panel} ${componentCssClasses.terminalButtonItem}`
+ );
+
+ const saveButton = terminalButtonList.length && terminalButtonList[0].firstElementChild;
+
+ expect(saveButton).toBeTruthy();
+ expect(saveButton instanceof HTMLButtonElement).toBeTruthy();
+
+ (saveButton as HTMLButtonElement).click();
};
it('should not show tooltip when empty string is passed and control is invalid', () => {
@@ -962,7 +970,7 @@ export class TestWithSelect extends BaseTestComponent {
@Component({
selector: 'name',
- imports: [ReactiveFormsModule, KbqInlineEditModule, KbqTextareaModule],
+ imports: [ReactiveFormsModule, KbqFormFieldModule, KbqInlineEditModule, KbqTextareaModule],
template: `
{{ control.value }}
diff --git a/packages/e2e/routes.ts b/packages/e2e/routes.ts
index e7ac63428..3811a76e1 100644
--- a/packages/e2e/routes.ts
+++ b/packages/e2e/routes.ts
@@ -33,7 +33,12 @@ import { E2eFileUploadDropzone, E2eFileUploadStateAndStyle } from '../components
import { E2eFilterBarStates } from '../components/filter-bar/e2e';
import { E2eFormFieldGroup, E2eFormFieldset } from '../components/form-field/e2e';
import { E2eIconStateAndStyle, E2eIconSvg } from '../components/icon/e2e';
-import { E2eInlineEditMenuButton, E2eInlineEditStates, E2eInlineEditTruncation } from '../components/inline-edit/e2e';
+import {
+ E2eInlineEditActionButtons,
+ E2eInlineEditMenuButton,
+ E2eInlineEditStates,
+ E2eInlineEditTruncation
+} from '../components/inline-edit/e2e';
import { E2eInputStateAndStyle } from '../components/input/e2e';
import { E2eLinkStates, E2eLinkWithCaption } from '../components/link/e2e';
import { E2eListStates } from '../components/list/e2e';
@@ -213,6 +218,7 @@ const components = [
E2eInlineEditStates,
E2eInlineEditMenuButton,
E2eInlineEditTruncation,
+ E2eInlineEditActionButtons,
E2eFormHorizontal,
E2eTypographyStyles,
E2eTreeTwoLineNode,