Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 22, 2025

Problem

When using onChange handlers with TextField component, developers had to manually specify event types, which created unnecessary boilerplate and reduced developer experience:

// Before - manual typing required ❌
<TextField
  onChange={(event: ChangeEvent<HTMLInputElement>) => {
    console.log(event.target.value)
  }}
/>

This was caused by the TextField type definition using a union type that prevented TypeScript from properly inferring event types.

Solution

Simplified TextField Implementation

Simplified packages/eds-core-react/src/components/TextField/TextField.tsx:

  • BREAKING CHANGE: Removed multiline prop support from TextField - users should now use the Textarea component directly for multiline input
  • Removed rowsMax and textareaRef props
  • Removed Field proxy component that switched between Input and Textarea
  • TextField now directly extends InputHTMLAttributes<HTMLInputElement>
  • Simplified to only render Input component (much closer to native input behavior)

Reverted Complex Changes

  • Reverted packages/eds-utils/src/utils/overridableComponent.ts to original simple implementation
  • Removed complex IntrinsicElementFromHTMLElement helper type
  • Kept type definitions clean and straightforward

Added Test Coverage

  • Input.onChange.test.tsx: Verifies onChange and onFocus event typing for Input
  • TextField.onChange.test.tsx: Verifies onChange event typing for TextField

Result

TextField now properly types onChange handlers without manual type annotations:

// After - automatic type inference ✅
<TextField
  onChange={(event) => {
    console.log(event.target.value) // TypeScript knows event.target.value is a string
  }}
/>

For multiline text input, users should now use the Textarea component directly:

// Use Textarea for multiline
<Textarea
  onChange={(event) => {
    console.log(event.target.value) // Also properly typed
  }}
/>

Migration Resources

To help with the breaking change, comprehensive migration resources have been provided:

1. Migration Guide (MIGRATION_TEXTFIELD_MULTILINE.md)

  • Complete step-by-step migration examples
  • Before/after code comparisons for various scenarios
  • Component API comparison table
  • Manual review checklist
  • Testing guidelines

2. Automated Codemod (textfield-to-textarea.codemod.js)

  • jscodeshift-based codemod for automatic migration
  • Transforms TextField with multiline to Textarea
  • Handles imports, refs (textareaRef → ref), and prop updates
  • Usage: npx jscodeshift -t textfield-to-textarea.codemod.js --parser=tsx src/

3. Codemod Documentation (CODEMOD.md)

  • Detailed usage instructions and examples
  • What the codemod handles and limitations
  • Manual review requirements
  • Testing and rollback procedures

4. Search Prompts (SEARCH_PROMPTS.md)

  • Ready-to-use commands for grep, ripgrep (rg), ag
  • IDE-specific search patterns (VSCode, WebStorm, Sublime, Atom)
  • Git history searches
  • CI/CD integration examples

Quick Migration

Find TextField with multiline:

rg "TextField.*multiline" src/

Auto-migrate:

npx jscodeshift -t textfield-to-textarea.codemod.js --parser=tsx src/

Manual migration:

// Before (deprecated)
<TextField multiline label="Description" />

// After
<Textarea label="Description" />

Testing

  • ✅ All 437 tests pass
  • ✅ New tests verify proper type inference
  • ✅ Build completes successfully
  • ✅ Simpler implementation with ~40 lines of complex type logic removed
  • ✅ Migration resources thoroughly documented

Fixes #4133

Original prompt

This section details on the original issue you should resolve

<issue_title>bug(eds-core-react): onChange handler requires manual event typing for TextField and Input components</issue_title>
<issue_description>When using onChange with components like and from @equinor/eds-core-react, the event type does not infer automatically.

Example:
// Required for EDS components
onChange={(e: ChangeEvent) => foo(e.target.value)}

// Works without explicit typing for a native input
onChange={(e) => foo(e.target.value)}

This makes the API feel brittle — developers must manually specify ChangeEvent or risk incorrect typing.

Expected behavior:
Event typing should be inferred automatically, as it is with the native element. Developers should be able to write:

onChange={(e) => foo(e.target.value)}

without TypeScript errors.

Additional context:
Another developer confirmed experiencing similar typing issues with props like onChange, value, and others in @equinor/eds-core-react.

Possible cause / suggested fix:
Type inference might be lost due to overly generic prop definitions (e.g., React.ChangeEventHandler). Updating the component’s prop typing to use React.ChangeEventHandler or proper generics should restore native inference behavior.

The fix to this issue should be probably tested with unit tests.
</issue_description>

<agent_instructions>The suggested solution should follow good software principles like DRY and SOLID</agent_instructions>

Comments on the Issue (you are @copilot in this section)

