feat: TextFieldSearch migration (extension)#1171
Conversation
📖 Storybook Preview |
📖 Storybook Preview |
brianacnguyen
left a comment
There was a problem hiding this comment.
can you extract the types out to design-system-shared?
a4daf39 to
5fda8a6
Compare
5fda8a6 to
27d5e9f
Compare
a5e798a to
226ff9b
Compare
📖 Storybook Preview |
📖 Storybook Preview |
There was a problem hiding this comment.
Solid work bringing TextFieldSearch into the design system react! ADR-0003/0004 architecture is correct, the shared type is appropriately minimal, migration docs cover the main breaking changes well, and test coverage is thorough 🔥
I've approved incase you want to merge and address the comments below in a follow up PR.
| import React, { forwardRef } from 'react'; | ||
|
|
||
| import { ButtonIcon } from '../ButtonIcon'; | ||
| import { ButtonIconSize } from '../ButtonIcon'; |
There was a problem hiding this comment.
suggestion: Merge into a single import:
import { ButtonIcon, ButtonIconSize } from '../ButtonIcon';| import { ButtonIconSize } from '../ButtonIcon'; | ||
| import { Icon, IconName, IconSize } from '../Icon'; | ||
| import { TextField } from '../TextField'; | ||
| import { TextFieldType } from '../TextField/TextField.types'; |
There was a problem hiding this comment.
suggestion: Prefer the module index over internal type file paths:
import { TextField, TextFieldType } from '../TextField';Same pattern applies in TextFieldSearch.types.ts (line 3, '../ButtonIcon/ButtonIcon.types' → '../ButtonIcon') and TextFieldSearch.stories.tsx (line 4, '../TextField/TextField.types' → '../TextField').
| <ButtonIcon | ||
| data-testid="text-field-search-clear-button" | ||
| ariaLabel="Clear" | ||
| iconName={IconName.Close} |
There was a problem hiding this comment.
suggestion: A few visual details differ from the RN implementation. I've reached out in slack to confirm but I think we want to align to the RN version
iconName={IconName.CircleX}on the clear button (vsClosehere)size={ButtonIconSize.Md}on the clear button (vsSmhere)iconProps={{ color: IconColor.IconAlternative }}on the clear button iconIconSize.Md+IconColor.IconAlternativeon the search icon (vsIconSize.Smwith no explicit color here)rounded-fullcontainer style for the pill shape
| * | ||
| * @default true | ||
| */ | ||
| showClearButton?: boolean; |
There was a problem hiding this comment.
suggestion: An audit of the extension usages shows all instances either pass showClearButton={true} explicitly or rely on the default — no caller ever sets it to false. The RN implementation also has no equivalent prop; the clear button always appears when value is truthy. Worth removing showClearButton entirely to keep both platforms aligned and simplify the API.
| /** | ||
| * Click handler for the clear button. Use it to reset the controlled `value`. | ||
| */ | ||
| clearButtonOnClick?: React.MouseEventHandler<HTMLButtonElement>; |
There was a problem hiding this comment.
suggestion: clearButtonOnClick is optional, so a visible clear button can render with no handler — clicking it silently does nothing. The RN equivalent (onPressClearButton) is required. Aligns with the showClearButton removal suggestion: if the button always shows when value is truthy, the handler should be required to match consumer expectations and the RN API.
| <ControlledTextFieldSearch | ||
| placeholder="Without clear button" | ||
| value="hello" | ||
| showClearButton={false} |
There was a problem hiding this comment.
suggestion: When showClearButton={false}, the browser still renders its own native clear button for type="search" inputs on hover (see screen recording). If we remove showClearButton altogether and make the default always true this should no longer be an issue
textfieldsearch.clearbutton.mov
📖 Storybook Preview |
📖 Storybook Preview |
0ede10d to
7ae14b9
Compare
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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 173711f. Configure here.
📖 Storybook Preview |
## Release 43.0.0 This release drops Node.js 18 support across the release line, adds several new components, and includes a small set of breaking API changes that are documented in the migration guides. ### 📦 Package Versions - `@metamask/design-system-shared`: **0.21.0** - `@metamask/design-system-react`: **0.25.0** - `@metamask/design-system-react-native`: **0.28.0** - `@metamask/design-tokens`: **8.5.0** - `@metamask/design-system-tailwind-preset`: **0.9.0** - `@metamask/design-system-twrnc-preset`: **0.5.0** ### 🔄 Shared Type Updates (0.21.0) #### Added - Added `ContentPropsShared` and `ContentVerticalAlignment` for React Native list-style rows and related layout patterns ([#1192](#1192)) #### Changed - **BREAKING:** Dropped Node.js 18 support for the release line; consumers must run Node 20 or newer ([#1206](#1206)) - **BREAKING:** Updated `TextAreaPropsShared` to remove `inputElement` so React Native `TextArea` can render the root `TextInput` directly ([#1205](#1205)) ### 🌐 React Web Updates (0.25.0) #### Added - Added `Popover` for anchored overlays such as menus, tooltips, and dialogs ([#1153](#1153)) - Added `TextArea` for controlled multiline text entry ([#1036](#1036)) - Added `TextFieldSearch` for controlled search-field flows on top of `TextField` ([#1171](#1171)) - Added `FormTextField` for labeled form controls built from `Label`, `TextField`, and `HelpText` ([#1197](#1197)) #### Changed - **BREAKING:** Dropped Node.js 18 support for the release line; consumers must run Node 20 or newer ([#1206](#1206)) - Updated avatar fallback handling so `AvatarToken`, `AvatarNetwork`, and `AvatarFavicon` resolve consistently when the requested image is unavailable ([#1212](#1212)) ### 📱 React Native Updates (0.28.0) #### Added - Added `Content` for composing scrollable and padded content sections on React Native screens; it is closely related to the upcoming `ListItem` work ([#1192](#1192)) #### Changed - **BREAKING:** Dropped Node.js 18 support for the release line; consumers must run Node 20 or newer ([#1206](#1206)) - Added default padding and `isInteractive` support to `SectionHeader` so section rows match the new mobile layout patterns ([#1210](#1210)) - **BREAKING:** Flattened `TextArea` so it renders the root `TextInput` directly; pass `TextInput` props on `TextArea`, use the component `ref` for the input, and stop relying on `inputProps` or `inputElement` ([#1205](#1205)) - Updated avatar fallback handling so `AvatarToken`, `AvatarNetwork`, and `AvatarFavicon` resolve consistently when the requested image is unavailable ([#1212](#1212)) ###⚠️ Breaking Changes #### Node.js 18 support removed **What Changed:** - The release line now requires Node 20 or newer. - This applies across the monorepo, including the shared package, web package, React Native package, tokens, and both preset packages. **Impact:** - Consumers still on Node 18 must upgrade their runtime before installing or developing against this release line. - Node 18 is end-of-life, so this change aligns the repo with the supported app runtimes. #### React Native `TextArea` flattening **What Changed:** - `TextArea` now renders the root `TextInput` directly. - `inputProps` and `inputElement` are removed. - `inputRef` is replaced by the component `ref`. **Migration:** ```tsx // Before (0.27.0) <TextArea inputProps={{ placeholder: 'Message' }} inputElement={<CustomInput />} /> // After (0.28.0) <TextArea placeholder="Message" ref={inputRef} /> ``` **Impact:** - Affects React Native consumers using `TextArea`. - Call sites that depended on the wrapper/input split need to be updated. See migration guides for complete instructions: - [React Migration Guide](./packages/design-system-react/MIGRATION.md#from-version-0220-to-0230) - [React Native Migration Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0270-to-0280) ### ✅ 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.20.0 → 0.21.0) - shared type additions and breaking TextArea/shared runtime baseline - [x] design-system-react: minor (0.24.0 → 0.25.0) - new components and release-line update - [x] design-system-react-native: minor (0.27.0 → 0.28.0) - new component, SectionHeader update, and breaking TextArea change - [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** - [x] 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 - [ ] All tests pass (`yarn build && yarn test && yarn lint`) - [x] Changelog validation passes (`yarn changelog:validate`) ## **Pre-merge reviewer checklist** - [x] I've reviewed the [Reviewing Release PRs](./docs/reviewing-release-prs.md) guide - [x] Package versions follow semantic versioning - [x] Changelog entries are consumer-facing (not commit message regurgitation) - [x] Breaking changes are documented in MIGRATION.md with examples - [x] All unreleased changes are accounted for in changelogs <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Breaking React Native TextArea and Node 18 removal affect consumer upgrades; most diff is release metadata with coordinated peer dependency bumps. > > **Overview** > **Release 43.0.0** bumps the monorepo root to **43.0.0** and publishes coordinated semver bumps across design-system packages, with **yarn.lock** peer ranges updated for `@metamask/design-system-tailwind-preset` **^0.9.0** and `@metamask/design-system-twrnc-preset` **^0.5.0**. > > Across the release line, changelogs record **Node.js 18 dropped** (Node **20+** required). **@metamask/design-system-react** **0.25.0** documents new **`Popover`**, **`TextArea`**, **`TextFieldSearch`**, and **`FormTextField`**, plus avatar fallback fixes. **@metamask/design-system-react-native** **0.28.0** adds **`Content`**, updates **`SectionHeader`** (default padding, **`isInteractive`**), and includes a **breaking** **`TextArea`** flattening (`inputProps` / `inputElement` / `inputRef` removed; props and **`ref`** target the root **`TextInput`**). **@metamask/design-system-shared** **0.21.0** adds **`ContentPropsShared`** / **`ContentVerticalAlignment`** and removes **`inputElement`** from shared **`TextArea`** props. > > Migration guide edits in this diff: React Native **0.27.0 → 0.28.0** **`TextArea`** guidance; React version heading **0.22.0 → 0.23.0** for **`BannerBase`** (changelog-driven **0.25.0** items are not new migration sections here). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 23b0cda. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->

Description
Added
TextFieldSearchcomponent.Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-318
Manual testing steps
TextFieldSearchcomponentScreenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Low Risk
New UI component and documentation with test coverage; no auth, data, or core runtime path changes.
Overview
Adds
TextFieldSearchto@metamask/design-system-react: a controlled search field on top ofTextFieldwith a default search icon, fixedtype="search", pill styling, and a trailing clearButtonIconwhenvalueis set.clearButtonOnClickis required; clear label defaults to'Clear'and can be localized viaclearButtonProps.ariaLabel(replacing extensionuseI18nContext). The package exports the component and documents extension migration inMIGRATION.md(TextFieldSearchSize→TextFieldSize,is*state props, removed polymorphicas/ configurabletype).Ships Storybook (
README.mdx, stories) and unit tests for rendering, clear-button behavior, andTextFieldforwarding.FormTextFielddocs/tests/stories are adjusted only: stories use inline state /Boxinstead of a shared controlled helper; tests drop size-class assertions and asserttextFieldPropson the inner field viatitle.Reviewed by Cursor Bugbot for commit 67dd120. Bugbot is set up for automated code reviews on this repo. Configure here.