Skip to content

feat(textarea): add new TEDI-ready component #540 - #542

Open
ly-tempel-bitweb wants to merge 2 commits into
rcfrom
feat/540-add-textarea-tedi-ready-component
Open

feat(textarea): add new TEDI-ready component #540#542
ly-tempel-bitweb wants to merge 2 commits into
rcfrom
feat/540-add-textarea-tedi-ready-component

Conversation

@ly-tempel-bitweb

@ly-tempel-bitweb ly-tempel-bitweb commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added a TEDI-Ready textarea component with form integration, resizing, auto-grow, row limits, and height controls.
    • Added character counting and validation feedback to form fields.
    • Improved textarea styling, disabled states, and interaction behavior.
  • Documentation
    • Added usage guidance and examples for the new textarea capabilities.
    • Marked the legacy textarea component as deprecated with migration guidance.
  • Bug Fixes
    • Prevented incompatible clear buttons and icons from appearing with textareas.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ly-tempel-bitweb, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7072c399-23d2-4034-932d-053d5af6d60f

📥 Commits

Reviewing files that changed from the base of the PR and between cff425f and 86cf11f.

📒 Files selected for processing (3)
  • tedi/components/form/form-field/form-field.component.spec.ts
  • tedi/components/form/form-field/form-field.component.ts
  • tedi/components/form/textarea/textarea.component.ts
📝 Walkthrough

Walkthrough

Adds a TEDI-Ready TextareaComponent with form-control integration, resizing and auto-grow options, sizing constraints, and validation state support. Form fields now project textareas, display character counts, and suppress incompatible controls. Documentation, deprecation notices, styles, tests, and Storybook examples are included.

Changes

TEDI-Ready Textarea

Layer / File(s) Summary
Textarea control implementation
tedi/components/form/textarea/*, tedi/components/form/index.ts, tedi/components/form/textarea/textarea.component.spec.ts
Adds a standalone textarea[tedi-textarea] control implementing ControlValueAccessor and FormFieldControl, with resize, auto-grow, height, row-limit, disabled, invalid, and reactive-form behavior.
Form-field textarea integration
tedi/components/form/form-field/*
Adds textarea projection and detection, suppresses icon and clear-button behavior for textareas, derives character-limit validation, renders character counts, and updates textarea-aware styling and tests.
Textarea documentation and Storybook coverage
skills/tedi-angular/references/components.md, community/components/form/textarea/*, tedi/components/form/textarea/textarea.stories.ts
Documents the new API and migration path, marks the community textarea deprecated, and adds stories for states, sizing, character counts, height options, and form integrations.

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
Loading

Possibly related PRs

Suggested reviewers: airikej

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a new TEDI-ready textarea component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/540-add-textarea-tedi-ready-component

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ly-tempel-bitweb ly-tempel-bitweb linked an issue Jul 13, 2026 that may be closed by this pull request
21 tasks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

updateValidationState doesn't consider characterCountExceeded(), leaving aria-invalid stale on the textarea.

validationState (line 157) forces "invalid" when the character limit is exceeded, so the form-field gets a red border. However, updateValidationState calls setInvalidState based solely on NgControl status — it never includes characterCountExceeded(). As a result, control.invalid() stays false and the textarea's [attr.aria-invalid] binding evaluates to null, 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 win

Prefer Renderer2 over direct nativeElement mutation for CVA writes.

The constructor effect() (line 150-152) and setDisabledState (line 174) write directly to this.el.nativeElement. Angular's own ControlValueAccessor documentation and its built-in DefaultValueAccessor implement writeValue/setDisabledState via Renderer2.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 win

Add tests for the characterLimit feature.

The new characterLimit input, characterCount/characterCountExceeded computeds, and the character-count UI are significant FormFieldComponent additions, but no tests cover them. Consider adding cases for: character count display (current/limit), error class when exceeded, validationState becoming "invalid", and aria-invalid on the textarea when the limit is exceeded (contingent on the updateValidationState fix).

🤖 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

📥 Commits

Reviewing files that changed from the base of the PR and between 770d06e and cff425f.

📒 Files selected for processing (12)
  • community/components/form/textarea/textarea.component.ts
  • community/components/form/textarea/textarea.stories.ts
  • skills/tedi-angular/references/components.md
  • tedi/components/form/form-field/form-field.component.html
  • tedi/components/form/form-field/form-field.component.scss
  • tedi/components/form/form-field/form-field.component.spec.ts
  • tedi/components/form/form-field/form-field.component.ts
  • tedi/components/form/index.ts
  • tedi/components/form/textarea/textarea.component.scss
  • tedi/components/form/textarea/textarea.component.spec.ts
  • tedi/components/form/textarea/textarea.component.ts
  • tedi/components/form/textarea/textarea.stories.ts

class="tedi-form-field__character-count"
[class.tedi-form-field__character-count--error]="characterCountExceeded()"
>
{{ characterCount() }}/{{ characterLimit() }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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()",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to be resizing or applying height to the wrapper of the textarea not textarea itself, see here: ive resized the textarea and started typing into every row but it cuts off as if the default height applies to the textarea and resize styles apply to the wrapper:

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Textarea]: new TEDI-ready component

2 participants