Skip to content

Commit f0bfc43

Browse files
authored
chore(inline-edit): removed text flick on mode change (#DS-4360) (#1334)
1 parent 9b5bf15 commit f0bfc43

File tree

11 files changed

+155
-5
lines changed

11 files changed

+155
-5
lines changed

packages/components-dev/inline-edit/module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
2+
import { E2eInlineEditStates } from '../../components/inline-edit/e2e';
23
import { InlineEditExamplesModule } from '../../docs-examples/components/inline-edit';
34
import { DevThemeToggle } from '../theme-toggle';
45

@@ -29,7 +30,8 @@ export class DevDocsExamples {}
2930
selector: 'dev-app',
3031
imports: [
3132
DevDocsExamples,
32-
DevThemeToggle
33+
DevThemeToggle,
34+
E2eInlineEditStates
3335
],
3436
providers: [],
3537
templateUrl: './template.html',
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<dev-theme-toggle />
22
<hr />
33

4+
<e2e-inline-edit-states />
5+
46
<dev-examples />
16.5 KB
Loading
18.5 KB
Loading
17.3 KB
Loading
16.3 KB
Loading
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { expect, Locator, Page, test } from '@playwright/test';
2+
import { e2eEnableDarkTheme } from '../../e2e/utils';
3+
4+
test.describe('KbqInlineEdit', () => {
5+
test.describe('E2eInlineEditStates', () => {
6+
const getComponent = (page: Page) => page.getByTestId('e2eInlineEditStates');
7+
const getTable = (locator: Locator) => locator.getByTestId('e2eInlineEditList');
8+
const clickOpenTrigger = (locator: Locator) => locator.getByTestId('e2eInlineEditOpenTrigger').click();
9+
const clickFocusTrigger = (locator: Locator) => locator.getByTestId('e2eInlineEditFocusTrigger').click();
10+
11+
test('edit states', async ({ page }) => {
12+
await page.goto('/E2eInlineEditStates');
13+
14+
const component = getComponent(page);
15+
16+
const screenshotTarget = getTable(component);
17+
18+
await clickOpenTrigger(component);
19+
20+
await expect(screenshotTarget).toHaveScreenshot('01-light.png');
21+
await e2eEnableDarkTheme(page);
22+
await expect(screenshotTarget).toHaveScreenshot('01-dark.png');
23+
});
24+
25+
test('view states', async ({ page }) => {
26+
await page.goto('/E2eInlineEditStates');
27+
28+
const component = getComponent(page);
29+
30+
const screenshotTarget = getTable(component);
31+
32+
await clickFocusTrigger(component);
33+
34+
await expect(screenshotTarget).toHaveScreenshot('02-light.png');
35+
await e2eEnableDarkTheme(page);
36+
await expect(screenshotTarget).toHaveScreenshot('02-dark.png');
37+
});
38+
});
39+
});
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { NgTemplateOutlet } from '@angular/common';
2+
import { ChangeDetectionStrategy, Component, viewChildren } from '@angular/core';
3+
import { FormsModule } from '@angular/forms';
4+
import { KbqButtonModule } from '@koobiq/components/button';
5+
import { kbqInjectNativeElement } from '@koobiq/components/core';
6+
import { KbqFormFieldModule } from '@koobiq/components/form-field';
7+
import { KbqInputModule } from '@koobiq/components/input';
8+
import { KbqInlineEdit } from './inline-edit';
9+
import { KbqInlineEditModule } from './module';
10+
11+
@Component({
12+
selector: 'e2e-inline-edit-states',
13+
imports: [
14+
KbqInlineEditModule,
15+
FormsModule,
16+
KbqFormFieldModule,
17+
KbqInputModule,
18+
NgTemplateOutlet,
19+
KbqButtonModule
20+
],
21+
template: `
22+
<button kbq-button data-testid="e2eInlineEditOpenTrigger" (click)="openInlineEdits()">open inline edits</button>
23+
<button kbq-button data-testid="e2eInlineEditFocusTrigger" (click)="focusInlineEdits()">
24+
focus inline edits
25+
</button>
26+
27+
<div
28+
class="layout-column layout-gap-xxl layout-margin-bottom-6xl flex layout-padding-3xs"
29+
data-testid="e2eInlineEditList"
30+
>
31+
<kbq-inline-edit>
32+
<div class="example-inline-text" kbqInlineEditViewMode>
33+
<ng-container *ngTemplateOutlet="view; context: { $implicit: { value: '' } }" />
34+
</div>
35+
<kbq-form-field kbqInlineEditEditMode>
36+
<input kbqInput [placeholder]="'placeholder'" />
37+
</kbq-form-field>
38+
</kbq-inline-edit>
39+
40+
<kbq-inline-edit>
41+
<div class="example-inline-text" kbqInlineEditViewMode>
42+
<ng-container *ngTemplateOutlet="view; context: { $implicit: { value: 'value' } }" />
43+
</div>
44+
<kbq-form-field kbqInlineEditEditMode>
45+
<input kbqInput [placeholder]="'placeholder'" [value]="'value'" />
46+
</kbq-form-field>
47+
</kbq-inline-edit>
48+
49+
<kbq-inline-edit>
50+
<kbq-label>Label</kbq-label>
51+
52+
<div class="example-inline-text" kbqInlineEditViewMode>
53+
<ng-container *ngTemplateOutlet="view; context: { $implicit: { value: 'value' } }" />
54+
</div>
55+
<kbq-form-field kbqInlineEditEditMode>
56+
<input kbqInput [placeholder]="'placeholder'" [value]="'value'" />
57+
</kbq-form-field>
58+
</kbq-inline-edit>
59+
60+
<kbq-inline-edit showActions>
61+
<div class="example-inline-text" kbqInlineEditViewMode>
62+
<ng-container *ngTemplateOutlet="view; context: { $implicit: { value: 'value' } }" />
63+
</div>
64+
<kbq-form-field kbqInlineEditEditMode>
65+
<input kbqInput [placeholder]="'placeholder'" [value]="'value'" />
66+
</kbq-form-field>
67+
</kbq-inline-edit>
68+
</div>
69+
70+
<ng-template #view let-control>
71+
@if (!control.value) {
72+
<span kbqInlineEditPlaceholder>placeholder</span>
73+
} @else {
74+
{{ control.value }}
75+
}
76+
</ng-template>
77+
`,
78+
styles: `
79+
:host {
80+
max-width: 500px;
81+
}
82+
`,
83+
changeDetection: ChangeDetectionStrategy.OnPush,
84+
host: {
85+
class: 'layout-margin-top-l layout-row',
86+
'data-testid': 'e2eInlineEditStates'
87+
}
88+
})
89+
export class E2eInlineEditStates {
90+
protected readonly inlineEditList = viewChildren(KbqInlineEdit);
91+
private readonly nativeElement = kbqInjectNativeElement();
92+
93+
openInlineEdits() {
94+
this.inlineEditList().forEach((inlineEdit) => inlineEdit.toggleMode());
95+
}
96+
97+
focusInlineEdits() {
98+
this.nativeElement
99+
.querySelectorAll<HTMLElement>('.kbq-inline-edit__focus_container')
100+
.forEach((focusContainer) => {
101+
focusContainer.classList.add('cdk-focused');
102+
focusContainer.classList.add('cdk-keyboard-focused');
103+
});
104+
}
105+
}

packages/components/inline-edit/inline-edit.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ export class KbqInlineEdit {
234234
.subscribe((currentMode) => this.modeChange.emit(currentMode));
235235
}
236236

237-
/** @docs-private */
238-
protected toggleMode(): void {
237+
/** Manually switch mode */
238+
toggleMode(): void {
239239
this.mode.update((mode) => (mode === 'view' ? 'edit' : 'view'));
240240
}
241241

packages/e2e/routes.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { E2eEmptyStateStateAndStyle } from '../components/empty-state/e2e';
2020
import { E2eFileUploadStateAndStyle } from '../components/file-upload/e2e';
2121
import { E2eFilterBarStates } from '../components/filter-bar/e2e';
2222
import { E2eIconStateAndStyle } from '../components/icon/e2e';
23+
import { E2eInlineEditStates } from '../components/inline-edit/e2e';
2324
import { E2eInputStateAndStyle } from '../components/input/e2e';
2425
import { E2eLinkStates } from '../components/link/e2e';
2526
import { E2eListStates } from '../components/list/e2e';
@@ -130,7 +131,8 @@ const components = [
130131
E2eTreeSelectStates,
131132
E2eMultiTreeSelectStates,
132133
E2eMultilineTreeSelectStates,
133-
E2eSelectWithSearchAndFooter
134+
E2eSelectWithSearchAndFooter,
135+
E2eInlineEditStates
134136
];
135137

136138
export const e2eRoutes: Routes = components.map((component) => {

0 commit comments

Comments
 (0)