Pending Review
Pending Review from User Experience (UX)
Textarea Component
Overview
The PWC Textarea component provides a multi-line text input interface with comprehensive validation, accessibility features, and responsive design capabilities. Built on standard HTML textarea elements with enhanced functionality including character limits, clear actions, and seamless form integration for collecting extended text content and user feedback.
Core Capabilities
- Multi-line Text Input - Native textarea element with customizable rows, character limits, and automatic text wrapping for extended content
- Built-in Clear Action - Optional clear button with close icon for quick content removal and user convenience
- Length Validation - Support for minimum and maximum character limits with real-time validation feedback and user guidance
- Accessibility Support - ARIA attributes, keyboard navigation, screen reader compatibility, and focus management for inclusive design
- Form Integration - Seamless PWC form context integration with validation states, error handling, and data synchronization
- Loading State Management - Skeleton rendering during form initialization and data loading operations with appropriate visual feedback
When to use Textarea:
- Extended text input scenarios requiring multiple lines such as comments, descriptions, feedback, and detailed responses
- Form fields where users need to provide lengthy explanations, detailed information, or multi-paragraph content
- Content creation interfaces where users compose messages, notes, documentation, or other substantial text content
- Data collection forms requiring open-ended responses with flexible input length and formatting requirements
When not to use Textarea:
- Single-line text input where regular input components provide better user experience and visual consistency
- Structured data entry where specific input types (email, number, date) offer better validation and user guidance
- Short responses or simple values where textarea height creates unnecessary vertical space and visual complexity
Basic Implementation
import { PwcButton, PwcForm, PwcTextarea, PwcSubmitEvent } from "@progress-i360/pwc-react";
import { useState } from 'react';
function ProductFeedbackForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = (event: Event) => {
const detail = (event as PwcSubmitEvent).detail;
setIsSubmitting(true);
setTimeout(() => {
setIsSubmitting(false);
detail.success();
}, 2000);
};
return (
<PwcForm onPwcSubmit={handleSubmit}>
<PwcTextarea
name="generalFeedback"
label="General Feedback"
placeholder="Share your overall experience with our product..."
maxLength={500}
required
hint="Help us understand what's working well and what could be improved"
clear
/>
<PwcTextarea
name="suggestions"
label="Improvement Suggestions"
placeholder="What improvements or new features would you like to see?"
maxLength={750}
hint="Optional: Help us prioritize future development"
clear
/>
<PwcButton
type="submit"
variant="primary"
label={isSubmitting ? 'Submitting...' : 'Submit Feedback'}
disabled={isSubmitting}
/>
</PwcForm>
);
}
import { useEffect, useRef, useState } from 'react';
import '@progress-i360/progress-web-components/button';
import '@progress-i360/progress-web-components/form';
import '@progress-i360/progress-web-components/textarea';
type TextareaElement = HTMLElement & {
value?: string;
required?: boolean;
maxLength?: number;
minLength?: number;
clear?: boolean;
disabled?: boolean;
};
type ButtonElement = HTMLElement & {
label?: string;
disabled?: boolean;
variant?: string;
};
type PwcSubmitDetail = {
payload: Record<string, unknown>;
success: () => void;
};
const DRAFT_STORAGE_KEY = 'ticketDraft';
function SupportTicketForm() {
const formRef = useRef<HTMLElement | null>(null);
const descriptionRef = useRef<TextareaElement | null>(null);
const contextRef = useRef<TextareaElement | null>(null);
const submitButtonRef = useRef<ButtonElement | null>(null);
const [formData, setFormData] = useState({
description: '',
additionalContext: ''
});
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(() => {
const timer = setTimeout(() => {
if (formData.description || formData.additionalContext) {
localStorage.setItem(DRAFT_STORAGE_KEY, JSON.stringify(formData));
}
}, 1000);
return () => clearTimeout(timer);
}, [formData]);
useEffect(() => {
const textarea = descriptionRef.current;
if (!textarea) {
return;
}
textarea.value = formData.description;
textarea.required = true;
textarea.maxLength = 1000;
textarea.minLength = 25;
textarea.clear = true;
textarea.disabled = isSubmitting;
const handleChange = (event: Event) => {
const detail = (event as CustomEvent<string>).detail ?? '';
setFormData((previous) => ({ ...previous, description: detail }));
};
textarea.addEventListener('pwc-change', handleChange);
return () => {
textarea.removeEventListener('pwc-change', handleChange);
};
}, [formData.description, isSubmitting]);
useEffect(() => {
const textarea = contextRef.current;
if (!textarea) {
return;
}
textarea.value = formData.additionalContext;
textarea.maxLength = 800;
textarea.clear = true;
textarea.disabled = isSubmitting;
const handleChange = (event: Event) => {
const detail = (event as CustomEvent<string>).detail ?? '';
setFormData((previous) => ({ ...previous, additionalContext: detail }));
};
textarea.addEventListener('pwc-change', handleChange);
return () => {
textarea.removeEventListener('pwc-change', handleChange);
};
}, [formData.additionalContext, isSubmitting]);
useEffect(() => {
const button = submitButtonRef.current;
if (!button) {
return;
}
button.label = isSubmitting ? 'Submitting...' : 'Submit Ticket';
button.disabled = isSubmitting;
button.variant = 'primary';
}, [isSubmitting]);
useEffect(() => {
const formElement = formRef.current;
if (!formElement) {
return;
}
const handleSubmit = (event: Event) => {
const submitDetail = (event as CustomEvent<PwcSubmitDetail>).detail;
if (!submitDetail || isSubmitting) {
return;
}
setIsSubmitting(true);
setTimeout(() => {
submitDetail.success();
setIsSubmitting(false);
localStorage.removeItem(DRAFT_STORAGE_KEY);
}, 2000);
};
formElement.addEventListener('pwc-submit', handleSubmit as EventListener);
return () => {
formElement.removeEventListener('pwc-submit', handleSubmit as EventListener);
};
}, [isSubmitting]);
return (
<pwc-form ref={formRef}>
<pwc-textarea
ref={descriptionRef}
name="description"
label="Issue Description"
placeholder="Describe the problem you're experiencing..."
hint="Provide a detailed description (minimum 25 characters)"
></pwc-textarea>
<pwc-textarea
ref={contextRef}
name="additionalContext"
label="Additional Context"
placeholder="Browser version, OS, error messages, screenshots, etc."
hint="Any additional information that might be helpful"
></pwc-textarea>
<pwc-button ref={submitButtonRef} type="submit"></pwc-button>
</pwc-form>
);
}
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@progress-i360/progress-web-components/button";
import "@progress-i360/progress-web-components/textarea";
@Component({
selector: 'textarea-demo',
template: `
<pwc-textarea
label="Project Description"
placeholder="Describe your project in detail..."
[maxLength]="500"
[minLength]="10"
required
hint="Provide a clear overview of your project goals and requirements"
(pwc-change)="updateDescription($event)"
(pwc-input)="trackProgress($event)">
</pwc-textarea>
<pwc-textarea
label="Additional Comments"
placeholder="Any additional thoughts or questions?"
[maxLength]="1000"
hint="Optional: Share any other relevant information"
[disabled]="!isDescriptionValid"
(pwc-change)="updateComments($event)">
</pwc-textarea>
<pwc-textarea
label="Technical Requirements"
placeholder="List technical specifications, constraints, or dependencies..."
[maxLength]="2000"
[readOnly]="isReadOnly"
[border]="true"
hint="Detailed technical information for development team"
(pwc-change)="updateRequirements($event)">
</pwc-textarea>
<div class="character-counter" *ngIf="showProgress">
<p>Description: {{ descriptionLength }}/{{ maxDescriptionLength }} characters</p>
<p>Progress: {{ getCompletionPercentage() }}% complete</p>
</div>
<div class="form-actions" *ngIf="hasContent">
<pwc-button
label="Clear All"
variant="outline"
(pwc-click)="clearAllFields()">
</pwc-button>
<pwc-button
label="Save Draft"
variant="primary"
[disabled]="!canSave"
(pwc-click)="saveDraft()">
</pwc-button>
</div>
`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class TextareaDemo {
projectDescription = '';
additionalComments = '';
technicalRequirements = '';
descriptionLength = 0;
maxDescriptionLength = 500;
isReadOnly = false;
get isDescriptionValid() {
return this.projectDescription.length >= 10;
}
get showProgress() {
return this.descriptionLength > 0;
}
get hasContent() {
return this.projectDescription || this.additionalComments || this.technicalRequirements;
}
get canSave() {
return this.isDescriptionValid && this.projectDescription.length <= this.maxDescriptionLength;
}
updateDescription(event: CustomEvent<string>) {
this.projectDescription = event.detail || '';
this.descriptionLength = this.projectDescription.length;
// Auto-enable technical requirements when description is substantial
if (this.descriptionLength > 100) {
this.isReadOnly = false;
}
}
trackProgress(event: CustomEvent<string>) {
this.descriptionLength = (event.detail || '').length;
}
updateComments(event: CustomEvent<string>) {
this.additionalComments = event.detail || '';
}
updateRequirements(event: CustomEvent<string>) {
this.technicalRequirements = event.detail || '';
}
getCompletionPercentage(): number {
let completed = 0;
let total = 3;
if (this.isDescriptionValid) completed++;
if (this.additionalComments.length > 0) completed++;
if (this.technicalRequirements.length > 0) completed++;
return Math.round((completed / total) * 100);
}
clearAllFields() {
this.projectDescription = '';
this.additionalComments = '';
this.technicalRequirements = '';
this.descriptionLength = 0;
this.isReadOnly = false;
}
saveDraft() {
const draft = {
description: this.projectDescription,
comments: this.additionalComments,
requirements: this.technicalRequirements,
timestamp: new Date()
};
console.log('Saving draft:', draft);
// Simulate API call
setTimeout(() => {
alert('Draft saved successfully!');
}, 500);
}
}
import '@progress-i360/progress-web-components/textarea';
// Create textarea for feedback with character limit
const feedbackTextarea = document.createElement('pwc-textarea');
feedbackTextarea.label = 'Your Feedback';
feedbackTextarea.placeholder = 'Please share your thoughts...';
feedbackTextarea.name = 'feedback';
feedbackTextarea.maxLength = 250;
feedbackTextarea.required = true;
feedbackTextarea.addEventListener('pwc-change', (event) => {
console.log('Feedback updated:', event.detail);
});
document.body.appendChild(feedbackTextarea);
Usage Patterns
- Form Content Input - Extended text fields for comments, descriptions, feedback, and other multi-line content requiring user input
- Message Composition - Email drafts, chat messages, notes, and other communication content with flexible formatting needs
- Data Collection Interfaces - Survey responses, application forms, and user-generated content requiring detailed text input
- Content Management Systems - Article drafts, documentation editing, and content creation tools with validation and character limits
Best Practices
Content Strategy Guidelines
- Clear Labeling - Use descriptive labels that clearly indicate the expected content type, format, and purpose of the text input
- Helpful Placeholder Text - Provide example content or guidance that demonstrates the expected input format and style
- Character Limit Guidance - Set appropriate minimum and maximum character limits with clear messaging about requirements and constraints
- Contextual Hints - Use hint text to provide additional guidance, formatting requirements, or examples of good input
Performance Optimization
- Debounced Validation - Implement input debouncing to prevent excessive validation calls during rapid typing and user input
- Efficient Change Handling - Use optimized event handling patterns to manage text updates and form synchronization effectively
- Memory Management - Properly handle large text content and component cleanup to prevent memory leaks in long-running applications
- Loading State Integration - Implement skeleton states and loading indicators during form initialization and data operations
Integration Architecture
- Form Context Coordination - Integrate seamlessly with PWC form systems for validation, error handling, and data management workflows
- Validation Strategy Design - Implement comprehensive validation patterns that handle text length, format requirements, and content rules
- Accessibility Standards - Ensure proper ARIA labeling, keyboard navigation, and screen reader compatibility for inclusive user experiences
- Error Handling Patterns - Provide clear validation feedback with actionable error messages and recovery guidance for users
Common Use Cases
Data Table Headers
- Contact forms with message fields requiring detailed user input and inquiry information for customer service workflows
- Feedback collection systems with structured comment fields and rating explanations for product improvement analysis
- Support ticket creation with problem descriptions and detailed context for technical assistance and resolution tracking
Search Result Sections
- Content creation interfaces with draft management and auto-save functionality for blog posts and article composition
- Review and comment systems with moderation capabilities and content validation for community-driven platforms
- Survey response collection with open-ended questions and detailed feedback gathering for research and analysis purposes
Dashboard Widget Headers
- Settings panels with configuration descriptions and detailed parameter explanations for system customization workflows
- Report generation interfaces with custom description fields and analysis notes for business intelligence dashboards
- User profile management with bio sections and detailed information fields for professional networking and social platforms
Troubleshooting
Common Issues
Actions Not Triggering
Symptoms: Clear button doesn't work, input events don't fire, or form submission doesn't include textarea values
Solutions:
-
Verify that event handlers are properly bound using
.bind(this)pattern and component instance references are maintained -
Check that form context integration is working correctly and textarea changes trigger form updates and validation
-
Ensure that disabled state management allows or prevents user interactions appropriately based on component configuration
Actions Not Visible
Symptoms: Clear button doesn't appear, textarea doesn't render, or component appears blank in form contexts
Solutions:
-
Confirm that textarea has content and clear action visibility logic is functioning properly for user interaction states
-
Check that loading states and skeleton rendering work correctly during form initialization and data loading operations
-
Verify that responsive styles and layout constraints accommodate textarea content properly across different screen sizes
Layout Issues
Symptoms: Textarea appears with incorrect height, text wrapping doesn't work, or component doesn't fit form layouts properly
Solutions:
-
Use appropriate container styling and max-width constraints to ensure textarea fits within form layouts and responsive designs
-
Check that text wrapping and overflow handling work correctly for various content lengths and formatting requirements
-
Ensure that focus states and border styling provide clear visual feedback without disrupting overall layout consistency
Icon Problems
Symptoms: Clear icon doesn't display, button states don't show proper icons, or icon interactions don't work correctly
Solutions:
-
Verify that close icon is available in your icon system and renders correctly with appropriate sizing and color theming
-
Check that icon click handlers are properly configured and trigger clear functionality without interfering with textarea focus
-
Ensure that icon visibility logic works correctly based on content state and disabled status for optimal user experience
Implementation Support
- Text Content Management - Best practices for handling large text inputs, character counting, and content validation patterns
- Form Integration Strategies - Comprehensive guidance for textarea integration with PWC form systems and validation workflows
- Accessibility Compliance - WCAG guidelines implementation, keyboard navigation patterns, and screen reader optimization for text input interfaces
Resources
Storybook Documentation
For comprehensive API documentation, interactive examples, and testing tools: 📖 View Complete API Documentation in Storybook →
This guide provides high-level implementation guidance. For detailed API specifications and interactive examples, visit our Storybook documentation.