fix(field): prevent NaN transforms when element is hidden

Fixes #5815

When a field's display is set to none, getBoundingClientRect() returns
zeros, causing division by zero in getLabelKeyframes(). This resulted
in NaN values in transform strings.

Added check to skip animation when label dimensions are zero.
This commit is contained in:
eliasmurcray 2025-10-28 10:21:47 -07:00
parent 7619df0d64
commit 590ae99ff7
2 changed files with 28 additions and 0 deletions

View File

@ -320,6 +320,10 @@ export class Field extends LitElement {
} = restingLabelEl.getBoundingClientRect();
const floatingScrollWidth = floatingLabelEl.scrollWidth;
const restingScrollWidth = restingLabelEl.scrollWidth;
// If either label has no dimensions (e.g., display: none), skip animation
if (floatingScrollWidth === 0 || restingScrollWidth === 0) {
return [];
}
// Scale by width ratio instead of font size since letter-spacing will scale
// incorrectly. Using the width we can better approximate the adjusted
// scale and compensate for tracking and overflow.

View File

@ -408,4 +408,28 @@ describe('Field', () => {
.toBeTrue();
});
});
describe('label animation', () => {
it('should not produce NaN transforms when populated while hidden', async () => {
const {instance} = await setupTest({label: 'Hidden Label'});
instance.style.display = 'none';
await env.waitForStability();
const animateCalls: unknown[] = [];
spyOn(Element.prototype, 'animate').and.callFake((keyframes, options) => {
animateCalls.push(keyframes);
return new Animation();
});
const consoleErrorSpy = spyOn(console, 'error');
instance.populated = true;
await env.waitForStability();
for (const keyframe of animateCalls) {
const frames = Array.isArray(keyframe) ? keyframe : [keyframe];
for (const frame of frames) {
const transform = (frame as any)?.transform ?? '';
expect(transform).not.toMatch(/NaN/);
}
}
expect(consoleErrorSpy).not.toHaveBeenCalled();
});
});
});