Skip to content
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

feat: configure minimum number of rows in text area #8138

Merged
merged 5 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
6 changes: 6 additions & 0 deletions packages/text-area/src/vaadin-text-area-mixin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ export declare class TextAreaMixinClass {
*/
pattern: string;

/**
* Minimum number of rows to show. Default is two rows, which is also the minimum value.
* @attr {number} min-rows
*/
minRows: number;

/**
* Scrolls the textarea to the start if it has a vertical scrollbar.
*/
Expand Down
43 changes: 35 additions & 8 deletions packages/text-area/src/vaadin-text-area-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ export const TextAreaMixin = (superClass) =>
pattern: {
type: String,
},

/**
* Minimum number of rows to show. Default is two rows, which is also the minimum value.
* @attr {number} min-rows
*/
minRows: {
type: Number,
value: 2,
},
};
}

Expand All @@ -51,6 +60,10 @@ export const TextAreaMixin = (superClass) =>
return [...super.constraints, 'maxlength', 'minlength', 'pattern'];
}

static get observers() {
return ['__updateMinHeight(minRows, inputElement, _inputField)'];
web-padawan marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Used by `InputControlMixin` as a reference to the clear button element.
* @protected
Expand All @@ -77,14 +90,13 @@ export const TextAreaMixin = (superClass) =>
ready() {
super.ready();

this.addController(
new TextAreaController(this, (input) => {
this._setInputElement(input);
this._setFocusElement(input);
this.stateTarget = input;
this.ariaTarget = input;
}),
);
this.__textAreaController = new TextAreaController(this, (input) => {
this._setInputElement(input);
this._setFocusElement(input);
this.stateTarget = input;
this.ariaTarget = input;
});
this.addController(this.__textAreaController);
this.addController(new LabelledInputController(this.inputElement, this._labelController));

this.addEventListener('animationend', this._onAnimationEnd);
Expand Down Expand Up @@ -178,6 +190,21 @@ export const TextAreaMixin = (superClass) =>
inputField.scrollTop = scrollTop;
}

/** @private */
__updateMinHeight(minRows) {
if (!this._inputField || !this.inputElement) {
return;
}

// For minimum height, just set the number of rows on the native textarea,
// which causes the input container to grow as well.
// Do not override this on custom slotted textarea as number of rows may
// have been configured there.
if (this.inputElement === this.__textAreaController.defaultNode) {
web-padawan marked this conversation as resolved.
Show resolved Hide resolved
this.inputElement.rows = Math.max(minRows, 2);
web-padawan marked this conversation as resolved.
Show resolved Hide resolved
}
}

/**
* Scrolls the textarea to the start if it has a vertical scrollbar.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ snapshots["vaadin-text-area host default"] =
</div>
<textarea
id="textarea-vaadin-text-area-3"
rows="2"
slot="textarea"
>
</textarea>
Expand All @@ -41,6 +42,7 @@ snapshots["vaadin-text-area host helper"] =
<textarea
aria-describedby="helper-vaadin-text-area-1"
id="textarea-vaadin-text-area-3"
rows="2"
slot="textarea"
>
</textarea>
Expand Down Expand Up @@ -77,6 +79,7 @@ snapshots["vaadin-text-area host error"] =
aria-invalid="true"
id="textarea-vaadin-text-area-3"
invalid=""
rows="2"
slot="textarea"
>
</textarea>
Expand Down
50 changes: 50 additions & 0 deletions packages/text-area/test/text-area.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,56 @@ describe('text-area', () => {
);
});

describe('min rows', () => {
const lineHeight = 20;
beforeEach(async () => {
const fixture = fixtureSync(`
<div>
<style>
vaadin-text-area textarea {
line-height: ${lineHeight}px;
}
</style>
<vaadin-text-area></vaadin-text-area>
</div>
`);
textArea = fixture.querySelector('vaadin-text-area');
await nextUpdate(textArea);
});

it('should use min-height of two rows by default', () => {
expect(textArea.clientHeight).to.equal(lineHeight * 2);
});

it('should use min-height based on minimum rows', async () => {
textArea.minRows = 4;
await nextUpdate(textArea);

expect(textArea.clientHeight).to.equal(lineHeight * 4);
});

it('should not be possible to set min-height to less than two rows', async () => {
textArea.minRows = 1;
await nextUpdate(textArea);

expect(textArea.clientHeight).to.closeTo(lineHeight * 2, 1);
});

it('should not overwrite rows on custom slotted textarea', async () => {
const custom = document.createElement('textarea');
custom.setAttribute('slot', 'textarea');
custom.rows = 1;
textArea.appendChild(custom);
await nextUpdate(textArea);

textArea.minRows = 4;
await nextUpdate(textArea);

expect(custom.rows).to.equal(1);
expect(textArea.clientHeight).to.closeTo(lineHeight, 1);
});
});

describe('--_text-area-vertical-scroll-position CSS variable', () => {
function wheel({ element = inputField, deltaY = 0 }) {
const e = new CustomEvent('wheel', { bubbles: true, cancelable: true });
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions packages/text-area/test/visual/lumo/text-area.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,10 @@ describe('text-area', () => {
element.appendChild(span);
await visualDiff(div, 'suffix');
});

it('min-rows', async () => {
element.value = 'value';
element.minRows = 4;
await visualDiff(div, 'min-rows');
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions packages/text-area/test/visual/material/text-area.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,10 @@ describe('text-area', () => {
element.appendChild(span);
await visualDiff(div, 'suffix');
});

it('min-rows', async () => {
element.value = 'value';
element.minRows = 4;
await visualDiff(div, 'min-rows');
});
});