Skip to content

chore: Added Input component to DSR and DSRN#909

Merged
brianacnguyen merged 11 commits into
mainfrom
migrate/inputs
Feb 19, 2026
Merged

chore: Added Input component to DSR and DSRN#909
brianacnguyen merged 11 commits into
mainfrom
migrate/inputs

Conversation

@brianacnguyen

@brianacnguyen brianacnguyen commented Feb 17, 2026

Copy link
Copy Markdown
Contributor

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:

  • Input in both packages with a shared API: textVariant (typography), isDisabled, isReadonly, plus className (web) / twClassName (native) for overrides. The native Input also supports isStateStylesDisabled to optionally skip disabled/focus state styles. Both extend their platform’s native input (HTML input / RN TextInput).
  • Web (DSR): New component using twMerge, design-token Tailwind classes, and Text typography constants (CLASSMAP_TEXT_VARIANT_FONTSTYLE, CLASSMAP_TEXT_VARIANT_FONTWEIGHT). Supports forwardRef, className, and style.
  • Mobile (DSRN): Migrated Input aligned with DSRN templates: styling via useTailwind and 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.
  • Exports added in both packages. Storybook stories (Default, Variant, IsDisabled, IsReadonly) and documentation (README.mdx for web, README.md for native) added for both. Unit tests added for both implementations.

Related issues

Fixes: N/A

Manual testing steps

  1. Web: Run yarn storybook and open Input under React Components. Confirm Default, Variant (textVariant), IsDisabled, and IsReadonly stories.
  2. React Native: Run yarn storybook:ios or yarn storybook:android and open Input under Components. Confirm the same variants and that focus/disabled/readonly states look correct.
  3. Run tests: yarn workspace @metamask/design-system-react run test -- Input.test and yarn 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

  • 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

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 Input component to both @metamask/design-system-react (HTML input) 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 via useTailwind, theme-based placeholder color via useTheme, focus/disabled state styling (with optional isStateStylesDisabled), 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.

@brianacnguyen brianacnguyen self-assigned this Feb 17, 2026
@brianacnguyen brianacnguyen requested a review from a team as a code owner February 17, 2026 00:29
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

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

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

if (!isDisabled) {
setIsFocused(false);
onBlur?.(e);
}

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.

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.

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is an extreme edge case that we should ignore

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react/src/components/Input/Input.tsx
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview


const resolvedStyle = [
inputStyle,
Platform.OS === 'ios' && { textAlignVertical: 'center' as const },

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.

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)

Fix in Cursor Fix in Web

@github-actions

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.

},
ref,
) => {
const [isFocused, setIsFocused] = useState(autoFocus);

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.

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)

Fix in Cursor Fix in Web

@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.

Looking good! Left some minor suggestions

Comment thread packages/design-system-react-native/src/components/Input/Input.constants.ts Outdated
Comment thread packages/design-system-react-native/src/components/Input/Input.constants.ts 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/Input/README.md
Comment thread packages/design-system-react-native/src/components/Input/README.md Outdated
Comment thread packages/design-system-react/src/components/Input/Input.constants.ts Outdated
Comment thread packages/design-system-react/src/components/Input/Input.stories.tsx
Comment thread packages/design-system-react/src/components/Input/Input.test.tsx Outdated
georgewrmarshall added a commit that referenced this pull request Feb 18, 2026
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)
@kirillzyusko kirillzyusko mentioned this pull request Feb 18, 2026
7 tasks
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@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.

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 🙏

@georgewrmarshall georgewrmarshall enabled auto-merge (squash) February 19, 2026 19:58
@brianacnguyen

Copy link
Copy Markdown
Contributor Author

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

@brianacnguyen brianacnguyen enabled auto-merge (squash) February 19, 2026 20:13
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@brianacnguyen brianacnguyen merged commit c59863a into main Feb 19, 2026
43 checks passed
@brianacnguyen brianacnguyen deleted the migrate/inputs branch February 19, 2026 20:17
georgewrmarshall added a commit that referenced this pull request Feb 20, 2026
## 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>
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