Skip to content

fix: overlapping of stepper-button and value #1672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8446b3d
fix: overlapping of stepper-button and value
matthiashader Jan 29, 2025
2188285
Merge branch 'main' into fix/2196-number-input
matthiashader Jan 29, 2025
6f1a36e
fix: vrts and review comments
matthiashader Jan 30, 2025
fb20e8c
Merge remote-tracking branch 'origin/fix/2196-number-input' into fix/โ€ฆ
matthiashader Jan 30, 2025
d2089b9
fix: lifecycle
matthiashader Jan 30, 2025
b273992
Merge branch 'main' into fix/2196-number-input
jul-lam Feb 3, 2025
6baede0
refactor(number-input): apply review suggestion to refactor if statement
AndreasBerliner Feb 3, 2025
18bdd17
Update packages/core/src/tests/number-input/dynamic/index.html
jul-lam Feb 3, 2025
d0938eb
Update packages/core/src/tests/date-input/dynamic/index.html
jul-lam Feb 3, 2025
2de1050
Update packages/core/src/tests/input/dynamic/index.html
jul-lam Feb 3, 2025
421ef3c
Update packages/core/src/tests/date-input/date-input.e2e.ts
jul-lam Feb 3, 2025
8dd3e7e
Update packages/core/src/tests/date-input/basic/index.html
jul-lam Feb 3, 2025
41e030c
Update packages/core/src/components/input/number-input.tsx
jul-lam Feb 3, 2025
8122b5d
fix(input): adapt changeset
AndreasBerliner Feb 5, 2025
d8f5af1
fix(inputs): disposable observers to update paddings when slot contenโ€ฆ
AndreasBerliner Feb 5, 2025
a5ed813
Merge branch 'fix/2196-number-input' of github.com:siemens/ix into fiโ€ฆ
AndreasBerliner Feb 5, 2025
5f8823f
docs: adapt input types examples
jul-lam Feb 5, 2025
95195ea
docs: change input types examples width to 11rem
jul-lam Feb 6, 2025
c38305e
test(inputs): merge dynamic input e2e tests into one single test
AndreasBerliner Feb 7, 2025
af92d1b
Merge branch 'fix/2196-number-input' of github.com:siemens/ix into fiโ€ฆ
AndreasBerliner Feb 7, 2025
3087ff8
test(inputs): sonar fix - explicit local variable declaration in commโ€ฆ
AndreasBerliner Feb 7, 2025
d9cce94
test(inputs): refactor let to const
AndreasBerliner Feb 7, 2025
cbc7e06
test(inputs): add screenshots
jul-lam Feb 7, 2025
7cd0a52
refactor(inputs): change naming of disposable observers to be more coโ€ฆ
AndreasBerliner Feb 10, 2025
4d5a1bc
fix(date-input): review fix remove duplicate html tag for date-input
AndreasBerliner Feb 10, 2025
c767e8f
test(inputs): add element to end-slots of inputs with display none toโ€ฆ
AndreasBerliner Feb 10, 2025
f7810e9
Merge branch 'fix/2196-number-input' of github.com:siemens/ix into fiโ€ฆ
AndreasBerliner Feb 10, 2025
eebf9b7
test(date-input): update screenshots
jul-lam Feb 10, 2025
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
5 changes: 5 additions & 0 deletions .changeset/little-days-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siemens/ix': patch
---

