diff --git a/core/src/components.d.ts b/core/src/components.d.ts index f2b1fbe72e..155cfbff9a 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -2803,7 +2803,7 @@ export namespace Components { } interface IonTextarea { /** - * If `true`, the element height will increase based on the value. + * If `true`, the textarea container will grow and shrink based on the contents of the textarea. */ "autoGrow": boolean; /** @@ -6786,7 +6786,7 @@ declare namespace LocalJSX { } interface IonTextarea { /** - * If `true`, the element height will increase based on the value. + * If `true`, the textarea container will grow and shrink based on the contents of the textarea. */ "autoGrow"?: boolean; /** diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts b/core/src/components/textarea/test/autogrow/textarea.e2e.ts index a7280fba64..60025be53a 100644 --- a/core/src/components/textarea/test/autogrow/textarea.e2e.ts +++ b/core/src/components/textarea/test/autogrow/textarea.e2e.ts @@ -2,11 +2,9 @@ import { expect } from '@playwright/test'; import { test } from '@utils/test/playwright'; test.describe('textarea: autogrow', () => { - test.skip('should not have visual regressions', async ({ page }) => { + test('should not have visual regressions', async ({ page }) => { await page.goto(`/src/components/textarea/test/autogrow`); - await page.waitForChanges(); - await page.setIonViewport(); expect(await page.screenshot()).toMatchSnapshot(`textarea-autogrow-diff-${page.getSnapshotSettings()}.png`); diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..2342f2b018 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..dc304f16b0 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Safari-linux.png new file mode 100644 index 0000000000..1925bd6672 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..177f1fd621 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Chrome-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..41dde72b3a Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Firefox-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Safari-linux.png new file mode 100644 index 0000000000..e9458501d1 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-ios-rtl-Mobile-Safari-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..e71666b4fc Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..11f1048045 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 0000000000..debd228585 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..5ab31bfdf7 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Chrome-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..efcccc036b Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Firefox-linux.png differ diff --git a/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Safari-linux.png new file mode 100644 index 0000000000..7ac556d249 Binary files /dev/null and b/core/src/components/textarea/test/autogrow/textarea.e2e.ts-snapshots/textarea-autogrow-diff-md-rtl-Mobile-Safari-linux.png differ diff --git a/core/src/components/textarea/test/basic/index.html b/core/src/components/textarea/test/basic/index.html index 30352e0310..93def8b9f4 100644 --- a/core/src/components/textarea/test/basic/index.html +++ b/core/src/components/textarea/test/basic/index.html @@ -67,12 +67,6 @@ Clear on Edit - - -
diff --git a/core/src/components/textarea/textarea.scss b/core/src/components/textarea/textarea.scss index 15203a1986..eac5f8bc23 100644 --- a/core/src/components/textarea/textarea.scss +++ b/core/src/components/textarea/textarea.scss @@ -26,7 +26,7 @@ --placeholder-color: initial; --placeholder-font-style: initial; --placeholder-font-weight: initial; - --placeholder-opacity: .5; + --placeholder-opacity: 0.5; --padding-top: 0; --padding-end: 0; --padding-bottom: 0; @@ -71,22 +71,41 @@ --padding-start: 0; } - // Native Textarea // -------------------------------------------------- .textarea-wrapper { + display: grid; + min-width: inherit; max-width: inherit; min-height: inherit; max-height: inherit; + + &::after { + // This technique is used for an auto-resizing textarea. + // The text contents are reflected as a pseudo-element that is visually hidden. + // This causes the textarea container to grow as needed to fit the contents. + + white-space: pre-wrap; + + content: attr(data-replicated-value) " "; + + visibility: hidden; + } +} + +.native-textarea, +.textarea-wrapper::after { + @include padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start)); + @include text-inherit(); + + grid-area: 1 / 1 / 2 / 2; } .native-textarea { @include border-radius(var(--border-radius)); @include margin(0); - @include padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start)); - @include text-inherit(); display: block; @@ -103,6 +122,8 @@ resize: none; appearance: none; + overflow: hidden; + &::placeholder { @include padding(0); @@ -117,7 +138,7 @@ } .native-textarea[disabled] { - opacity: .4; + opacity: 0.4; } // Input Cover: Unfocused @@ -136,6 +157,15 @@ pointer-events: none; } +:host([auto-grow]) .cloned-input { + // Workaround for webkit rendering issue with scroll assist. + // When cloning the textarea and scrolling into view, + // a white box is rendered from the difference in height + // from the auto grow container. + // This change forces the cloned input to match the true + // height of the textarea container. + height: 100%; +} // Item Floating: Placeholder // ---------------------------------------------------------------- diff --git a/core/src/components/textarea/textarea.tsx b/core/src/components/textarea/textarea.tsx index 41d34c02e7..57d00b6f7c 100644 --- a/core/src/components/textarea/textarea.tsx +++ b/core/src/components/textarea/textarea.tsx @@ -1,10 +1,10 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core'; -import { Build, Component, Element, Event, Host, Method, Prop, State, Watch, h, readTask } from '@stencil/core'; +import { Build, Component, Element, Event, Host, Method, Prop, State, Watch, h, writeTask } from '@stencil/core'; import { getIonMode } from '../../global/ionic-global'; import type { Color, StyleEventDetail, TextareaChangeEventDetail } from '../../interface'; import type { Attributes } from '../../utils/helpers'; -import { inheritAriaAttributes, debounceEvent, findItemLabel, inheritAttributes, raf } from '../../utils/helpers'; +import { inheritAriaAttributes, debounceEvent, findItemLabel, inheritAttributes } from '../../utils/helpers'; import { createColorClasses } from '../../utils/theme'; /** @@ -147,9 +147,10 @@ export class Textarea implements ComponentInterface { @Prop() wrap?: 'hard' | 'soft' | 'off'; /** - * If `true`, the element height will increase based on the value. + * If `true`, the textarea container will grow and shrink based + * on the contents of the textarea. */ - @Prop() autoGrow = false; + @Prop({ reflect: true }) autoGrow = false; /** * The value of the textarea. @@ -227,20 +228,7 @@ export class Textarea implements ComponentInterface { } componentDidLoad() { - raf(() => this.runAutoGrow()); - } - - private runAutoGrow() { - const nativeInput = this.nativeInput; - if (nativeInput && this.autoGrow) { - readTask(() => { - nativeInput.style.height = 'auto'; - nativeInput.style.height = nativeInput.scrollHeight + 'px'; - if (this.textareaWrapper) { - this.textareaWrapper.style.height = nativeInput.scrollHeight + 'px'; - } - }); - } + this.runAutoGrow(); } /** @@ -286,6 +274,18 @@ export class Textarea implements ComponentInterface { }); } + private runAutoGrow() { + if (this.nativeInput && this.autoGrow) { + writeTask(() => { + if (this.textareaWrapper) { + // Replicated value is an attribute to be used in the stylesheet + // to set the inner contents of a pseudo element. + this.textareaWrapper.dataset.replicatedValue = this.value ?? ''; + } + }); + } + } + /** * Check if we need to clear the text input if clearOnEdit is enabled */