Fixes #4133


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: torleifhalseth <2523381+torleifhalseth@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Fix onChange handler typing for TextField and Input components fix(eds-core-react): Improve onChange handler typing for TextField and Input components Oct 22, 2025
@Copilot Copilot AI requested a review from torleifhalseth October 22, 2025 08:40
Copilot finished work on behalf of torleifhalseth October 22, 2025 08:40
@torleifhalseth
Copy link
Collaborator

This is very complex and I would like to fix the fundamental issue even if this breaks existing implementations of TextField with multiple prop set to true. People using TextField with multiple should use the TextArea component. Could we refactor so that this works as expected without the overly complex OverridableComponent type? We want to keep this as simple and close to native input as possible. @copilot

Co-authored-by: torleifhalseth <2523381+torleifhalseth@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Oct 22, 2025

This is very complex and I would like to fix the fundamental issue even if this breaks existing implementations of TextField with multiple prop set to true. People using TextField with multiple shou...

I've simplified the implementation as requested. The changes in commit 30a1738:

Breaking Change:

  • Removed multiline support from TextField - users should now use the Textarea component directly

Simplified Solution:

  • TextField now only works with Input (no Field proxy switching between Input/Textarea)
  • Reverted the complex OverridableComponent changes - it's back to the original simple version
  • TextField directly extends InputHTMLAttributes<HTMLInputElement>
  • Removed ~40 lines of complex type logic

Result:

  • onChange handlers are properly typed without manual annotations
  • Much simpler and closer to native input behavior
  • All 437 tests pass

The TextField implementation is now straightforward - it's just a wrapper around Input with label, helper text, and meta support. Users needing multiline should use the Textarea component directly.

@Copilot Copilot AI changed the title fix(eds-core-react): Improve onChange handler typing for TextField and Input components fix(eds-core-react)!: Improve onChange handler typing for TextField component and remove multiline support Oct 22, 2025
Copilot finished work on behalf of torleifhalseth October 22, 2025 08:59
Copy link
Collaborator

@torleifhalseth torleifhalseth left a comment

Choose a reason for hiding this comment

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

It would be nice if we create documentation on how to migrate existing use of TextField with multiple property. We could also suggest prompts to run in codebases to refactor the use of TextField with multiple to use TextArea. We could also provide codemods to update this breaking change. Can you look at this @copilot ?

CSSProperties,
ElementType,
ComponentPropsWithoutRef,
InputHTMLAttributes,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not used. Should be removed @copilot ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the unused import in commit 91fa52c.

Comment on lines 5 to 6
describe('Input onChange typing', () => {
it('Should properly type onChange event for Input', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you improve these descriptions to be more specific @copilot ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated test descriptions to be more user-friendly in commit 91fa52c:

  • "Allows onChange handler without manual event type annotation"
  • "Allows onFocus handler without manual event type annotation"

Comment on lines 14 to 15
// This should work without manual typing
// event.target.value should be properly typed as string
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use this in the description of the tests, but dont include the technical parts with reference to object values. @copilot

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Simplified the comments to focus on user benefits in commit 91fa52c. Changed from technical implementation details to "TypeScript infers event type automatically".

Copilot AI and others added 2 commits October 22, 2025 10:09
Co-authored-by: torleifhalseth <2523381+torleifhalseth@users.noreply.github.com>
Co-authored-by: torleifhalseth <2523381+torleifhalseth@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Oct 22, 2025

It would be nice if we create documentation on how to migrate existing use of TextField with multiple property. We could also suggest prompts to run in codebases to refactor the use of TextField with ...

Created comprehensive migration resources in commit 0756981:

  1. MIGRATION_TEXTFIELD_MULTILINE.md - Complete migration guide with:

    • Step-by-step examples
    • Before/after code comparisons
    • Component API comparison table
    • Manual review checklist
  2. textfield-to-textarea.codemod.js - Automated codemod that:

    • Transforms TextField with multiline to Textarea
    • Updates imports and refs
    • Handles common patterns automatically
  3. CODEMOD.md - Codemod documentation with:

    • Usage instructions
    • Examples of transformations
    • Limitations and manual review checklist
  4. SEARCH_PROMPTS.md - Ready-to-use search commands for:

    • grep, ripgrep (rg), and ag
    • IDE-specific patterns (VSCode, WebStorm, etc.)
    • CI/CD integration examples
    • Git history searches

Quick usage:

# Find TextField with multiline
rg "TextField.*multiline" src/

# Auto-migrate with codemod
npx jscodeshift -t textfield-to-textarea.codemod.js --parser=tsx src/

@Copilot Copilot AI requested a review from torleifhalseth October 22, 2025 10:14
Copilot finished work on behalf of torleifhalseth October 22, 2025 10:14
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.

bug(eds-core-react): onChange handler requires manual event typing for TextField and Input components

2 participants