fix initial overlapping between value and stepper button on `ix-number-input`
16 changes: 11 additions & 5 deletions packages/core/src/components/date-input/date-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import {
import { DateTime } from 'luxon';
import { dropdownController } from '../dropdown/dropdown-controller';
import { SlotEnd, SlotStart } from '../input/input.fc';
import { adjustPaddingForStartAndEnd } from '../input/input.util';
import {
adjustPaddingForStartAndEnd,
observeElementUntilVisible,
} from '../input/input.util';
import {
ClassMutationObserver,
HookValidationLifecycle,
Expand Down Expand Up @@ -172,6 +175,7 @@ export class DateInput implements IxInputFieldComponent<string> {
private readonly inputElementRef = makeRef<HTMLInputElement>();
private readonly dropdownElementRef = makeRef<HTMLIxDropdownElement>();
private classObserver?: ClassMutationObserver;
private intersectionObserver?: IntersectionObserver;
private invalidReason?: string;

updateFormInternalValue(value: string): void {
Expand All @@ -198,7 +202,10 @@ export class DateInput implements IxInputFieldComponent<string> {
}

componentDidRender(): void {
this.updatePaddings();
this.intersectionObserver = observeElementUntilVisible(
this.hostElement,
() => this.updatePaddings()
);
}

private updatePaddings() {
Expand All @@ -210,9 +217,8 @@ export class DateInput implements IxInputFieldComponent<string> {
}

disconnectedCallback(): void {
if (this.classObserver) {
this.classObserver.destroy();
}
this.classObserver?.destroy();
this.intersectionObserver?.disconnect();
}

@Watch('value')
Expand Down
13 changes: 11 additions & 2 deletions packages/core/src/components/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
checkAllowedKeys,
getAriaAttributesForInput,
mapValidationResult,
observeElementUntilVisible,
onInputBlur,
} from './input.util';

Expand Down Expand Up @@ -171,6 +172,7 @@ export class Input implements IxInputFieldComponent<string> {
private readonly inputRef = makeRef<HTMLInputElement>();
private readonly slotEndRef = makeRef<HTMLDivElement>();
private readonly slotStartRef = makeRef<HTMLDivElement>();
private intersectionObserver?: IntersectionObserver;

private readonly inputId = `input-${inputIds++}`;

Expand All @@ -189,8 +191,11 @@ export class Input implements IxInputFieldComponent<string> {
this.inputType = this.type;
}

componentDidRender() {
this.updatePaddings();
componentDidRender(): void {
this.intersectionObserver = observeElementUntilVisible(
this.hostElement,
() => this.updatePaddings()
);
}

private updatePaddings() {
Expand All @@ -201,6 +206,10 @@ export class Input implements IxInputFieldComponent<string> {
);
}

disconnectedCallback(): void {
this.intersectionObserver?.disconnect();
}

updateFormInternalValue(value: string) {
this.formInternals.setFormValue(value);
this.value = value;
Expand Down
23 changes: 23 additions & 0 deletions packages/core/src/components/input/input.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,29 @@ export function adjustPaddingForStartAndEnd(
});
}

export function observeElementUntilVisible(
hostElement: HTMLElement,
updateCallback: () => void
): IntersectionObserver {
const rect = hostElement.getBoundingClientRect();

if (rect.width !== 0 && rect.height !== 0) {
updateCallback();
}

const intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
intersectionObserver.disconnect();
updateCallback();
}
});
});

intersectionObserver.observe(hostElement);
return intersectionObserver;
}

export function getAriaAttributesForInput(
component: IxInputFieldComponent
): A11yAttributes {
Expand Down
16 changes: 14 additions & 2 deletions packages/core/src/components/input/number-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
checkAllowedKeys,
checkInternalValidity,
mapValidationResult,
observeElementUntilVisible,
onInputBlur,
} from './input.util';

