chore: Added Input component to DSR and DSRN#909
Conversation
📖 Storybook Preview |
📖 Storybook Preview |
| if (!isDisabled) { | ||
| setIsFocused(false); | ||
| onBlur?.(e); | ||
| } |
There was a problem hiding this comment.
Blur callback dropped after disable
Medium Severity
onBlur is only forwarded when isDisabled is false. If the input is focused and then becomes disabled, the native blur event can occur but the consumer’s onBlur never runs. This can leave parent form state out of sync because blur-driven validation or touched-state updates are skipped.
There was a problem hiding this comment.
This is an extreme edge case that we should ignore
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
|
|
||
| const resolvedStyle = [ | ||
| inputStyle, | ||
| Platform.OS === 'ios' && { textAlignVertical: 'center' as const }, |
There was a problem hiding this comment.
Platform check reverses vertical alignment behavior
Low Severity
textAlignVertical is applied only when Platform.OS === 'ios', but this prop is effective on Android and ignored on iOS. This makes Input.tsx skip the alignment style on the platform where it works, causing inconsistent vertical text alignment and leaving an ineffective style path on iOS.
Additional Locations (1)
📖 Storybook Preview |
| }, | ||
| ref, | ||
| ) => { | ||
| const [isFocused, setIsFocused] = useState(autoFocus); |
There was a problem hiding this comment.
Readonly autofocused input shows false focus state
Low Severity
isFocused is initialized from autoFocus, but isReadonly makes TextInput non-editable via editable={false}. With isReadonly and autoFocus together, the component can render with focused border styles even though the input cannot actually receive focus, creating a persistent incorrect visual state in Input.tsx.
Additional Locations (2)
georgewrmarshall
left a comment
There was a problem hiding this comment.
Looking good! Left some minor suggestions
Added "Anti-Patterns to Avoid" section with 3 key patterns identified in PR reviews: 1. SAMPLE_PROPS constants - Use component default parameters instead 2. Default test IDs - No defaults, consumer provides when needed, React uses data-testid 3. String children type checking - Use explicit props or require Text composition Also condensed Benefits and Quick Decision Rules sections to keep file at 398 lines (within 200-400 target). References: - PR #909 review: #909 (review) - PR #908 discussion: #908 (comment)
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
georgewrmarshall
left a comment
There was a problem hiding this comment.
Great work! Looks good would it be possible to address the Cursor comments? If they're not applicable or false or resolved we should comment that and the why. We should treat them like legitimate reviews. It helps with final review 🙏
Will merge to unblock @kirillzyusko . Will create a follow up PR to address these cursor comments |
📖 Storybook Preview |
## Summary Reverts the failed Release 20.0.0 (#921) to redo it properly with complete changelogs and correct yarn.lock. ## Context Release 20.0.0 was merged to main but the publish workflow failed due to a yarn.lock issue: - **Failed workflow:** https://github.com/MetaMask/metamask-design-system/actions/runs/22198282954 - **Root cause:** yarn.lock not updated when peer dependency changed After the release was merged, 7 additional PRs were merged to main: 1. Label component (#907) 2. HeaderBase component (#902) 3. Skeleton (#891) 4. Card (#923) 5. BottomSheetFooter (#899) 6. Toast (#892) 7. Input component (#909) ## Why Revert? To maintain clean version history and proper changelogs: - Release 20.0.0 was never published to NPM (latest is 19.0.0) - The 7 PRs merged after are not documented in Release 20.0.0 changelog - Reverting allows us to create a proper Release 20.0.0 that includes ALL changes ## Changes This PR reverts commit `45004196` which: - Restores package versions to pre-release state (8.1.1, 0.7.0, 0.6.0, etc.) - Restores root package.json version from 20.0.0 to 19.0.0 - Removes Release 20.0.0 changelog entries ## Next Steps After this is merged: 1. Create new `release/20.0.0` branch using standard release process 2. Include all changes (original + 7 PRs) in changelogs 3. **Run `yarn install` to update yarn.lock** 4. Merge new Release 20.0.0 PR 5. Publish workflow will succeed with correct lockfile 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>


Description
This PR adds the Input component to both
@metamask/design-system-react(web) and@metamask/design-system-react-native(mobile).Reason for the change: A shared, light-weight borderless input is needed for use inside TextField and other form contexts across MetaMask products. Migrating and adding Input to the design system keeps styling and behavior consistent and avoids duplication.
What’s included:
textVariant(typography),isDisabled,isReadonly, plusclassName(web) /twClassName(native) for overrides. The native Input also supportsisStateStylesDisabledto optionally skip disabled/focus state styles. Both extend their platform’s native input (HTMLinput/ RNTextInput).twMerge, design-token Tailwind classes, and Text typography constants (CLASSMAP_TEXT_VARIANT_FONTSTYLE,CLASSMAP_TEXT_VARIANT_FONTWEIGHT). SupportsforwardRef,className, andstyle.useTailwindand design tokens,useTheme+ design-tokens for placeholder color, named exports, and typography from Text constants. Exported from the package index with stories, tests, and README.Related issues
Fixes: N/A
Manual testing steps
yarn storybookand open Input under React Components. Confirm Default, Variant (textVariant), IsDisabled, and IsReadonly stories.yarn storybook:iosoryarn storybook:androidand open Input under Components. Confirm the same variants and that focus/disabled/readonly states look correct.yarn workspace @metamask/design-system-react run test -- Input.testandyarn workspace @metamask/design-system-react-native run test -- Input.test.Screenshots/Recordings
Before
N/A — new component in DSR; migrated/realigned component in DSRN.
After
DSR
Screen.Recording.2026-02-16.at.4.25.54.PM.mov
DSRN
Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2026-02-16.at.16.19.26.mov
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Low Risk
New component addition with limited blast radius; risk is mostly visual/behavioral regressions in consumers due to default styling and RN focus/disabled handler logic.
Overview
Adds a new
Inputcomponent to both@metamask/design-system-react(HTMLinput) and@metamask/design-system-react-native(TextInput) with a mostly shared API (textVariant,isDisabled,isReadonly) and per-platform styling override props (className/twClassName).Includes platform-specific behavior/styling: web uses Tailwind class composition via
twMerge, while RN applies Tailwind styles viauseTailwind, theme-based placeholder color viauseTheme, focus/disabled state styling (with optionalisStateStylesDisabled), and iOS vertical text alignment.Wires the component into public exports in both packages, adds Storybook stories (and registers RN story), and adds docs (
README.mdx/README.md) plus unit tests covering states, typography variant styling, ref forwarding (web), and focus/blur handling (RN).Written by Cursor Bugbot for commit 64f1356. This will update automatically on new commits. Configure here.