Skip to content

Commit cadc33c

Browse files
committed
fix(core): update fit-text input to native field sizing
Signed-off-by: Cory Rylan <crylan@nvidia.com>
1 parent 204aa52 commit cadc33c

6 files changed

Lines changed: 62 additions & 75 deletions

File tree

Lines changed: 2 additions & 2 deletions
Loading

‎projects/core/.visual/toolbar.png‎

Lines changed: 2 additions & 2 deletions
Loading

‎projects/core/src/forms/control/control.css‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@
5353
--width: fit-content;
5454
}
5555

56+
:host([fit-text]) {
57+
--max-width: fit-content;
58+
--width: fit-content;
59+
60+
::slotted(input),
61+
::slotted(select) {
62+
field-sizing: content;
63+
}
64+
}
65+
5666
:host([nve-control]) ::slotted(input:focus),
5767
:host([nve-control]) ::slotted(select:focus),
5868
:host([nve-control]) ::slotted(textarea:focus),

‎projects/core/src/forms/control/control.test.ts‎

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -269,94 +269,105 @@ describe(`${Control.metadata.tag}: fit-text input`, () => {
269269
removeFixture(fixture);
270270
});
271271

272-
it('should set control width to input text character width',async()=>{
272+
it('should set input width to text content width',async()=>{
273+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
274+
constfitTextWidth=input.getBoundingClientRect().width;
275+
276+
element.fitText=false;
273277
awaitelementIsStable(element);
274-
expect(element.style.getPropertyValue('--control-width')).toBe(`4ch`);
278+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
279+
280+
expect(fitTextWidth).toBeLessThan(input.getBoundingClientRect().width);
275281
});
276282

277-
it('should update control width to input text character width',async()=>{
278-
awaitelementIsStable(element);
283+
it('should update input width to text content width',async()=>{
284+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
285+
constinitialWidth=input.getBoundingClientRect().width;
286+
279287
input.value='123456789012345678901234567890';
280288
input.dispatchEvent(newEvent('input'));
281289
awaitelementIsStable(element);
282-
expect(element.style.getPropertyValue('--control-width')).toBe(`30ch`);
290+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
291+
292+
expect(input.getBoundingClientRect().width).toBeGreaterThan(initialWidth);
283293
});
284294

285-
it('should update control width to input text character width with icon offset',async()=>{
286-
awaitelementIsStable(element);
295+
it('should update input width to native date content width',async()=>{
296+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
297+
consttextWidth=input.getBoundingClientRect().width;
298+
287299
input.type='date';
288300
input.value='';
289301
input.dispatchEvent(newEvent('input'));
290302
awaitelementIsStable(element);
291-
expect(element.style.getPropertyValue('--control-width')).toBe(`4ch`);
292-
expect(input.style.maxWidth).toBe(`2ch`);
303+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
304+
305+
expect(input.getBoundingClientRect().width).toBeGreaterThan(textWidth);
293306
});
294307
});
295308

296-
describe(`${Control.metadata.tag}: fit-content input`,()=>{
309+
describe(`${Control.metadata.tag}: fit-text select`,()=>{
297310
letfixture: HTMLElement;
298311
letelement: Control;
299-
letinput: HTMLInputElement;
312+
letselect: HTMLSelectElement;
300313

301314
beforeEach(async()=>{
302315
fixture=awaitcreateFixture(html`
303-
<nve-controlfit-content>
316+
<nve-controlfit-text>
304317
<label>label</label>
305-
<inputtype="text" />
318+
<select>
319+
<optionvalue="short">Short</option>
320+
<optionvalue="long">A much longer option</option>
321+
</select>
306322
</nve-control>
307323
`);
308324
element=fixture.querySelector(Control.metadata.tag);
309-
input=fixture.querySelector('input');
325+
select=fixture.querySelector('select');
310326
awaitelementIsStable(element);
311327
});
312328

313329
afterEach(()=>{
314330
removeFixture(fixture);
315331
});
316332

317-
it('should update control width to input browser default content',async()=>{
333+
it('should update select width to selected content width',async()=>{
334+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
335+
constinitialWidth=select.getBoundingClientRect().width;
336+
337+
select.value='long';
338+
select.dispatchEvent(newEvent('change'));
318339
awaitelementIsStable(element);
319-
awaitnewPromise(r=>requestAnimationFrame(r));
320-
expect(Math.floor(input.getBoundingClientRect().width)>100).toBe(true);
321-
expect(Math.floor(input.getBoundingClientRect().width)<250).toBe(true);
340+
awaitnewPromise(resolve=>requestAnimationFrame(resolve));
341+
342+
expect(select.getBoundingClientRect().width).toBeGreaterThan(initialWidth);
322343
});
323344
});
324345

325-
describe(`${Control.metadata.tag}: fit-text select`,()=>{
346+
describe(`${Control.metadata.tag}: fit-content input`,()=>{
326347
letfixture: HTMLElement;
327348
letelement: Control;
328-
letinput: HTMLSelectElement;
349+
letinput: HTMLInputElement;
329350

330351
beforeEach(async()=>{
331352
fixture=awaitcreateFixture(html`
332-
<nve-controlfit-text>
353+
<nve-controlfit-content>
333354
<label>label</label>
334-
<select>
335-
<optionvalue="1">Option 1</option>
336-
<optionvalue="2">Option 12345678</option>
337-
</select>
338-
<nve-control-message>message</nve-control-message>
355+
<inputtype="text" />
339356
</nve-control>
340357
`);
341358
element=fixture.querySelector(Control.metadata.tag);
342-
input=fixture.querySelector('select');
359+
input=fixture.querySelector('input');
343360
awaitelementIsStable(element);
344361
});
345362

346363
afterEach(()=>{
347364
removeFixture(fixture);
348365
});
349366

350-
it('should set control width to input text character width',async()=>{
351-
awaitelementIsStable(element);
352-
expect(element.style.getPropertyValue('--control-width')).toBe(`12ch`);
353-
});
354-
355-
it('should update control width to input text character width',async()=>{
356-
awaitelementIsStable(element);
357-
input.value='2';
358-
input.dispatchEvent(newEvent('change'));
367+
it('should update control width to input browser default content',async()=>{
359368
awaitelementIsStable(element);
360-
expect(element.style.getPropertyValue('--control-width')).toBe(`19ch`);
369+
awaitnewPromise(r=>requestAnimationFrame(r));
370+
expect(Math.floor(input.getBoundingClientRect().width)>100).toBe(true);
371+
expect(Math.floor(input.getBoundingClientRect().width)<250).toBe(true);
361372
});
362373
});

‎projects/core/src/forms/control/control.ts‎

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,6 @@ export class Control extends LitElement {
171171
super.disconnectedCallback();
172172
this.shadowRoot!.removeEventListener('slotchange',this.#onRootSlotchange);
173173
this.shadowRoot!.removeEventListener('slotchange',this.#onInputSlotchange);
174-
if(this.fitText&&this.input){
175-
this.input.removeEventListener('input',this.#onFitTextUpdate);
176-
this.input.removeEventListener('change',this.#onFitTextUpdate);
177-
}
178174
this.#observers.forEach(observer=>observer.disconnect());
179175
this.#observers.length=0;
180176
}
@@ -184,7 +180,6 @@ export class Control extends LitElement {
184180

185181
if(this.input&&this.#observers.length===0){
186182
this.#setupInput();
187-
this.#setupFitText();
188183
}
189184
};
190185

@@ -242,31 +237,6 @@ export class Control extends LitElement {
242237
this.#updateAssociations();
243238
};
244239

245-
#setupFitText(){
246-
if(this.fitText){
247-
this.#getCharacterWidth();
248-
this.input.addEventListener('input',this.#onFitTextUpdate);
249-
this.input.addEventListener('change',this.#onFitTextUpdate);
250-
}
251-
}
252-
253-
#onFitTextUpdate =()=>{
254-
this.#getCharacterWidth();
255-
};
256-
257-
#getCharacterWidth(){
258-
if(this.input.tagName==='INPUT'){
259-
constoffset=this.input.type!=='text' ? 4 : 0;
260-
this.style.setProperty('--control-width',`${this.input.value.length+offset}ch`);
261-
this.input.style.setProperty('max-width',`${this.input.value.length+2}ch`,'important');
262-
}elseif(this.input.tagName==='SELECT'){
263-
this.style.setProperty(
264-
'--control-width',
265-
`${(this.inputasunknownasHTMLSelectElement).options[(this.inputasunknownasHTMLSelectElement).selectedIndex]!.textContent!.length+4}ch`
266-
);
267-
}
268-
}
269-
270240
#polyfillShowPicker(){
271241
if(!this.input.showPicker){
272242
this.input.showPicker=()=>this.input.focus();

‎projects/core/src/input/input.css‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@
2222
min-width: var(--min-width);
2323
}
2424

25-
:host([fit-text]) {
26-
--max-width: fit-content;
27-
}
28-
2925
[input] {
3026
height:var(--height);
3127
background:var(--background);

0 commit comments

Comments
 (0)