Expand Down Expand Up @@ -168,6 +169,7 @@ export class NumberInput implements IxInputFieldComponent<number> {
private readonly slotEndRef = makeRef<HTMLDivElement>();
private readonly slotStartRef = makeRef<HTMLDivElement>();
private readonly numberInputId = `number-input-${numberInputIds++}`;
private intersectionObserver?: IntersectionObserver;

@HookValidationLifecycle()
updateClassMappings(result: ValidationResults) {
Expand All @@ -178,8 +180,17 @@ export class NumberInput implements IxInputFieldComponent<number> {
this.updateFormInternalValue(this.value);
}

componentDidRender() {
this.updatePaddings();
componentDidLoad() {
this.intersectionObserver = observeElementUntilVisible(
this.hostElement,
() => this.updatePaddings()
);
}

disconnectedCallback() {
if (this.intersectionObserver) {
this.intersectionObserver.disconnect();
}
}

private updatePaddings() {
Expand Down Expand Up @@ -260,6 +271,7 @@ export class NumberInput implements IxInputFieldComponent<number> {
slotStartRef={this.slotStartRef}
onSlotChange={() => this.updatePaddings()}
></SlotStart>

<InputElement
id={this.numberInputId}
readonly={this.readonly}
Expand Down
43 changes: 43 additions & 0 deletions packages/core/src/tests/date-input/basic/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!--
SPDX-FileCopyrightText: 2024 Siemens AG

SPDX-License-Identifier: MIT
-->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0"
/>
<title>Date Input Test</title>
<style>
.date-input-wrapper {
padding: 1rem;
}
</style>
</head>
<body>
<div class="date-input-wrapper">
<h4>Default</h4>
<ix-date-input></ix-date-input>

<h4>Disabled</h4>
<ix-date-input>
<ix-date-input value='1970/01/01' disabled></ix-date-input>
</ix-date-input>

<h4>Label</h4>
<ix-date-input
label='Begin'
name='begin'
helper-text='Some helper text'
value='1970/01/01'
></ix-date-input>

</div>
<script src="http://127.0.0.1:8080/scripts/e2e/load-e2e-runtime.js"></script>
</body>
</html>
34 changes: 34 additions & 0 deletions packages/core/src/tests/date-input/date-input.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2024 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import { expect } from '@playwright/test';
import { regressionTest } from '@utils/test';

regressionTest.describe('date-input', () => {
regressionTest('basic', async ({ page }) => {
await page.goto('date-input/basic');
await expect(page).toHaveScreenshot();
});
});

regressionTest.describe('hide date-input initially', () => {
regressionTest('show date-input again', async ({ page }) => {
await page.goto('date-input/dynamic');

const toggleButton = page.getByRole('button', {
name: 'Add Date Input',
});
await toggleButton.click();

const numberInputContainer = page.locator('#date-input-container');
await expect(numberInputContainer).toBeVisible();

await expect(page).toHaveScreenshot();
});
});
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.
44 changes: 44 additions & 0 deletions packages/core/src/tests/date-input/dynamic/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!--
SPDX-FileCopyrightText: 2024 Siemens AG
SPDX-License-Identifier: MIT
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0"
/>
<title>Date Input Test</title>
<style>
.date-input-wrapper {
padding: 1rem;
}
#date-input-container {
display: none;
margin-top: 1rem;
}
</style>
</head>
<body>
<div class="date-input-wrapper">
<ix-button onclick="toggleVisibility()">Add Date Input</ix-button>
<div id="date-input-container">
<ix-date-input></ix-date-input>
</div>
</div>

<script>
function toggleVisibility() {
const container = document.getElementById('date-input-container');
const button = document.querySelector('button');
const isVisible = container.style.display === 'block';

container.style.display = isVisible ? 'none' : 'block';
button.textContent = isVisible ? 'Add Date Input' : 'Remove Date Input';
}
</script>
<script src="http://127.0.0.1:8080/scripts/e2e/load-e2e-runtime.js"></script>
</body>
</html>
46 changes: 46 additions & 0 deletions packages/core/src/tests/input/dynamic/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: 2024 Siemens AG
SPDX-License-Identifier: MIT
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0"
/>
<title>Input Test</title>
<style>
.input-wrapper {
padding: 1rem;
}
#input-container {
display: none;
margin-top: 1rem;
}
</style>
</head>
<body>
<div class="input-wrapper">
<ix-button onclick="toggleVisibility()">Add Input</ix-button>
<div id="input-container">
<ix-input value="Lorem ipsum">
<ix-icon-button slot="start" icon="star" size="24"></ix-icon-button>
</ix-input>
</div>
</div>

<script>
function toggleVisibility() {
const container = document.getElementById('input-container');
const button = document.querySelector('button');
const isVisible = container.style.display === 'block';

container.style.display = isVisible ? 'none' : 'block';
button.textContent = isVisible ? 'Add Input' : 'Remove Input';
}
</script>
<script src="http://127.0.0.1:8080/scripts/e2e/load-e2e-runtime.js"></script>
</body>
</html>
14 changes: 14 additions & 0 deletions packages/core/src/tests/input/input.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,18 @@ regressionTest.describe('input', () => {
await expect(page.locator('ix-tooltip')).toBeVisible();
await expect(page).toHaveScreenshot();
});

regressionTest('hide input initially', async ({ page }) => {
await page.goto('input/dynamic');

const toggleButton = page.getByRole('button', {
name: 'Add Input',
});
await toggleButton.click();

const inputContainer = page.locator('#input-container');
await expect(inputContainer).toBeVisible();

await expect(page).toHaveScreenshot();
});
});
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.
44 changes: 44 additions & 0 deletions packages/core/src/tests/number-input/dynamic/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!--
SPDX-FileCopyrightText: 2024 Siemens AG
SPDX-License-Identifier: MIT
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0"
/>
<title>Number Input Test</title>
<style>
.number-input-wrapper {
padding: 1rem;
}
#number-input-container {
display: none;
margin-top: 1rem;
}
</style>
</head>
<body>
<div class="number-input-wrapper">
<ix-button onclick="toggleVisibility()">Add Number Input</ix-button>
<div id="number-input-container">
<ix-number-input show-stepper-buttons value="0"></ix-number-input>
</div>
</div>

<script>
function toggleVisibility() {
const container = document.getElementById('number-input-container');
const button = document.querySelector('button');
const isVisible = container.style.display === 'block';

container.style.display = isVisible ? 'none' : 'block';
button.textContent = isVisible ? 'Add Number Input' : 'Remove Number Input';
}
</script>
<script src="http://127.0.0.1:8080/scripts/e2e/load-e2e-runtime.js"></script>
</body>
</html>
Loading
Loading