Skip to content

feat: [DSRN] Added TextArea#1141

Merged
brianacnguyen merged 14 commits into
mainfrom
dsrn/textarea
May 8, 2026
Merged

feat: [DSRN] Added TextArea#1141
brianacnguyen merged 14 commits into
mainfrom
dsrn/textarea

Conversation

@brianacnguyen

@brianacnguyen brianacnguyen commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds TextArea to @metamask/design-system-react-native: a multiline field built from the existing Input inside a styled Box (border, focus/error/disabled states, min height, transparent inner input). It aligns with the shared field model by introducing TextAreaPropsShared in @metamask/design-system-shared (ADR-0004), mirroring TextField without start/end accessories.

Input was updated so multiline mode works correctly: typography uses the text variant + font classes instead of single-line input metrics, the inner TextInput receives multiline, and the iOS-only lineHeight: 0 placeholder workaround is skipped when multiline so paragraph layout is not broken.

Also included: README, Storybook stories, and unit tests for TextArea; Input tests were extended for multiline behavior.

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-573

Manual testing steps

  1. From the repo root, run React Native Storybook (e.g. yarn storybook:ios or yarn storybook:android).
  2. Open the TextArea stories and verify default, disabled, error, and focus border behavior; type multiple lines and confirm layout and placeholder alignment.
  3. Spot-check a story or screen that still uses Input in single-line mode to confirm no regression.

Screenshots/Recordings

If applicable, add screenshots and/or recordings to visualize the before and after of your change.

Before

After

Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2026-04-30.at.13.24.23.mov

Pre-merge author checklist

  • I've followed MetaMask Contributor Docs
  • I've completed the PR template to the best of my ability
  • I’ve included tests if applicable
  • I’ve documented my code using JSDoc format if applicable
  • I’ve applied the right labels on the PR (see labeling guidelines). Not required for external contributors.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Updates shared Input styling/placeholder behavior and introduces a new multiline TextArea, so regressions could affect existing input rendering across platforms (especially iOS/Android placeholder/layout differences). Scope is UI-focused with good test coverage, but touches a widely-used primitive.

Overview
Adds a new TextArea component to @metamask/design-system-react-native: a multiline, bordered field wrapper around Input with focus/error/disabled chrome, inputProps passthrough, and separate refs for the root container vs. inner TextInput.

Updates Input to properly support multiline usage by forwarding multiline, using variant typography styles (instead of single-line metrics) for multiline, and scoping the iOS lineHeight: 0 placeholder workaround to single-line only.

Extends/updates unit tests and Storybook to cover the new TextArea and the updated Input multiline + iOS placeholder behaviors, and aligns shared prop contracts by introducing TextAreaPropsShared and refactoring TextFieldPropsShared to build on InputPropsShared (which now includes placeholder and autoFocus).

Reviewed by Cursor Bugbot for commit fb78795. Bugbot is set up for automated code reviews on this repo. Configure here.

@brianacnguyen brianacnguyen self-assigned this Apr 30, 2026
@brianacnguyen brianacnguyen requested a review from a team as a code owner April 30, 2026 20:06
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react-native/src/components/TextArea/TextArea.stories.tsx Outdated
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall left a comment

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.

Overall this PR looks good, and the RN implementation/tests are in solid shape. I think the remaining issue is mostly sequencing and shared-API shape: PR #1043 should land first so this component can build on InputPropsShared, and then TextAreaPropsShared can be based on the shared input contract rather than inheriting from TextFieldPropsShared.

Comment thread packages/design-system-shared/src/types/TextArea/TextArea.types.ts
@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1d9dd05. Configure here.

@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall left a comment

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.

The RN implementation is close, and the earlier dependency/focus-state issues look resolved, but I think there are still a few API/process issues to address before merge. This PR extends the React Native-specific onChangeText callback name further into @metamask/design-system-shared, appears to expose textVariant on TextField through shared-type inheritance even though the source extension component does not expose typography control, and manually updates packages/design-system-shared/CHANGELOG.md even though changelog updates are part of the release process. I think those should be cleaned up before this lands.

Comment thread packages/design-system-shared/src/types/TextArea/TextArea.types.ts Outdated
Comment thread packages/design-system-shared/CHANGELOG.md Outdated
Comment thread packages/design-system-react-native/src/components/Input/Input.test.tsx Outdated
Comment thread packages/design-system-react-native/src/components/Input/Input.tsx
Comment thread packages/design-system-react-native/src/components/TextArea/TextArea.tsx Outdated
Comment thread packages/design-system-react-native/src/components/Input/Input.tsx Outdated
@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall left a comment

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.

The current revision looks ready to merge. The earlier shared-type/API concerns appear resolved: TextAreaPropsShared now builds on InputPropsShared, TextField no longer exposes textVariant through shared inheritance, and the changelog edit is gone. The RN implementation and targeted multiline/input tests also look solid from this pass.

@brianacnguyen brianacnguyen enabled auto-merge (squash) May 8, 2026 19:59
@github-actions

github-actions Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@brianacnguyen brianacnguyen merged commit f4d5f42 into main May 8, 2026
44 checks passed
@brianacnguyen brianacnguyen deleted the dsrn/textarea branch May 8, 2026 20:04
@brianacnguyen brianacnguyen mentioned this pull request May 15, 2026
17 tasks
brianacnguyen added a commit that referenced this pull request May 15, 2026
## Release 40.0.0

This release updates the shared layer and both UI packages: new
extension-aligned primitives and form helpers on web, new selection and
multi-line input components on React Native, shared types and context
for those APIs, coordinated **`BannerBase`** close behavior, and
**`ButtonBase`** defaults driven by **`size`** (with migration guidance
for wrappers that overrode label, icon, or spacing).

