From dc2102c667b2e640e99adc351ddb0597eeb2fef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20I=C3=9Fbr=C3=BCcker?= Date: Tue, 7 Jan 2025 12:55:55 +0100 Subject: [PATCH] feat: allow shrinking text area to single row (#8168) * feat: allow using single row for text area * update material theme to align single row textarea with other field components * update screenshots * update docs --- .../text-area/src/vaadin-text-area-mixin.d.ts | 2 +- packages/text-area/src/vaadin-text-area-mixin.js | 8 ++++---- packages/text-area/test/text-area.common.js | 10 +++++----- .../text-area/baseline/single-row.png | Bin 0 -> 1404 bytes .../text-area/test/visual/lumo/text-area.test.js | 8 ++++++++ .../text-area/baseline/single-row.png | Bin 0 -> 1079 bytes .../test/visual/material/text-area.test.js | 8 ++++++++ .../theme/lumo/vaadin-text-area-styles.js | 5 ++++- 8 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 packages/text-area/test/visual/lumo/screenshots/text-area/baseline/single-row.png create mode 100644 packages/text-area/test/visual/material/screenshots/text-area/baseline/single-row.png diff --git a/packages/text-area/src/vaadin-text-area-mixin.d.ts b/packages/text-area/src/vaadin-text-area-mixin.d.ts index 54042d48b14..3e01a9a7ff9 100644 --- a/packages/text-area/src/vaadin-text-area-mixin.d.ts +++ b/packages/text-area/src/vaadin-text-area-mixin.d.ts @@ -63,7 +63,7 @@ export declare class TextAreaMixinClass { pattern: string; /** - * Minimum number of rows to show. Default is two rows, which is also the minimum value. + * Minimum number of rows to show. Default is two rows. * * When using a custom slotted textarea, the minimum number of rows are not applied for backwards compatibility. * diff --git a/packages/text-area/src/vaadin-text-area-mixin.js b/packages/text-area/src/vaadin-text-area-mixin.js index 938441168ee..8f65f08c172 100644 --- a/packages/text-area/src/vaadin-text-area-mixin.js +++ b/packages/text-area/src/vaadin-text-area-mixin.js @@ -42,7 +42,7 @@ export const TextAreaMixin = (superClass) => }, /** - * Minimum number of rows to show. Default is two rows, which is also the minimum value. + * Minimum number of rows to show. Default is two rows. * * When using a custom slotted textarea, the minimum number of rows are not applied for backwards compatibility. * @@ -219,7 +219,7 @@ export const TextAreaMixin = (superClass) => // Do not override this on custom slotted textarea as number of rows may // have been configured there. if (this.inputElement === this.__textAreaController.defaultNode) { - this.inputElement.rows = Math.max(minRows, 2); + this.inputElement.rows = Math.max(minRows, 1); } } @@ -257,8 +257,8 @@ export const TextAreaMixin = (superClass) => * @private */ __minRowsChanged(minRows) { - if (minRows < 2) { - console.warn(' minRows must be at least 2.'); + if (minRows < 1) { + console.warn(' minRows must be at least 1.'); } } diff --git a/packages/text-area/test/text-area.common.js b/packages/text-area/test/text-area.common.js index 19d6d6cfc58..25dd33c2b8a 100644 --- a/packages/text-area/test/text-area.common.js +++ b/packages/text-area/test/text-area.common.js @@ -379,18 +379,18 @@ describe('text-area', () => { expect(textArea.clientHeight).to.equal(lineHeight * 4); }); - it('should not be possible to set min-height to less than two rows', async () => { + it('should be possible to set min-height to a single row', async () => { textArea.minRows = 1; await nextUpdate(textArea); - expect(textArea.clientHeight).to.closeTo(lineHeight * 2, 1); + expect(textArea.clientHeight).to.closeTo(lineHeight, 1); }); - it('should log warning when setting minRows to less than two rows', async () => { - textArea.minRows = 1; + it('should log warning when setting minRows to less than one row', async () => { + textArea.minRows = 0; await nextUpdate(textArea); - expect(console.warn).to.be.calledWith(' minRows must be at least 2.'); + expect(console.warn).to.be.calledWith(' minRows must be at least 1.'); }); it('should not log warning when setting minRows to two rows or more', async () => { diff --git a/packages/text-area/test/visual/lumo/screenshots/text-area/baseline/single-row.png b/packages/text-area/test/visual/lumo/screenshots/text-area/baseline/single-row.png new file mode 100644 index 0000000000000000000000000000000000000000..be4a77b40dde5374c6afb29c54a17a508d6f65b1 GIT binary patch literal 1404 zcmai!X*?4Q9LJX)Dn+5lk!$2?JcLnm?U`d@n?0V#F@z|Ome^vCD@Pxm?U6IgIiqr= zoO@`lO_(E-3>9l7JY}mn(n8Oqx6ko;Ui|*Q7rz((-<#i;ghDvWNUKN#000@d3k<#M zoL$-Pm)gC-20re)wg-=Ph5{b2)!qRBl9q6ogXgbh@3~1X`2+xKwSDS?p-q_9-3c5C zQT$eAxI`ht9&*VWTE`h+h{O7*a*DJRCNaEukpaq)bWQ4@suX1b3xl-q^n4wqkSYwu zDtbA!wE$^1r$Mh~3lP0t;?G?Sy9A2K_IUchEgoABjqKgX>FE`&u1s9`s1;p2EFmFL z1SZHj98?NykF9_wx1Z;A@OF~VQaTkV)S+v%A-SQ1?Q;Q{8(RiEZoEhjqLusZF*%;c zr>fh=K`MudZiJq>?SOrEXWYy%n>gX+0_4BG{?@EI1VtG^!d=Jiv@JT0!>S8!}0(EeRyFX)s8(r&q^u?|AE&MASTqxi)2cCW&w zq|%H#9JdyNV&qa>#e`9Q-IWke-pU64=7F30LV>oR%)kf~KKfba9D3B}pk;)w^Y<%! zNAUYfWr0mh&Kr%I=7xc>6w$d3%i&hAk`UOrBGnkdW367;T3~659Yt1XyT{CdE594+mDal%b!Yn3)7KYfN`E2`2Gp+X zt>}>umWP$ilF`0%44ODv=LM$Dq;>zxe5b0!Fk($XeFn{Z%Kr_Sf>=&c{c^I&f^_+l z-_=+9k{=n59L|36d{s%EVY>Qg^qT3s#iW${XVO)ph*hou80!vbk>{51?3FQ+8_LEs>COynfp3$f zW%?#3ARk_@7#ysK~v>em9cQQ#Diw zhq#x4aHoT{OivY;SzLOSw58b@?}vpSWCcY(^?N?pGN&fLk#IE~1I2EsT4C=IWj1$! zIY8~S`xw=Szc?bsMU|3BBU`-BTSx4b{=_)*xr-uX4h>F@@+{HH$`*O`@OCEjea0dpg(pSvtB zy6v?5)}S4emgKeFB|aT|f=i&-xP+uj9|%~OvPwil|8tmKvWA+PjEeOm#VrXBMcuOD zFa2zah6M|w-NKC_hUB`QxpMA1_P5n%tEY%{Yagp$-yu`A*RXLxI{$#o|1jvUy$bAm U(?SQObGtYNz#S2=2hhOOuYGi)(f|Me literal 0 HcmV?d00001 diff --git a/packages/text-area/test/visual/lumo/text-area.test.js b/packages/text-area/test/visual/lumo/text-area.test.js index cc09d18af46..20fda27c7e4 100644 --- a/packages/text-area/test/visual/lumo/text-area.test.js +++ b/packages/text-area/test/visual/lumo/text-area.test.js @@ -130,4 +130,12 @@ describe('text-area', () => { element.maxRows = 4; await visualDiff(div, 'max-rows'); }); + + it('single-row', async () => { + element.minRows = 1; + element.value = 'value'; + element.clearButtonVisible = true; + + await visualDiff(div, 'single-row'); + }); }); diff --git a/packages/text-area/test/visual/material/screenshots/text-area/baseline/single-row.png b/packages/text-area/test/visual/material/screenshots/text-area/baseline/single-row.png new file mode 100644 index 0000000000000000000000000000000000000000..ff964517a866312c16a948529b2a52a480b30f0a GIT binary patch literal 1079 zcmeAS@N?(olHy`uVBq!ia0vp^SAf`sgAGXj+#wweq!^2X+?^QKos)UVz`*>`)5S5Q zV$R!Jian3KWR8D)zt^VGB}~a($vrHr&n3*vGPu(v>{?7vWMt=>HEU!#U6iz6S0ueJ zDtJHbz`OeIaTWXhH=WeuNi}=uy_`Az-1EKCk2ta~=Ot43+=!Y3!s_*|A<{7&)<8<*F-Q<*s{SG7GX$-dwa9cuD; ztz&+1dBAbK<4>#CEi?EkqIW^A?v8=*ZQa>d9?nrey?XZlh#Z-9FJ`XG|8sp)L7(nz z->%}mlFdu4&wTfb{+BK!e+Gx(7ff_cHGN@TT~%=VPwLIIhcU*`XQB~JR?zwCh}0fVQjpUXO@geCwC!2g5* literal 0 HcmV?d00001 diff --git a/packages/text-area/test/visual/material/text-area.test.js b/packages/text-area/test/visual/material/text-area.test.js index 083a987e9ab..845efb0c3e1 100644 --- a/packages/text-area/test/visual/material/text-area.test.js +++ b/packages/text-area/test/visual/material/text-area.test.js @@ -132,4 +132,12 @@ describe('text-area', () => { element.maxRows = 4; await visualDiff(div, 'max-rows'); }); + + it('single-row', async () => { + element.minRows = 1; + element.value = 'value'; + element.clearButtonVisible = true; + + await visualDiff(div, 'single-row'); + }); }); diff --git a/packages/text-area/theme/lumo/vaadin-text-area-styles.js b/packages/text-area/theme/lumo/vaadin-text-area-styles.js index ac322f9c39a..7594635e80b 100644 --- a/packages/text-area/theme/lumo/vaadin-text-area-styles.js +++ b/packages/text-area/theme/lumo/vaadin-text-area-styles.js @@ -15,6 +15,7 @@ const textArea = css` [part='input-field'] ::slotted(textarea) { height: auto; box-sizing: border-box; + min-height: 0; } [part='input-field'] { @@ -64,11 +65,13 @@ const textArea = css` align-self: flex-start; } - /* Vertically align icon prefix/suffix/clear button with the first line of text */ [part='input-field'] ::slotted(vaadin-icon[slot$='fix']), [part='clear-button'] { + /* Vertically align icon prefix/suffix/clear button with the first line of text */ top: calc((var(--lumo-icon-size-m) - 1em * var(--lumo-line-height-s)) / -2); margin-top: calc((var(--lumo-icon-size-m) - 1em * var(--lumo-line-height-s)) / -2); + /* Reduce effective height to match line height of native textarea, so icons don't increase component size when using single row */ + margin-bottom: calc((var(--lumo-icon-size-m) - 1em * var(--lumo-line-height-s)) / -2); } `;