feat(textarea): add new TEDI-ready component #540 - #542
Conversation
|
Warning Review limit reached
Next review available in: 31 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a TEDI-Ready ChangesTEDI-Ready Textarea
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant FormFieldComponent
participant TextareaComponent
participant AngularForms
FormFieldComponent->>TextareaComponent: project and detect textarea control
AngularForms->>TextareaComponent: write value or disabled state
TextareaComponent->>AngularForms: emit changes and touched state
FormFieldComponent->>FormFieldComponent: compute character count and validation state
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tedi/components/form/form-field/form-field.component.ts (1)
128-135: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
updateValidationStatedoesn't considercharacterCountExceeded(), leavingaria-invalidstale on the textarea.
validationState(line 157) forces"invalid"when the character limit is exceeded, so the form-field gets a red border. However,updateValidationStatecallssetInvalidStatebased solely onNgControlstatus — it never includescharacterCountExceeded(). As a result,control.invalid()staysfalseand the textarea's[attr.aria-invalid]binding evaluates tonull, creating a mismatch between the visual error state and the ARIA state.🔧 Proposed fix
private updateValidationState() { const invalid = !!this.ngControl?.invalid; const touched = !!this.ngControl?.touched; const dirty = !!this.ngControl?.dirty; - const fieldInvalid = invalid && (touched || dirty); + const fieldInvalid = + (invalid && (touched || dirty)) || this.characterCountExceeded(); this.control?.setInvalidState(fieldInvalid); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tedi/components/form/form-field/form-field.component.ts` around lines 128 - 135, Update updateValidationState to include characterCountExceeded() when computing fieldInvalid, so setInvalidState reflects the same forced-invalid condition used by validationState and keeps the textarea’s aria-invalid state synchronized with its visual validation state.
🧹 Nitpick comments (2)
tedi/components/form/textarea/textarea.component.ts (1)
143-175: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPrefer
Renderer2over directnativeElementmutation for CVA writes.The constructor
effect()(line 150-152) andsetDisabledState(line 174) write directly tothis.el.nativeElement. Angular's ownControlValueAccessordocumentation and its built-inDefaultValueAccessorimplementwriteValue/setDisabledStateviaRenderer2.setProperty(...)rather than direct DOM mutation, precisely to avoid tight coupling to the DOM renderer (relevant for SSR/testing/Web Worker rendering).♻️ Suggested refactor using Renderer2
-import { ChangeDetectionStrategy, Component, computed, effect, ElementRef, forwardRef, inject, input, model, signal, ViewEncapsulation } from "`@angular/core`"; +import { ChangeDetectionStrategy, Component, computed, effect, ElementRef, forwardRef, inject, input, model, Renderer2, signal, ViewEncapsulation } from "`@angular/core`"; ... private el = inject<ElementRef<HTMLTextAreaElement>>(ElementRef); + private renderer = inject(Renderer2); ... constructor() { effect(() => { const value = this.value(); if (this.el.nativeElement.value !== value) { - this.el.nativeElement.value = value; + this.renderer.setProperty(this.el.nativeElement, "value", value); } }); } ... setDisabledState(isDisabled: boolean): void { this.formDisabled.set(isDisabled); - this.el.nativeElement.disabled = isDisabled; + this.renderer.setProperty(this.el.nativeElement, "disabled", isDisabled); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tedi/components/form/textarea/textarea.component.ts` around lines 143 - 175, Replace direct DOM property assignments in the constructor effect and setDisabledState with Renderer2.setProperty calls, using the existing element reference and preserving the current value and disabled-state behavior. Inject or reuse Renderer2 in the component and keep writeValue/setValue and form-control callbacks unchanged.tedi/components/form/form-field/form-field.component.spec.ts (1)
232-280: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd tests for the
characterLimitfeature.The new
characterLimitinput,characterCount/characterCountExceededcomputeds, and the character-count UI are significantFormFieldComponentadditions, but no tests cover them. Consider adding cases for: character count display (current/limit), error class when exceeded,validationStatebecoming"invalid", andaria-invalidon the textarea when the limit is exceeded (contingent on theupdateValidationStatefix).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tedi/components/form/form-field/form-field.component.spec.ts` around lines 232 - 280, Add FormFieldComponent tests covering the characterLimit input and characterCount/characterCountExceeded computeds: verify the UI displays current/limit text, applies the error class when the limit is exceeded, reports validationState as "invalid", and sets aria-invalid on the projected textarea after the validation-state update. Extend the existing textarea host fixture or add focused hosts with values below and above the limit, and assert each exposed behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@tedi/components/form/form-field/form-field.component.ts`:
- Around line 128-135: Update updateValidationState to include
characterCountExceeded() when computing fieldInvalid, so setInvalidState
reflects the same forced-invalid condition used by validationState and keeps the
textarea’s aria-invalid state synchronized with its visual validation state.
---
Nitpick comments:
In `@tedi/components/form/form-field/form-field.component.spec.ts`:
- Around line 232-280: Add FormFieldComponent tests covering the characterLimit
input and characterCount/characterCountExceeded computeds: verify the UI
displays current/limit text, applies the error class when the limit is exceeded,
reports validationState as "invalid", and sets aria-invalid on the projected
textarea after the validation-state update. Extend the existing textarea host
fixture or add focused hosts with values below and above the limit, and assert
each exposed behavior.
In `@tedi/components/form/textarea/textarea.component.ts`:
- Around line 143-175: Replace direct DOM property assignments in the
constructor effect and setDisabledState with Renderer2.setProperty calls, using
the existing element reference and preserving the current value and
disabled-state behavior. Inject or reuse Renderer2 in the component and keep
writeValue/setValue and form-control callbacks unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f70510d0-5bbc-4bb2-914c-f49d5d0700ed
📒 Files selected for processing (12)
community/components/form/textarea/textarea.component.tscommunity/components/form/textarea/textarea.stories.tsskills/tedi-angular/references/components.mdtedi/components/form/form-field/form-field.component.htmltedi/components/form/form-field/form-field.component.scsstedi/components/form/form-field/form-field.component.spec.tstedi/components/form/form-field/form-field.component.tstedi/components/form/index.tstedi/components/form/textarea/textarea.component.scsstedi/components/form/textarea/textarea.component.spec.tstedi/components/form/textarea/textarea.component.tstedi/components/form/textarea/textarea.stories.ts
| class="tedi-form-field__character-count" | ||
| [class.tedi-form-field__character-count--error]="characterCountExceeded()" | ||
| > | ||
| {{ characterCount() }}/{{ characterLimit() }} |
There was a problem hiding this comment.
check if this is visible to assistive tech
| class: "tedi-textarea", | ||
| "[class.tedi-textarea--not-resizable]": "!resizable()", | ||
| "[class.tedi-textarea--auto-grow]": "autoGrow()", | ||
| "[style.height]": "heightStyle()", |
There was a problem hiding this comment.

Summary by CodeRabbit