### Package versions

- `@metamask/design-system-shared`: **0.18.0**
- `@metamask/design-system-react`: **0.23.0**
- `@metamask/design-system-react-native`: **0.25.0**

### Shared type updates (0.18.0)

#### Component type additions
([#1172](#1172),
[#1164](#1164),
[#1169](#1169),
[#1141](#1141))

**What changed**

- **`SelectButton`** shared props and variants
(`SelectButtonPropsShared`, `SelectButtonVariant`,
`SelectButtonEndArrow`).
- **`SegmentGroup`** shared props and **`SegmentGroupContext`**
(`SegmentGroupPropsShared`, `SegmentGroupContext`,
`SegmentGroupContextValue`).
- **`SensitiveText`** shared types (`SensitiveTextLength`,
`SensitiveTextPropsShared`, and related exports).
- **`HelpText`** shared types (`HelpTextSeverity`,
`HelpTextPropsShared`, and related exports).
- **`TextAreaPropsShared`** for multi-line input wrappers.

**Impact**

- React and React Native stay aligned on the same ADR-0003/0004-style
contracts for the new and updated surfaces above.

### React web updates (0.23.0)

#### Added

- **`PopoverHeader`** — popover title rows and trailing actions,
extension migration patterns
([#1158](#1158)).
- **`ModalHeader`** — modal title rows and accessory slots
([#1144](#1144)).
- **`Label`** — captions paired with form controls
([#1152](#1152)).
- **`SensitiveText`** — mask/reveal for sensitive strings with
configurable visible length
([#1164](#1164)).
- **`HelpText`** — helper, success, warning, and error copy under inputs
and controls
([#1169](#1169)).

#### Changed

- **`ButtonBase`** — label **`Text`** variant, start/end icon sizes, and
internal spacing are derived from **`size`** for each
**`ButtonBaseSize`**
([#1150](#1150)).
See [Migration guide —
ButtonBase](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react/MIGRATION.md#buttonbase-size-defaults).
- **`BannerBase`** — close behavior uses **`onClose`** only;
**`closeButtonProps.onClick`** is not the dismiss API;
**`closeButtonProps`** is for customization
([#1166](#1166)).

### React Native updates (0.25.0)

#### Added

- **`SelectButton`**, **`SegmentButton`**, **`SegmentGroup`**
([#1172](#1172)).
- **`SensitiveText`**, aligned with the shared contract
([#1164](#1164)).
- **`HeaderStandardAnimated`** and **`useHeaderStandardAnimated`**
([#1151](#1151)).
- **`TextArea`**
([#1141](#1141)).

#### Changed

- **`ButtonBase`** — same size-driven defaults as web
([#1150](#1150)).
See [Migration guide —
ButtonBase](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react-native/MIGRATION.md#buttonbase-size-defaults).
- **`BannerBase`** — close behavior uses **`onClose`** only;
**`closeButtonProps.onPress`** is not the dismiss API
([#1166](#1166)).

### Breaking changes

#### `BannerBase` close API (both platforms)

**What changed**

- **React:** Use **`onClose`** for dismiss behavior.
**`closeButtonProps.onClick`** is removed from that role. The close
control is tied to **`onClose`**. **`closeButtonProps`** remains for
non-behavioral customization (e.g. **`data-testid`**, accessibility,
styling hooks).
- **React Native:** Same pattern: **`onClose`** instead of
**`closeButtonProps.onPress`** for dismiss behavior.

**Migration**

- Move any close action from **`closeButtonProps.onClick`** /
**`closeButtonProps.onPress`** to **`onClose`**.
- If you previously forced a close button with only
**`closeButtonProps`**, also provide **`onClose`**.

**Impact**

- Call sites that dismissed via **`closeButtonProps`** or showed a close
button without **`onClose`** must be updated.

See:

- [React — From version 0.22.0 to
0.x.0](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react/MIGRATION.md#from-version-0220-to-0x0)
- [React Native — From version 0.24.0 to
0.x.0](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react-native/MIGRATION.md#from-version-0240-to-0x0)

**`ButtonBase`:** not called out here as a semver-breaking API change;
consumers who overrode typography, icon size, or spacing on
**`ButtonBase`** wrappers should follow the ButtonBase migration
sections linked above.

### Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] `yarn changelog:validate` passes
- [x] Version bumps follow semantic versioning
- [x] `@metamask/design-system-shared`: **minor** (0.17.x → 0.18.0) —
new shared exports for select/segment, sensitive text, help text, text
area
- [x] `@metamask/design-system-react`: **minor** (0.22.x → 0.23.0) — new
components; **`BannerBase`** / **`ButtonBase`** behavior
- [x] `@metamask/design-system-react-native`: **minor** (0.24.x →
0.25.0) — new components; **`BannerBase`** / **`ButtonBase`** behavior
- [x] Breaking changes documented (**`BannerBase`**) in MIGRATION with
before/after examples
- [x] PR references present in changelog entries

## Pre-merge author checklist

- [ ] [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [ ] [Release
Workflow](https://github.com/MetaMask/metamask-design-system/blob/main/.cursor/rules/release-workflow.md)
- [ ] `yarn build && yarn test && yarn lint`
- [ ] `yarn changelog:validate`

## Pre-merge reviewer checklist

- [ ] [Reviewing Release
PRs](https://github.com/MetaMask/metamask-design-system/blob/main/docs/reviewing-release-prs.md)
- [ ] Package versions and semver match what this PR actually publishes
- [ ] Changelogs are consumer-facing
- [ ] Breaking changes covered in MIGRATION.md
- [ ] No unpublished package is missing from the changelogs / version
list for **this** PR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants