refactor: updated Input and TextField to align with mobile fixes#1000
Conversation
📖 Storybook Preview |
📖 Storybook Preview |
There was a problem hiding this comment.
Looks good! Could we avoid adding startAccessoryTestID / endAccessoryTestID as new props. If we want to reduce wrapper Views in a future refactor, these props will force us to keep (or replace) the wrappers and can create extra breaking-change surface. For test we can put thetestID on the accessory element itself (or let consumers wrap accessories as needed).
Reference: the extension TextField implementation is materially less wrapper-heavy: https://github.com/MetaMask/metamask-extension/blob/main/ui/components/component-library/text-field/text-field.tsx#L131
| /** | ||
| * Optional test ID for the start accessory wrapper (when `startAccessory` is set). | ||
| */ | ||
| startAccessoryTestID?: string; |
There was a problem hiding this comment.
suggestion: Can we drop startAccessoryTestID / endAccessoryTestID? Adding wrapper-specific testID props makes it harder to remove wrapper Views later without additional breaking changes. If an E2E test needs a stable selector, we can pass testID directly on the accessory element (or let consumers wrap the accessory). See extension TextField for a less wrapper-heavy approach: https://github.com/MetaMask/metamask-extension/blob/main/ui/components/component-library/text-field/text-field.tsx#L131
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
georgewrmarshall
left a comment
There was a problem hiding this comment.
LGTM! Left a non-blocking question about the error and focused state
📖 Storybook Preview |
📖 Storybook Preview |
## Release 26.0.0 This release adds new BannerAlert components, introduces `KeyValueRow` for React Native, includes breaking simplifications to React Native `TextButton` and `TextField`, and continues ADR-0003/0004 shared type migrations. ### 📦 Package Versions - `@metamask/design-system-shared`: **0.5.0** - `@metamask/design-system-react`: **0.12.0** - `@metamask/design-system-react-native`: **0.12.0** ### 🔄 Shared Type Updates (0.5.0) #### Component Type Additions (#975, #997) **What Changed:** - Added `BannerAlertSeverity` const object + `BannerAlertPropsShared` - Added `AvatarNetworkPropsShared` type (ADR-0004) **Impact:** - Enables consistent cross-platform `BannerAlert` severity/types - Continues ADR-0003/ADR-0004 const-object + string-union + shared types adoption ### 🌐 React Web Updates (0.12.0) #### Added - Added `BannerAlert` component (#975) #### Changed - Updated `TextButton` hover/pressed styles to be text-only (no background fill) (#1001) - Updated `Candlestick` icon asset with smaller size variant (#998) ### 📱 React Native Updates (0.12.0) #### Added - Added `BannerAlert` component (#966) - Added `KeyValueRow` component (#959) #### Changed - **BREAKING:** Simplified `TextButton` to a text-only control and removed `size`/`TextButtonSize`, inverse/disabled props, and icon/accessory props (#1001) - Migration: `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120` - **BREAKING:** Removed `TextFieldSize` and the `size` prop; `TextField` is now a single fixed-height (48px) row (#1000) - Migration: `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120` - Updated `Candlestick` icon asset with smaller size variant (#998) #### Fixed - Improved `Input` single-line typography alignment (including iOS placeholder behavior) (#1000) ###⚠️ Breaking Changes #### TextButton API (React Native) **What Changed:** - Removed `size`/`TextButtonSize`, `isDisabled`, `isInverse`, and start/end icon & accessory props - `TextButton` now aligns with `Text` typography and press handlers (`variant`, `fontWeight`, `onPress`, etc.) **Migration:** See `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120`. **Impact:** - Affects all React Native `TextButton` usages relying on the removed props #### TextField Size API (React Native) **What Changed:** - Removed `TextFieldSize` and the `size` prop - `TextField` is now a single fixed-height (48px) row **Migration:** See `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120`. **Impact:** - Affects all React Native `TextField` usages passing `size` / importing `TextFieldSize` ### ✅ Checklist - [x] Changelogs updated with human-readable descriptions - [x] Changelog validation passed (`yarn changelog:validate`) - [x] Version bumps follow semantic versioning - [x] design-system-shared: minor (0.4.0 → 0.5.0) - new shared types - [x] design-system-react: minor (0.11.0 → 0.12.0) - new component + non-breaking changes - [x] design-system-react-native: minor (0.11.0 → 0.12.0) - new components + breaking API changes (pre-1.0) - [x] Breaking changes documented with migration guidance - [x] Migration guides updated with before/after examples (if breaking changes) - [x] PR references included in changelog entries ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) - [x] I've reviewed the [Release Workflow](./.cursor/rules/release-workflow.md) cursor rule - [x] All tests pass (`yarn build && yarn test && yarn lint`) - [x] Changelog validation passes (`yarn changelog:validate`) ## **Pre-merge reviewer checklist** - [ ] I've reviewed the [Reviewing Release PRs](./docs/reviewing-release-prs.md) guide - [ ] Package versions follow semantic versioning - [ ] Changelog entries are consumer-facing (not commit message regurgitation) - [ ] Breaking changes are documented in MIGRATION.md with examples - [ ] All unreleased changes are accounted for in changelogs <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Mostly a version/changelog release PR, but includes documented **breaking** React Native API removals for `TextButton` and `TextField` that can break downstream consumers on upgrade. > > **Overview** > Bumps the monorepo version to `26.0.0` and releases `@metamask/design-system-react`/`@metamask/design-system-react-native` to `0.12.0` and `@metamask/design-system-shared` to `0.5.0`. > > Updates changelogs and the React Native migration guide to reflect new `BannerAlert` (web + RN) and `KeyValueRow` (RN), shared type additions (`BannerAlertSeverity`/`BannerAlertPropsShared`, `AvatarNetworkPropsShared`), and **breaking** RN API changes removing `TextButton` sizing/icons/disabled/inverse props and removing `TextField` sizing (`TextFieldSize`/`size`) in favor of a fixed-height row. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5ead00c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
Aligns React Native **Input** and **TextField** with the mobile product
fixes: more predictable single-line text layout and a single, spec-sized
text field row.
**Input**
- Stops using `text-${textVariant}` Tailwind classes for typography and
applies **font size and letter spacing from design tokens** via new
`MAP_TEXT_VARIANT_INPUT_METRICS` in `Input.constants.ts`, **without**
paragraph `lineHeight` so `TextInput` vertical alignment matches the
intended legacy behavior.
- Keeps the **iOS placeholder** `lineHeight: 0` workaround only when the
placeholder is visible.
- Removes the unconditional iOS `textAlignVertical: 'center'` style.
- **Storybook:** wraps interactive stories in a small **controlled**
helper so typing works with required `value`.
**TextField**
- **Breaking:** removes **`TextFieldSize`** and the `size` prop; the
field is always a **48px** row (`h-12`) with a **46px** inner `Input` so
the bordered row does not overflow.
- Container uses **`bg-muted`** and **state-based border colors** (muted
at rest; default when focused; error / primary combinations for error +
focus; muted when disabled).
- Inner `Input` is **single-line** (`numberOfLines={1}`,
`multiline={false}`).
- Accessory spacing is **`mr-3` / `ml-3`**; adds
**`startAccessoryTestID`** and **`endAccessoryTestID`** on the accessory
wrapper views for E2E.
- README, package exports, tests, and stories updated accordingly.
## **Related issues**
Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-654
## **Manual testing steps**
1. From the repo root, run React Native Storybook (`yarn storybook:ios`
or `yarn storybook:android`).
2. Open **Components → Input**: confirm variants, disabled/readonly, and
that typing works in controlled stories; on **iOS**, check placeholder
vs. filled text vertical alignment.
3. Open **Components → TextField**: confirm 48px height, muted
background, border colors for default / focus / error / disabled, and
start/end accessories; if you use E2E, confirm `startAccessoryTestID` /
`endAccessoryTestID` resolve.
## **Screenshots/Recordings**
### **Before**
_Input / TextField before this branch (e.g. old sizes, old
borders/background, any misaligned placeholder)._
### **After**
https://github.com/user-attachments/assets/dc37ed5c-3bcc-484e-8677-fd74684fcdf9
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
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.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Medium risk because it introduces a breaking API change (removes
`TextFieldSize`/`size`) and alters text/layout styling that could affect
UI rendering across platforms.
>
> **Overview**
> Updates React Native `Input` typography to use token-driven
`fontSize`/`letterSpacing` (without Tailwind `text-*` line heights) and
narrows the iOS placeholder line-height workaround to
placeholder-visible state.
>
> Refactors `TextField` to a single fixed **48px** row (46px inner
`Input`), removes `TextFieldSize` and related exports, and updates
container visuals (muted background, `gap-3` accessory spacing, and
revised focus/error/disabled border behavior) while forcing single-line
input.
>
> Refreshes Storybook stories to use controlled wrappers, updates unit
tests to match the new layout/state styling, and documents the breaking
change in `MIGRATION.md`/`TextField` README.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dc44871. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Release 26.0.0 This release adds new BannerAlert components, introduces `KeyValueRow` for React Native, includes breaking simplifications to React Native `TextButton` and `TextField`, and continues ADR-0003/0004 shared type migrations. ### 📦 Package Versions - `@metamask/design-system-shared`: **0.5.0** - `@metamask/design-system-react`: **0.12.0** - `@metamask/design-system-react-native`: **0.12.0** ### 🔄 Shared Type Updates (0.5.0) #### Component Type Additions (#975, #997) **What Changed:** - Added `BannerAlertSeverity` const object + `BannerAlertPropsShared` - Added `AvatarNetworkPropsShared` type (ADR-0004) **Impact:** - Enables consistent cross-platform `BannerAlert` severity/types - Continues ADR-0003/ADR-0004 const-object + string-union + shared types adoption ### 🌐 React Web Updates (0.12.0) #### Added - Added `BannerAlert` component (#975) #### Changed - Updated `TextButton` hover/pressed styles to be text-only (no background fill) (#1001) - Updated `Candlestick` icon asset with smaller size variant (#998) ### 📱 React Native Updates (0.12.0) #### Added - Added `BannerAlert` component (#966) - Added `KeyValueRow` component (#959) #### Changed - **BREAKING:** Simplified `TextButton` to a text-only control and removed `size`/`TextButtonSize`, inverse/disabled props, and icon/accessory props (#1001) - Migration: `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120` - **BREAKING:** Removed `TextFieldSize` and the `size` prop; `TextField` is now a single fixed-height (48px) row (#1000) - Migration: `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120` - Updated `Candlestick` icon asset with smaller size variant (#998) #### Fixed - Improved `Input` single-line typography alignment (including iOS placeholder behavior) (#1000) ###⚠️ Breaking Changes #### TextButton API (React Native) **What Changed:** - Removed `size`/`TextButtonSize`, `isDisabled`, `isInverse`, and start/end icon & accessory props - `TextButton` now aligns with `Text` typography and press handlers (`variant`, `fontWeight`, `onPress`, etc.) **Migration:** See `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120`. **Impact:** - Affects all React Native `TextButton` usages relying on the removed props #### TextField Size API (React Native) **What Changed:** - Removed `TextFieldSize` and the `size` prop - `TextField` is now a single fixed-height (48px) row **Migration:** See `./packages/design-system-react-native/MIGRATION.md#from-version-0110-to-0120`. **Impact:** - Affects all React Native `TextField` usages passing `size` / importing `TextFieldSize` ### ✅ Checklist - [x] Changelogs updated with human-readable descriptions - [x] Changelog validation passed (`yarn changelog:validate`) - [x] Version bumps follow semantic versioning - [x] design-system-shared: minor (0.4.0 → 0.5.0) - new shared types - [x] design-system-react: minor (0.11.0 → 0.12.0) - new component + non-breaking changes - [x] design-system-react-native: minor (0.11.0 → 0.12.0) - new components + breaking API changes (pre-1.0) - [x] Breaking changes documented with migration guidance - [x] Migration guides updated with before/after examples (if breaking changes) - [x] PR references included in changelog entries ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) - [x] I've reviewed the [Release Workflow](./.cursor/rules/release-workflow.md) cursor rule - [x] All tests pass (`yarn build && yarn test && yarn lint`) - [x] Changelog validation passes (`yarn changelog:validate`) ## **Pre-merge reviewer checklist** - [ ] I've reviewed the [Reviewing Release PRs](./docs/reviewing-release-prs.md) guide - [ ] Package versions follow semantic versioning - [ ] Changelog entries are consumer-facing (not commit message regurgitation) - [ ] Breaking changes are documented in MIGRATION.md with examples - [ ] All unreleased changes are accounted for in changelogs <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Mostly a version/changelog release PR, but includes documented **breaking** React Native API removals for `TextButton` and `TextField` that can break downstream consumers on upgrade. > > **Overview** > Bumps the monorepo version to `26.0.0` and releases `@metamask/design-system-react`/`@metamask/design-system-react-native` to `0.12.0` and `@metamask/design-system-shared` to `0.5.0`. > > Updates changelogs and the React Native migration guide to reflect new `BannerAlert` (web + RN) and `KeyValueRow` (RN), shared type additions (`BannerAlertSeverity`/`BannerAlertPropsShared`, `AvatarNetworkPropsShared`), and **breaking** RN API changes removing `TextButton` sizing/icons/disabled/inverse props and removing `TextField` sizing (`TextFieldSize`/`size`) in favor of a fixed-height row. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5ead00c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Description
Aligns React Native Input and TextField with the mobile product fixes: more predictable single-line text layout and a single, spec-sized text field row.
Input
text-${textVariant}Tailwind classes for typography and applies font size and letter spacing from design tokens via newMAP_TEXT_VARIANT_INPUT_METRICSinInput.constants.ts, without paragraphlineHeightsoTextInputvertical alignment matches the intended legacy behavior.lineHeight: 0workaround only when the placeholder is visible.textAlignVertical: 'center'style.value.TextField
TextFieldSizeand thesizeprop; the field is always a 48px row (h-12) with a 46px innerInputso the bordered row does not overflow.bg-mutedand state-based border colors (muted at rest; default when focused; error / primary combinations for error + focus; muted when disabled).Inputis single-line (numberOfLines={1},multiline={false}).mr-3/ml-3; addsstartAccessoryTestIDandendAccessoryTestIDon the accessory wrapper views for E2E.Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-654
Manual testing steps
yarn storybook:iosoryarn storybook:android).startAccessoryTestID/endAccessoryTestIDresolve.Screenshots/Recordings
Before
Input / TextField before this branch (e.g. old sizes, old borders/background, any misaligned placeholder).
After
Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2026-03-24.at.23.57.08.mov
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Medium risk because it introduces a breaking API change (removes
TextFieldSize/size) and alters text/layout styling that could affect UI rendering across platforms.Overview
Updates React Native
Inputtypography to use token-drivenfontSize/letterSpacing(without Tailwindtext-*line heights) and narrows the iOS placeholder line-height workaround to placeholder-visible state.Refactors
TextFieldto a single fixed 48px row (46px innerInput), removesTextFieldSizeand related exports, and updates container visuals (muted background,gap-3accessory spacing, and revised focus/error/disabled border behavior) while forcing single-line input.Refreshes Storybook stories to use controlled wrappers, updates unit tests to match the new layout/state styling, and documents the breaking change in
MIGRATION.md/TextFieldREADME.Written by Cursor Bugbot for commit dc44871. This will update automatically on new commits. Configure here.