Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions packages/design-system-react-native/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This guide provides detailed instructions for migrating your project from one ve
- [BannerBase Component](#bannerbase-component)
- [Text Component](#text-component)
- [Icon Component](#icon-component)
- [Input Component](#input-component)
- [Version Updates](#version-updates)
- [From version 0.12.0 to 0.13.0](#from-version-0120-to-0130)
- [From version 0.11.0 to 0.12.0](#from-version-0110-to-0120)
Expand Down Expand Up @@ -644,6 +645,85 @@ import { Icon, IconName, IconSize, IconColor } from '@metamask/design-system-rea
- `hitSlop` remains available via inherited `ViewProps`
- `twClassName` is available for Tailwind utility overrides in the design system

### Input Component

The Input component has a mostly aligned API when migrating from the mobile component-library. The largest differences are around value control and default focus behavior.

#### Breaking Changes

##### Import Path

| Mobile Pattern | Design System Migration |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------ |
| `import Input from '.../Form/TextField/foundation/Input'` | `import { Input } from '@metamask/design-system-react-native'` |
| `import { TextVariant } from '.../components/Texts/Text'` | `import { TextVariant } from '@metamask/design-system-react-native'` |

##### Structured API Mapping

| Change Type | Mobile API | Design System API | Notes |
| ----------- | ---------- | ----------------- | ----- |
| Type/Behavior Change | `value?: string` from inherited `TextInputProps` | `value: string` (required) | Design system Input is controlled-only; provide a string value. |
| Default Change | `autoFocus = true` | `autoFocus = false` | Inputs no longer focus by default on mount. |
| Unchanged | `isDisabled?: boolean` | `isDisabled?: boolean` | Same meaning; maps to `editable={!isDisabled && !isReadonly}`. |
| Unchanged | `isReadonly?: boolean` | `isReadonly?: boolean` | Same meaning; maps to `editable={!isDisabled && !isReadonly}`. |
| Unchanged | `isStateStylesDisabled?: boolean` | `isStateStylesDisabled?: boolean` | Same behavior for focus/disabled state styling toggles. |
| Unchanged | `textVariant?: TextVariant` | `textVariant?: TextVariant` | Same prop, with `TextVariant.BodyMd` default in both implementations. |
| Added | — | `twClassName?: string` | Tailwind class overrides are now first-class via `twClassName`. |
| Unchanged | `onBlur` / `onFocus` event callbacks | `onBlur` / `onFocus` event callbacks | Same signature; still receive native focus events. |
| Unchanged | `onChangeText` | `onChangeText` | Same callback for text updates. |

#### Migration Examples

##### Before (Mobile)

```tsx
import Input from '../../../component-library/components/Form/TextField/foundation/Input';
import { TextVariant } from '../../../component-library/components/Texts/Text';

<Input
value={searchText}
placeholder="Search"
textVariant={TextVariant.BodyMd}
autoFocus
isDisabled={isLoading}
isReadonly={isReadonly}
onChangeText={setSearchText}
/>;
```

##### After (Design System)

```tsx
import {
Input,
TextVariant,
} from '@metamask/design-system-react-native';

<Input
value={searchText}
placeholder="Search"
textVariant={TextVariant.BodyMd}
isDisabled={isLoading}
isReadonly={isReadonly}
twClassName="px-2"
onChangeText={setSearchText}
/>;
```

##### Default Focus Behavior (If You Relied on Auto-Focus)

```tsx
import { Input } from '@metamask/design-system-react-native';

<Input value={searchText} autoFocus onChangeText={setSearchText} />;
```

#### API Differences

- `value` is now required, so initialize controlled state before rendering.
- `twClassName` is supported for Tailwind utility overrides in addition to `style`.
- Placeholder visibility and input metrics handling are preserved, including iOS placeholder line-height behavior.

## Version Updates

This section covers version-to-version breaking changes within `@metamask/design-system-react-native`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,7 @@ export const ConditionalExample = ({ isFocused }: { isFocused: boolean }) => {
## References

[MetaMask Design System Guides](https://www.notion.so/MetaMask-Design-System-Guides-Design-f86ecc914d6b4eb6873a122b83c12940)

## Migration from Mobile Component Library

For detailed migration instructions from the Mobile component-library, see the [Migration Guide](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react-native/MIGRATION.md#input-component).
87 changes: 87 additions & 0 deletions packages/design-system-react/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This guide provides detailed instructions for migrating your project from one ve
- [BannerBase Component](#bannerbase-component)
- [Text Component](#text-component)
- [Icon Component](#icon-component)
- [Input Component](#input-component)
- [Version Updates](#version-updates)
- [From version 0.12.0 to 0.13.0](#from-version-0120-to-0130)
- [From version 0.10.0 to 0.11.0](#from-version-0100-to-0110)
Expand Down Expand Up @@ -580,6 +581,92 @@ import {
- Icon color values should use `IconColor` enum values from `@metamask/design-system-react`
- Use SVG props directly for accessibility and rendering behavior

### Input Component

The Input component has breaking API changes when migrating from the extension component-library. The extension Input was polymorphic and inherited Box style-utility props, while the design system Input is a standard HTML `<input>` wrapper with an explicit API surface.

Refer to [General Extension Migration Guidance](#general-extension-migration-guidance) for the shared Box/style-utility migration approach used across all components.

#### Breaking Changes

##### Import Path

| Extension Pattern | Design System Migration |
| ------------------------------------------------------- | ----------------------------------------------------------- |
| `import { Input } from '../../component-library'` | `import { Input } from '@metamask/design-system-react'` |
| `import { InputType } from './input.types'` | Use native input `type` strings (for example `'text'`) |
| `import { TextVariant } from '../../../helpers/...` | `import { TextVariant } from '@metamask/design-system-react'` |

##### Structured API Mapping

| Change Type | Extension API | Design System API | Notes |
| ----------- | ------------- | ----------------- | ----- |
| Renamed | `disabled?: boolean` | `isDisabled?: boolean` | Use `isDisabled` to set `disabled` on the underlying `<input>`. |
| Renamed | `readOnly?: boolean` | `isReadonly?: boolean` | Use `isReadonly` to set `readOnly` on the underlying `<input>`. |
| Removed | `disableStateStyles?: boolean` | Removed | Design system Input always applies its state styles; use `className` overrides when needed. |
| Removed | `error?: boolean` | Removed | Pass `aria-invalid` directly when needed. |
| Removed | Polymorphic `as` support via `PolymorphicComponentPropWithRef` | Removed | Design system Input always renders an `<input>`. |
| Removed | Box `StyleUtilityProps` on Input (`margin`, `padding`, etc.) | Removed | Wrap with `Box`/layout primitives or use `className` for spacing/layout. |
| Type/Value Change | `autoComplete?: boolean` | Native `autoComplete?: string` | Migrate `true`/`false` usage to valid HTML autocomplete tokens (`'on'`, `'off'`, `'email'`, etc.). |
| Type/Value Change | `type?: InputType` (`text`, `number`, `password`, `search`) | Native input `type` strings | InputType enum is removed; use plain string values supported by HTML input. |
| Callback Signature Change | `onBlur?: () => void` | `onBlur?: FocusEventHandler<HTMLInputElement>` | Event object is now provided. |
| Callback Signature Change | `onFocus?: () => void` | `onFocus?: FocusEventHandler<HTMLInputElement>` | Event object is now provided. |
| Callback Signature Change | `onChange?: () => void` | `onChange?: ChangeEventHandler<HTMLInputElement>` | Event object is now provided. |
| Default Change | `textVariant = TextVariant.bodyMd` | `textVariant = TextVariant.BodyMd` | Enum member casing changed to PascalCase. |
| Behavior Note | `type` explicitly defaulted to `InputType.Text` in component | Browser default `type="text"` when omitted | Behavior is effectively unchanged when `type` is omitted. |

#### Migration Examples

##### Before (Extension)

```tsx
import { Input } from '../../component-library';
import {
TextVariant,
} from '../../../helpers/constants/design-system';

<Input
type="search"
textVariant={TextVariant.bodyMd}
autoComplete={false}
disabled={isLocked}
readOnly={isReadonly}
disableStateStyles
error={hasError}
onChange={() => {
// Legacy callback did not receive the event argument.
}}
/>;
```

##### After (Design System)

```tsx
import {
Input,
TextVariant,
} from '@metamask/design-system-react';

<Input
type="search"
textVariant={TextVariant.BodyMd}
autoComplete="off"
isDisabled={isLocked}
isReadonly={isReadonly}
aria-invalid={hasError}
onChange={(event) => {
const nextValue = event.currentTarget.value;
setSearch(nextValue);
}}
/>;
```

#### API Differences

- `className` and `style` remain available for customization.
- `placeholder`, `name`, `id`, `required`, `maxLength`, `value`, and `defaultValue` continue to work via inherited native input props.
- For layout concerns previously handled by Box style props on Input, prefer wrapping with `Box` and using layout props there.

## Version Updates

This section covers version-to-version breaking changes within `@metamask/design-system-react`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ The `style` prop should primarily be used for dynamic inline styles that cannot

<Controls of={InputStories.Default} />

## Migration from Extension Component Library

For detailed migration instructions from the Extension component-library, see the [Migration Guide](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react/MIGRATION.md#input-component).

## References

[MetaMask Design System Guides](https://www.notion.so/MetaMask-Design-System-Guides-Design-f86ecc914d6b4eb6873a122b83c12940)
Loading