Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { expect } from '@playwright/test';
import { test } from '@stencil/playwright';

test.describe('kol-input-text clear button', () => {
test('should render clear button when type is search and input has value', async ({ page }) => {
await page.setContent('<kol-input-text _label="Search" _type="search" _value="test"></kol-input-text>');
const clearButton = page.getByTestId('kol-input-text-clear-button');
await expect(clearButton).toBeVisible();
});

test('should not render clear button when type is not search', async ({ page }) => {
await page.setContent('<kol-input-text _label="Text" _type="text" _value="test"></kol-input-text>');
const clearButton = page.getByTestId('kol-input-text-clear-button');
await expect(clearButton).not.toBeVisible();
});

test('should not render clear button when input is empty', async ({ page }) => {
await page.setContent('<kol-input-text _label="Search" _type="search"></kol-input-text>');
const clearButton = page.getByTestId('kol-input-text-clear-button');
await expect(clearButton).not.toBeVisible();
});

test('should render clear button when input has value', async ({ page }) => {
await page.setContent('<kol-input-text _label="Search" _type="search" _value="test"></kol-input-text>');
const clearButton = page.getByTestId('kol-input-text-clear-button');
await expect(clearButton).toBeVisible();
});

test('should clear input value when clear button is clicked', async ({ page }) => {
await page.setContent('<kol-input-text _label="Search" _type="search" _value="test"></kol-input-text>');
const input = page.locator('kol-input-text input');
const clearButton = page.getByTestId('kol-input-text-clear-button');

await expect(input).toHaveValue('test');
await clearButton.click();
await expect(input).toHaveValue('');
});

test('should not render clear button when disabled', async ({ page }) => {
await page.setContent('<kol-input-text _label="Search" _type="search" _disabled _value="test"></kol-input-text>');
const clearButton = page.getByTestId('kol-input-text-clear-button');
await expect(clearButton).not.toBeVisible();
});

test('should have correct aria-label', async ({ page }) => {
await page.setContent('<kol-input-text _label="Search" _type="search" _value="test"></kol-input-text>');
const clearButton = page.getByTestId('kol-input-text-clear-button');
await expect(clearButton).toHaveAttribute('aria-label', 'Suche löschen');
});
});
30 changes: 28 additions & 2 deletions packages/components/src/components/input-text/shadow.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { JSX } from '@stencil/core';
import type { JSX, VNode } from '@stencil/core';
import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core';
import clsx from '../../utils/clsx';

import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper';
import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper';
import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper';
import KolIconButtonFc from '../../functional-components/IconButton';
import { translate } from '../../i18n';
import type {
AccessKeyPropType,
AriaDetailsPropType,
Expand Down Expand Up @@ -100,6 +102,30 @@ export class KolInputText implements ClickableElement, FocusableElement, InputTe
}
};

private readonly translateClearSearch = translate('kol-clear-search');

private getClearButton(): VNode | null {
if (this.state._type === 'search' && !this._disabled && this.state._hasValue) {
return (
<KolIconButtonFc
componentName="button"
class="kol-input-text__clear-button kol-input-container__smart-button"
data-testid="kol-input-text-clear-button"
label={this.translateClearSearch}
buttonVariant="ghost"
onClick={(): void => {
this._value = '';
this.ctaRef.el?.focus();
}}
icon="kolicon-x"
disabled={this._disabled}
/>
);
}

return null;
}

/**
* Returns the current value.
*/
Expand Down Expand Up @@ -208,7 +234,7 @@ export class KolInputText implements ClickableElement, FocusableElement, InputTe
public render(): JSX.Element {
return (
<KolFormFieldStateWrapperFc {...this.getFormFieldProps()}>
<KolInputContainerFc state={this.state}>
<KolInputContainerFc state={this.state} endAdornment={this.getClearButton()}>
<KolInputStateWrapperFc {...this.getInputProps()} />
</KolInputContainerFc>
</KolFormFieldStateWrapperFc>
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default {
'close-alert': 'Benachrichtigung schließen',
'show-password': 'einblenden',
'hide-password': 'ausblenden',
t'clear-search': 'Suche löschen',
'no-results-message': 'Keine Ergebnisse gefunden.',
'delete-selection': 'Auswahl entfernen',
'filename-text': 'Datei auswählen oder hier ablegen...',
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default {
'close-alert': 'Close notification',
'show-password': 'Show',
'hide-password': 'Hide',
t'clear-search': 'Clear search',
'no-results-message': 'No results found.',
'delete-selection': 'Delete selection',
'filename-text': 'Choose a file or drop it here...',
Expand Down
3 changes: 2 additions & 1 deletion packages/samples/react/src/components/input-text/basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { SampleDescription } from '../SampleDescription';
export const InputTextBasic: FC = () => (
<>
<SampleDescription>
<p>This story showcases the most important InputText variants: default, required, validation error, disabled, read-only, and with icons.</p>
<p>This story showcases the most important InputText variants: default, required, validation error, disabled, read-only, search with clear button, and with icons.</p>
</SampleDescription>

<div className="grid gap-4">
Expand All @@ -34,6 +34,7 @@ export const InputTextBasic: FC = () => (
<KolInputText _label="Name" _value="Anderson-Clark" _disabled />
<KolInputText _label="Name" _readOnly _value="Anderson-Clark" />
<KolInputText _label="Name" _icons="kolicon-house" _value="Anderson-Clark" />
<KolInputText _label="Search" _type="search" _value="test" _placeholder="Search with clear button" />
</div>
</>
);
19 changes: 19 additions & 0 deletions packages/samples/react/src/components/input-text/clear-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { KolInputText } from '@public-ui/react-v19';
import type { FC } from 'react';
import React from 'react';
import { SampleDescription } from '../SampleDescription';

export const InputTextClearButton: FC = () => (
<>
<SampleDescription>
<p>This sample demonstrates the clear button for search type input fields.</p>
</SampleDescription>

<div className="grid gap-4">
<KolInputText _label="Search" _type="search" _placeholder="Enter search term" />
<KolInputText _label="Search (with value)" _type="search" _value="test" _placeholder="Enter search term" />
<KolInputText _label="Search (disabled)" _type="search" _disabled _value="test" _placeholder="Disabled search" />
<KolInputText _label="Text (no clear button)" _type="text" _value="test" _placeholder="Regular text input" />
</div>
</>
);
Loading