Skip to content

Conversation

Jacksonmills
Copy link

Add the new Textarea(#718) component to provide an unstyled native text input with Field system integration:

  • Exposes <Textarea … /> with support for controlled and uncontrolled usage.
  • Integrates with the Field system for automatic state handling and validation.
  • Supports content-aware auto-resizing via minRows and maxRows.
  • Exposes data attributes for styling based on control state.
  • Sets up CSS Modules and Tailwind usage examples.
  • Includes unit tests for core behavior.
  • Ships a demo page under docs/src/app/(public)/content/react/components/textarea.

This is my first time adding a form control to base-ui. I’m following the repo’s patterns and totally down to adjust if this component needs tweaks.

Changed files

  • packages/react/src/textarea/Textarea.tsx
  • packages/react/src/textarea/index.ts
  • docs/src/app/(public)/content/react/components/textarea/*
  • packages/react/src/textarea/Textarea.test.tsx

Add a native, unstyled textarea component that integrates with the Field system to provide automatic state handling and validation.

Enable content-aware auto-resizing via minRows/maxRows, support controlled and uncontrolled usage, and expose data attributes for styling based on control state. Add documentation, API reference, unit tests, and package export so the component is discoverable and consumable.
Copy link

pkg-pr-new bot commented Oct 3, 2025

vite-css-base-ui-example

pnpm add https://pkg.pr.new/mui/base-ui/@base-ui-components/react@2898
pnpm add https://pkg.pr.new/mui/base-ui/@base-ui-components/utils@2898

commit: 35e5187

Copy link

netlify bot commented Oct 3, 2025

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 35e5187
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/68e18d217eeccc00083dd1ce
😎 Deploy Preview https://deploy-preview-2898--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@mui-bot
Copy link

mui-bot commented Oct 3, 2025

Bundle size report

Bundle Parsed size Gzip size
@base-ui-components/react 🔺+4.05KB(+1.11%) 🔺+1.45KB(+1.25%)

Details of bundle changes

@atomiks atomiks added the component: textarea Changes related to the textarea component. label Oct 3, 2025
Comment on lines 127 to 130
const lineHeight = parseFloat(getComputedStyle(el).lineHeight) || 24;
const min = minRows != null ? minRows * lineHeight : 0;
const maxPx = maxRows != null ? maxRows * lineHeight : Infinity;
const target = Math.min(maxPx, Math.max(min, el.scrollHeight));
Copy link
Member

Choose a reason for hiding this comment

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

Is this enough to do the calculation like this? 🤔
Other libraries like Material UI and react-textarea-autosize render a second, hidden textarea element presumably to handle edge cases

Check out:

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for reviewing!

The direct scrollHeight + lineHeight math works for the simple case, but at a glance you’re definitely right: Material UI and react-textarea-autosize handle things like box-sizing quirks, padding, and browser edge cases with the hidden textarea element. I’ll review their approach and see how we can adopt a similar pattern instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps some research into when field-sizing might be at 90%+ support would be helpful too. When it's widely supported, we won't need this functionality in JS. https://caniuse.com/?search=field-sizing

Copy link
Author

Choose a reason for hiding this comment

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

Absolutely, would be great to drop the JS once browser support crosses the 90% mark. Do you have a usual way to track when features hit that kind of support? Just Can I Use, or anything more automated you follow?

Copy link
Contributor

Choose a reason for hiding this comment

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

nothing automated

Copy link
Author

@Jacksonmills Jacksonmills Oct 4, 2025

Choose a reason for hiding this comment

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

Alright, I’ve updated things to better align with MUI’s approach and logic.

I also added a dedicated demo for field-sizing that explains the current browser support.

Jacksonmills and others added 14 commits October 3, 2025 08:28
Removes usage of the experimental field-sizing property and related Tailwind utility from textarea examples and removes hardcoded min-height in CSS modules.

Avoids depending on a feature with limited browser support (~71.47%). Adds space to create a dedicated example and documentation with compatibility research once support reaches ~90%, keeping demos stable and predictable in the meantime.
Extracts the textarea height calculation into a reusable utility and isolates the expensive measurement logic.

Reduces layout thrashing by tracking last-applied height and overflow to avoid redundant DOM writes, and introduces debounced scheduling (~166ms) for resize/observer events while using immediate RAF for input events to keep input responsive.

Adds proper timer/observer cleanup and a default rows fallback to ensure consistent initial sizing and improved runtime performance.
Replace a hardcoded property list and unsafe direct assignments with iteration over computed styles and setProperty/getPropertyValue to copy relevant CSS keys.

This avoids TypeScript readonly casts, picks up actual computed property names (including vendor-prefixed variants), and makes style copying more robust and cross-browser resilient.
Remove built-in inline "resize: none" from textarea rendering.

Allow consumers to control resizing via their own CSS instead of enforcing non-resizable behavior. Preserve existing value/rows handling; change affects styling only.
Adds interactive demos showing CSS field-sizing for the textarea component using CSS Modules and Tailwind, and updates documentation to explain the feature, browser support, and recommended fallback guidance.

Provides examples to let developers try native field-sizing behavior, clarifies current limited browser support, and notes a plan to adopt field-sizing by default once support reaches sufficient coverage.
@mnajdova
Copy link
Member

mnajdova commented Oct 7, 2025

@Jacksonmills this is a great first iteration. The team is a bit busy this week with React Conf, but we can come back to this in the next weeks. Thanks for putting in the effort :)

@Jacksonmills
Copy link
Author

@Jacksonmills this is a great first iteration. The team is a bit busy this week with React Conf, but we can come back to this in the next weeks. Thanks for putting in the effort :)

ofc no worries!


Because support is incomplete, the demo may not work in older browsers or Safari `<26`. If the textarea doesn't resize, try a **current Chrome or Edge** build.

> Once support passes ~90 %, we plan to switch the Textarea component to `field-sizing` by default, dropping the JS fallback.

Choose a reason for hiding this comment

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

I do find this quite optimistic. Would it be possible to just check for support and gate the resizing logic instead with CSS.supports("field-sizing", "content")?

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

Labels

component: textarea Changes related to the textarea component.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants