From a08a379fadae79de9e384fc1421d0cf6208debfa Mon Sep 17 00:00:00 2001 From: Mikolaj Adamowicz Date: Fri, 21 Aug 2026 12:43:47 +0200 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20write=20full=20v5=E2=86=92v6=20migr?= =?UTF-8?q?ation=20guide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace the TBC placeholder with complete coverage of packaging, theming, typography, accessibility, and per-component breaking changes for the 6.0 alpha, plus a "Planned for 6.0 stable" section for pending PRs. --- docs/6.x/docs/guides/migration.md | 666 ++++++++++++++++++++++++++---- 1 file changed, 582 insertions(+), 84 deletions(-) diff --git a/docs/6.x/docs/guides/migration.md b/docs/6.x/docs/guides/migration.md index 1fcd32bd25..497691c00e 100644 --- a/docs/6.x/docs/guides/migration.md +++ b/docs/6.x/docs/guides/migration.md @@ -2,127 +2,625 @@ title: Migration from Paper 5.x to 6.x --- -TBC +React Native Paper 6 updates every component to the current Material Design 3 spec and drops Material Design 2 support. The `version: 2` theme switch, the MD2 themes and the MD2-era components are gone. Removed and renamed API has no deprecation aliases, so everything that changed is listed below. -## Components +:::tip +Components and props that are not listed on this page kept their public API. The end of this page lists what is [planned for 6.0 stable](#planned-for-60-stable) but not in the alpha yet. +::: -### TextInput +## Installation and packaging -The Paper 6.x `TextInput` is a complete rewrite with a new API. Import the component the same way, but note that the props and behavior have changed significantly. +### New peer dependencies -#### Types +Animations now run on Reanimated. Install it and its worklets runtime next to the existing `react-native-safe-area-context` peer: -```tsx -import { TextInput, type TextInputProps } from 'react-native-paper'; +```bash npm2yarn +npm install react-native-reanimated react-native-worklets ``` -#### Variant +| v5 peer dependencies | v6 peer dependencies | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `react`, `react-native`, `react-native-safe-area-context` | `react`, `react-native`, `react-native-safe-area-context`, **`react-native-reanimated >=4.3.0`**, **`react-native-worklets >=0.8.1`** | + +### ESM-only package + +The CommonJS build was dropped. `main` now points to `lib/module/index.js` and the `module`, `react-native` and `source` fields are gone. Metro and Re.Pack handle this out of the box. Jest does not, so if your tests import Paper, add it to `transformIgnorePatterns` in your Jest config: + +```js +transformIgnorePatterns: [ + 'node_modules/(?!(@react-native|react-native|react-native-paper|react-native-reanimated|react-native-worklets|react-native-safe-area-context)/)', +], +``` + +### `react-native-paper/react-navigation` entry point removed + +The `react-native-paper/react-navigation` subpath, `createMaterialBottomTabNavigator` and the related types are gone. Use the bottom tabs navigator from React Navigation and render Paper's bar through its `tabBar` prop. The [BottomNavigation with React Navigation guide](./bottom-navigation) walks through it. -- **`mode="flat"`** → **`variant="filled"`** -- **`mode="outlined"`** → **`variant="outlined"`** +| v5 | v6 | +| ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- | +| `import { createMaterialBottomTabNavigator } from 'react-native-paper/react-navigation'` | `createBottomTabNavigator` from `@react-navigation/bottom-tabs` + `tabBar={props => }` | +| `MaterialBottomTabNavigationEventMap`, `MaterialBottomTabNavigationOptions`, `MaterialBottomTabNavigationProp`, `MaterialBottomTabScreenProps` | removed, no replacement (use the `@react-navigation/bottom-tabs` types) | + +```diff +- import { createMaterialBottomTabNavigator } from 'react-native-paper/react-navigation'; ++ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; ++ import { BottomNavigation } from 'react-native-paper'; + +- const Tab = createMaterialBottomTabNavigator(); ++ const Tab = createBottomTabNavigator(); +``` ```tsx -// Before (v5) - - + ( + navigation.navigate(route.name, route.params)} + renderIcon={({ route, focused, color }) => + descriptors[route.key].options.tabBarIcon?.({ focused, color, size: 24 }) ?? null + } + getLabelText={({ route }) => descriptors[route.key].options.title ?? route.name} + /> + )} +> + {/* screens */} + +``` -// After (v6) - - +The `react-native-paper/babel` plugin is unchanged. + +## Theming + +### Material Design 2 is gone + +Everything that existed only to support `version: 2` themes was deleted. There is no replacement for any of it. v6 always renders MD3. + +| v5 | v6 | +| ------------------------------------------------------------------------ | ------------------------------------------------------------- | +| `MD2LightTheme`, `MD2DarkTheme` | removed, no replacement | +| `MD2Colors` | removed, no replacement | +| `MD2Theme` (type) | removed, no replacement | +| `theme.version` (`2 \| 3`) | removed, `PaperProvider` ignores it | +| `theme.isV3` | removed, no replacement | +| `theme.mode` (`'adaptive' \| 'exact'`) | removed, no replacement | +| `theme.colors.accent` and every other MD2-only color role | removed, use the MD3 roles (`primary`, `secondary`, `tertiary`, …) | +| `configureFonts({ isV3: false })` / MD2 `Fonts` (`regular`, `medium`, `light`, `thin`) | removed, `configureFonts({ config })` only accepts the MD3 typescale (see [Fonts](./fonts)) | +| `theme.roundness` | `theme.shapes.corner.*` (`extraSmall`, `small`, `medium`, `large`, `largeIncreased`, `extraLarge`, `extraLargeIncreased`, `extraExtraLarge`) | +| `theme.animation.defaultAnimationDuration` | `theme.motion.duration.*` (`short1`…`extraLong4`); `theme.animation.scale` is kept | + +### Renamed exports + +The `MD3` prefix was dropped from all public names. The v5 names don't exist anymore, not even as type aliases. + +| v5 | v6 | +| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | +| `MD3LightTheme` | `LightTheme` | +| `MD3DarkTheme` | `DarkTheme` | +| `DefaultTheme` | `LightTheme` | +| `MD3Colors` (the reference palette object) | `Palette` | +| `MD3Theme` (type) | `Theme` | +| `ThemeBase` (type) | `Theme` | +| `MD3Elevation` (type) | `Elevation` | +| `MD3TypescaleKey` (runtime **enum**) | `TypescaleKey` (**type-only** union of the same 15 keys). Using it as a value, like `MD3TypescaleKey.bodyLarge`, has no replacement. Write the string `'bodyLarge'` instead | +| `MD3AndroidColors`, `ElevationLevels` (enum), `MD3Palette` (types) | removed, no replacement | + +```diff +- import { MD3LightTheme, MD3Colors, type MD3Theme } from 'react-native-paper'; ++ import { LightTheme, Palette, type Theme } from 'react-native-paper'; + +- const theme: MD3Theme = { +- ...MD3LightTheme, +- roundness: 2, +- colors: { ...MD3LightTheme.colors, primary: MD3Colors.primary40 }, ++ const theme: Theme = { ++ ...LightTheme, ++ shapes: { ...LightTheme.shapes, corner: { ...LightTheme.shapes.corner, small: 8 } }, ++ colors: { ...LightTheme.colors, primary: Palette.primary40 }, + }; ``` -#### Adornments +### Removed color roles and helpers + +| v5 | v6 | +| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| `theme.colors.backdrop` | `theme.colors.scrim` (Paper applies a `0.32` alpha to it) | +| `theme.colors.surfaceDisabled`, `theme.colors.onSurfaceDisabled` | removed, disabled states use `theme.colors.onSurface` at `0.38` opacity | +| `shadow()` export | removed, no replacement. Use `Surface` with `elevation`, or `theme.colors.elevation.levelN` | +| `overlay()` export | removed, no replacement (it was the MD2 dark-mode elevation overlay). Use the `surfaceContainer*` roles | + +### Type changes + +- **`theme.colors.*` is typed `ColorValue`, not `string`.** Code that does string operations on a theme color (`theme.colors.primary.toUpperCase()`, passing it to a `string`-typed prop of another library) needs a cast or `String(...)`. To match, most component color props (`color`, `iconColor`, `buttonColor`, `textColor`, `selectedColor`, `containerColor`, `uncheckedColor`, …) and render prop callbacks (`left({ color })`, `renderIcon({ color })`) changed from `string` to `ColorValue` as well. +- `PaperProvider` now picks light or dark from `theme.dark` (falling back to the system color scheme) and shallow-merges `theme.colors` over the base scheme. A partial `{ colors: { primary } }` override no longer wipes the other roles. `theme.version` is ignored. +- `adaptNavigationTheme` keeps its signature. The generated `colors.card` now maps to `surfaceContainer` instead of `elevation.level2`. + +### New in v6 + +None of this is breaking, but it's useful when replacing removed API. `Theme` has new `shapes`, `motion` and `elevation` sections and 20 new color roles (`surfaceContainer*`, `surfaceDim`/`surfaceBright`, `*Fixed`/`*FixedDim`/`on*Fixed*`, `stateLayerPressed`). `DynamicLightTheme`, `DynamicDarkTheme` and `isDynamicColorSupported` expose Android 12+ dynamic color. `PaperProvider` accepts `direction` (see [RTL](./rtl)) and `reduceMotion` (`'auto' | 'on' | 'off'`), and `useLocale` / `LocaleProvider` are exported. See the [Theming guide](./theming) for the full shape. + +## Typography + +The Material Design 2 typography components, already deprecated in v5, were removed together with their prop types. Use `Text` with a `variant` instead. The `variant` keys are unchanged. With the MD2 fallback gone, `variant` is now always applied. + +| v5 | v6 | +| --------------------------------------------------------------------- | -------------------------------------------- | +| `Caption` (+ `CaptionProps`) | `` | +| `Paragraph` (+ `ParagraphProps`) | `` | +| `Subheading` (+ `SubheadingProps`) | `` | +| `Title` (+ `TitleProps`) | `` | +| `Headline` (+ `HeadlineProps`) | `` | +| `Text` `ref: React.ForwardedRef<{ setNativeProps }>` | `ref: React.Ref<{ setNativeProps(args: object): void }>` | + +```diff +- Headline ++ Headline + +- Title ++ Title + +- Subheading ++ Subheading + +- Paragraph ++ Paragraph + +- Caption ++ Caption +``` + +## Accessibility props → `aria-*` + +All components now take the `aria-*` / `role` props from React Native instead of the older `accessibility*` ones. Where a component declared an accessibility prop in its own `Props`, the prop name changed. Where it only set them internally, the rendered accessibility tree changed but your code doesn't need to. + +| v5 | v6 | +| ---------------------------------------------------------- | ---------------------------------------------------------------- | +| `accessibilityLabel` | `aria-label` | +| `accessibilityRole` | `role` (`'header'` → `'heading'`, `'search'` → `'searchbox'`) | +| `accessibilityState={{ checked }}` | `aria-checked` (`boolean \| 'mixed'`; `'indeterminate'` → `'mixed'`) | +| `accessibilityState={{ selected }}` | `aria-selected` | +| `accessibilityState={{ disabled }}` | `aria-disabled` (derived from `disabled`, can't be overridden) | +| `accessibilityState={{ busy }}` | `aria-busy` | +| `accessibilityState={{ expanded }}` | `aria-expanded` | +| `accessibilityLiveRegion` | `aria-live` (`'none'` → `'off'`) | +| `accessibilityViewIsModal` | `aria-modal` | +| `accessibilityElementsHidden` | `aria-hidden` | +| `accessibilityValue={{ min, max, now }}` | `aria-valuemin`, `aria-valuemax`, `aria-valuenow` | +| `accessibilityTraits`, `accessibilityComponentType` | removed, no replacement (legacy RN props) | + +```diff +- ++ + +- ++ +``` + +**Where `accessibilityLabel` no longer type-checks** (the component has a closed prop set, so the old name is gone): `Checkbox.Item`, `FAB`, `FAB.Extended`, `FAB.Menu` (inside the `trigger` and `items` objects), `List.Accordion`, `Menu.Item`, `RadioButton.Item`, `SegmentedButtons` (inside `buttons[]`), `Switch`, `ToggleButton`, and `BottomNavigation` / `BottomNavigation.Bar` route objects. + +**Where the documented prop changed but the old name still compiles**: `Appbar.Action`, `Appbar.BackAction`, `Button`, `Chip`, `DataTable.Pagination`, `Drawer.Item`, `Drawer.CollapsedItem` and `IconButton` declare `'aria-label'` now, but they also forward native view props, so `accessibilityLabel` still reaches the native view. You should still migrate. `aria-label` is the documented prop and the only one Paper reads. + +Also: + +- `Button` and `Chip`: `accessibilityRole` → `role`. +- `FAB`, `FAB.Extended`, `Menu.Item`: the `accessibilityState` object prop was split into `aria-checked`, `aria-selected`, `aria-busy` and `aria-expanded`. +- `BottomNavigation` and `BottomNavigation.Bar`: route objects use `'aria-label'` instead of `accessibilityLabel` (`getAccessibilityLabel` defaults to `route['aria-label']`). + +**Not renamed** (still the v5 name): `Button.accessibilityHint`, `Chip.closeIconAccessibilityLabel`, `DataTable.Pagination.selectPageDropdownAccessibilityLabel`, `Menu.overlayAccessibilityLabel`, `Searchbar.searchAccessibilityLabel` / `clearAccessibilityLabel` / `traileringIconAccessibilityLabel`, `Snackbar.iconAccessibilityLabel`. + +## Changes that affect many components + +### `rippleColor` removed + +The per-component ripple color override was dropped. Ripples and state layers now come from the MD3 tokens of each component. There is no replacement. + +Removed from: `Button`, `Checkbox.Item`, `Chip`, `Drawer.Item`, `FAB` (and the former `AnimatedFAB` / `FAB.Group`), `List.Accordion`, `Menu.Item`, `RadioButton.Item`, `Searchbar` (`rippleColor` and `traileringRippleColor`), `Snackbar`, `ToggleButton`, and `DataTable.Pagination` (`paginationControlRippleColor`, `dropdownItemRippleColor`, `selectPageDropdownRippleColor`). + +`TouchableRipple` keeps `rippleColor`. Components that forward their props to it (`IconButton`, `Appbar.Action`, `Appbar.BackAction`, `TextInput.Icon`, `Checkbox`, `List.Item`, `DataTable.Row` / `DataTable.Cell`, `RadioButton.Android` / `RadioButton.IOS`) still accept it through that passthrough. It's no longer a documented prop of theirs though, and the default color is now token-driven. + +### `*Variant` props are typed `TypescaleKey` + +`Card.Title` `titleVariant` / `subtitleVariant`, `Checkbox.Item` `labelVariant`, `RadioButton.Item` `labelVariant` and `Text` `variant` were typed `keyof typeof MD3TypescaleKey`. They are now `TypescaleKey`. The accepted strings are the same, only code that passed the enum member breaks. + +### `ref` is no longer part of many `Props` types + +Components whose props extended `React.ComponentPropsWithRef` now extend `ViewProps` (likewise `ImageProps` for `Card.Cover`, `PressableProps` for `DataTable.Title`, `TextProps` for `Badge`). Affected: `ActivityIndicator`, `Avatar.*`, `Badge`, `Card.Actions` / `Content` / `Cover` / `Title`, `DataTable.*`, `Dialog.Actions` / `Content` / `ScrollArea`, `Drawer.*`, `List.Section`, `ProgressBar`, `Surface`. Passing a `ref` still works where the component forwards one. The difference is that `ref` is no longer visible in the `…Props` type. Components that previously used `forwardRef` (`Appbar.Action`, `Appbar.BackAction`, `Button`, `IconButton`, `ToggleButton`, `FAB`, `Surface`) take `ref` as a regular prop typed `React.Ref` instead of `React.RefObject`. + +## Components + +Only components with a changed public API are listed below, in alphabetical order. Accessibility renames, `rippleColor` removals and `string` → `ColorValue` changes are covered above and not repeated per component. + +These are the components and sub-components that no longer exist: + +| v5 | v6 | +| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `AnimatedFAB` (+ `AnimatedFABProps`, `AnimatedFABIconMode`, `AnimatedFABAnimateFrom`) | [`FAB.Extended`](#fabextended-replaces-animatedfab) | +| `FAB.Group` (+ `FABGroupProps`) | [`FAB.Menu`](#fabmenu-replaces-fabgroup) | +| `HelperText` (+ `HelperTextProps`) | [`TextInput` `supportingText`](#helpertext) | +| `Caption`, `Headline`, `Paragraph`, `Subheading`, `Title` | [`Text` with a `variant`](#typography) | +| `TextInput.Affix` (+ `TextInputAffixProps`) | [`TextInput` `prefix` / `suffix`](#textinputaffix) | +| `Checkbox.Android`, `Checkbox.IOS` (+ `CheckboxAndroidProps`, `CheckboxIOSProps`) | [`Checkbox`](#checkbox) | +| `createMaterialBottomTabNavigator` | [React Navigation bottom tabs](#react-native-paperreact-navigation-entry-point-removed) | + +### Appbar (Top app bar) + +`Appbar` / `Appbar.Header` `mode` was ignored under MD2 themes. It is now always applied. + +#### Appbar.Content + +The MD2 subtitle, deprecated in v5, was removed. + +| v5 | v6 | +| ---------------- | ------------------------------------- | +| `subtitle` | removed, no replacement | +| `subtitleStyle` | removed, no replacement | + +```diff +- ++ +``` + +### Badge + +The badge follows the MD3 sizes: a 6dp dot without `children`, a 16dp pill with them. + +| v5 | v6 | +| ---------------------------------------------------- | --------------------------------------------------------- | +| `size` | removed, no replacement. Size is derived from `children` | +| `ref` | removed from props | +| props typed as `Animated.Text` props (`Animated.Value` accepted in `style` etc.) | plain `TextProps`. Pass static values, `visible` handles the fade | + +```diff +- ++ +``` + +### BottomNavigation (Navigation bar) + +Applies to both `BottomNavigation` and `BottomNavigation.Bar`. `BottomNavigation.SceneMap` and the rest of the `Bar` API are unchanged, but see [Planned for 6.0 stable](#planned-for-60-stable). + +| v5 | v6 | +| ------------------------------------------------- | ----------------------------------------------------------------- | +| route `color` | removed, no replacement (MD2 per-tab color) | +| `getColor` | removed, no replacement | +| route `accessibilityLabel` | route `'aria-label'` | +| `shifting` default `routes.length > 3` under MD2 | default `false` | +| `compact` default `!theme.isV3` | default `false` | + +```diff +routes: [ +- { key: 'album', title: 'Album', focusedIcon: 'image-album', color: '#3F51B5', accessibilityLabel: 'Album' }, ++ { key: 'album', title: 'Album', focusedIcon: 'image-album', 'aria-label': 'Album' }, +] +``` + +### Button + +`mode` still accepts `'text' | 'outlined' | 'contained' | 'elevated' | 'contained-tonal'`. + +| v5 | v6 | +| --------------------------- | ------------------------------------------------------------------- | +| `color` | `buttonColor` (background) / `textColor` (label and icon) | +| `accessibilityRole` | `role` | + +```diff +- ++ +``` + +### Checkbox + +`Checkbox` renders one Material 3 checkbox on every platform. The platform-specific components and their prop types are gone. It now also forwards `TouchableRipple` props (`accessible`, `onFocus`, `onBlur`, `borderless`, `rippleColor`, …). -- **`left` / `right`** → **`startAccessory` / `endAccessory`** -- **`TextInput.Affix`** → **`prefix` / `suffix`**, or **`TextInput.Icon`**, or **`startAccessory` / `endAccessory`** +| v5 | v6 | +| ------------------------------------ | ------------------------------------------------------------------------------- | +| `Checkbox.Android`, `Checkbox.IOS` | `Checkbox` | +| `CheckboxAndroidProps`, `CheckboxIOSProps` | `CheckboxProps` | +| n/a | new `error` (uses `theme.colors.error`) and `style` (tap-target style) | + +```diff +- ++ +``` + +#### Checkbox.Item + +| v5 | v6 | +| --------- | ------------------------- | +| `mode` | removed, no replacement | + +```diff +- ++ +``` + +### Chip + +`accessibilityRole` → `role` (default `'button'`). `mode` (`'flat' | 'outlined'`) is unchanged. + +### DataTable + +#### DataTable.Pagination + +`paginationControlRippleColor`, `dropdownItemRippleColor` and `selectPageDropdownRippleColor` were removed with no replacement. All other props are unchanged. + +### Dialog + +#### Dialog.Title + +Its props were based on the removed MD2 `Title` component. They are now based on `Text`, so `variant` is available. `children`, `style` and `theme` are unchanged. + +### FAB (Floating action button) + +The floating action button family was rebuilt on the MD3 spec: `FAB` is the plain button, `FAB.Extended` replaces `AnimatedFAB` and `FAB.Menu` replaces `FAB.Group`. `FAB` now has a closed prop set and no longer spreads `Surface` / `View` props. + +| v5 | v6 | +| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `mode: 'flat' \| 'elevated'` | removed, no replacement. Elevation is token-driven | +| `variant: 'primary' \| 'secondary' \| 'tertiary' \| 'surface'` (default `'primary'`) | `variant: 'primary' \| 'secondary' \| 'tertiary' \| 'tonalPrimary' \| 'tonalSecondary' \| 'tonalTertiary'` (default **`'tonalPrimary'`**; `'surface'` removed) | +| `size: 'small' \| 'medium' \| 'large'` | `size: 'default' \| 'medium' \| 'large'` (56 / 80 / 96dp; `'small'` removed, `'default'` is the default) | +| `small`, `customSize` | removed, no replacement | +| `label` | removed, use `FAB.Extended` | +| `color` | `contentColor` (new `containerColor` for the background) | +| `icon` (optional when `label` was set) | `icon` is required | +| `uppercase`, `animated`, `loading`, `disabled`, `onLongPress`, `delayLongPress`, `labelMaxFontSizeMultiplier` | removed, no replacement | +| `accessibilityLabel`, `accessibilityState` | `aria-label`, `aria-checked` / `aria-selected` / `aria-busy` / `aria-expanded` | +| `style: Animated.WithAnimatedValue>` | `style: StyleProp` | +| `elevation` and other `Surface` props | removed, no replacement | + +```diff +- ++ +``` + +#### FAB.Extended (replaces AnimatedFAB) + +| v5 `AnimatedFAB` | v6 `FAB.Extended` | +| -------------------------------------------------------- | ---------------------------------------------------------------------------- | +| `AnimatedFAB`, `AnimatedFABProps` | `FAB.Extended`, `FABExtendedProps` | +| `extended` | `expanded` | +| `icon`, `label` | unchanged (both required) | +| `color` | `contentColor` (new `containerColor` for the background) | +| `variant: 'primary' \| 'secondary' \| 'tertiary' \| 'surface'` | `variant: 'primary' \| 'secondary' \| 'tertiary' \| 'tonalPrimary' \| 'tonalSecondary' \| 'tonalTertiary'` (`'surface'` removed) | +| `iconMode`, `animateFrom` (+ `AnimatedFABIconMode`, `AnimatedFABAnimateFrom`) | removed, no replacement. The label always animates in layout direction | +| `uppercase`, `disabled`, `onLongPress`, `delayLongPress`, `hitSlop`, `rippleColor` | removed, no replacement | +| `accessibilityLabel`, `accessibilityState` | `aria-label`, `aria-checked` / `aria-selected` / `aria-busy` / `aria-expanded` | +| `style: Animated.WithAnimatedValue>` | `style: StyleProp` | +| n/a | new `size: 'default' \| 'medium' \| 'large'` | + +```diff +- ++ +``` + +#### FAB.Menu (replaces FAB.Group) + +`FAB.Menu` is declarative: the trigger button is described by a `trigger` object and the menu holds between **two and six** `items` (enforced by the type). Per-item styling props were dropped, items are rendered from the theme tokens. + +| v5 `FAB.Group` | v6 `FAB.Menu` | +| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| `FAB.Group`, `FABGroupProps` | `FAB.Menu`, `FABMenuProps` (+ `FABMenuItemProps`, `FABMenuTriggerProps`) | +| `open` | `expanded` | +| `onStateChange({ open })` | `onDismiss()` for closing; open it from `trigger.onPress` | +| `icon`, `color`, `label`, `variant`, `visible`, `onPress`, `accessibilityLabel` on the group | `trigger: { icon, variant?, size?, containerColor?, contentColor?, visible?, onPress?, 'aria-label'?, testID? }` | +| `actions: Array<{ icon, label?, color?, labelTextColor?, style?, containerStyle?, wrapperStyle?, labelStyle?, size?, rippleColor?, accessibilityLabel?, accessibilityHint?, … }>` | `items: [{ icon?, label, onPress, 'aria-label'?, testID? }, …]` (2–6 entries; `label` required, styling props removed) | +| `backdropColor`, `fabStyle`, `style` | removed, no replacement | +| `toggleStackOnLongPress`, `enableLongPressWhenStackOpened`, `onLongPress`, `delayLongPress` | removed, no replacement | +| n/a | new `alignment: 'start' \| 'center' \| 'end'` (default `'end'`), `closeIcon` (default `'close'`) | ```tsx // Before (v5) -} - right={} -/> +const [state, setState] = React.useState({ open: false }); + +; // After (v6) - } - endAccessory={(p) => } - maxLength={100} - prefix="$" - suffix="/100" - counter -/> +const [expanded, setExpanded] = React.useState(false); + + setExpanded(false)} + trigger={{ icon: 'plus', 'aria-label': 'Actions', onPress: () => setExpanded(true) }} + items={[ + { icon: 'email', label: 'Email', onPress: sendEmail }, + { icon: 'star', label: 'Star', onPress: star }, + ]} +/>; ``` -#### Label and supporting text +### HelperText + +`HelperText` and `HelperTextProps` were removed. Supporting text is now rendered by `TextInput` itself through `supportingText`, a plain string. The `type`, `visible`, `padding` and `disabled` props of `HelperText` have no equivalent. The error style follows the input's `error` prop and conditional visibility is up to you (pass `undefined` to hide it). + +```diff +- +- Enter a valid email ++ +``` + +### IconButton + +No hard breaks. `rippleColor` and `accessibilityLabel` are no longer declared props but still pass through to `TouchableRipple` (see above). `mode` (`'outlined' | 'contained' | 'contained-tonal'`) is unchanged. + +### MaterialCommunityIcon (the `settings.icon` renderer) + +`IconProps.name` is typed `string` instead of the vector-icons name union. Custom icon renderers passed to `PaperProvider` `settings={{ icon }}` that relied on the narrower type need to widen their signature. + +### Menu + +`elevation` is typed `Elevation` (same `0`–`5` values). + +#### Menu.Item + +`rippleColor` was removed and the `accessibilityState` object was split into `aria-checked`, `aria-selected`, `aria-busy` and `aria-expanded`. + +### Searchbar + +`rippleColor` and `traileringRippleColor` were removed with no replacement. The `ref` is typed `React.Ref`. + +### SegmentedButtons + +Inside the `buttons` array, `accessibilityLabel` → `'aria-label'`. See also [Planned for 6.0 stable](#planned-for-60-stable). + +### Switch + +`Switch` no longer wraps the `Switch` from React Native and no longer extends its props. Colors come from the theme. -- **`label: React.Element | string`** → **`string`** -- **`HelperText`** was removed; use **`supportingText`**. +| v5 | v6 | +| ----------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `color` | removed. Override `theme.colors` (`primary`, `onPrimary`, `primaryContainer`, `surfaceContainerHighest`, `outline`, `onSurfaceVariant`) | +| `trackColor`, `thumbColor`, `ios_backgroundColor`, `onChange` and every other native `Switch` prop | removed, no replacement | +| `onValueChange?: Function` | `onValueChange?: (value: boolean) => void` | +| `accessibilityLabel` | `aria-label` | +| `ref` | removed from props | +| n/a | new `checkedIcon`, `uncheckedIcon` | + +```diff +- ++ +``` + +### TextInput + +The Paper 6.x `TextInput` is a complete rewrite with a new API. Import the component the same way, but note that the props and behavior have changed significantly. ```tsx -// Before (v5) -<> +import { TextInput, type TextInputProps } from 'react-native-paper'; +``` + +New exported types: `TextInputRenderProps`, `TextInputVariant`, `TextInputHandles`, `TextInputAccessoryProps`, `TextInputIconProps`. Removed: `TextInputAffixProps`, `TextInputLabelProp`. + +#### Variant + +| v5 | v6 | +| ----------------- | -------------------- | +| `mode="flat"` | `variant="filled"` | +| `mode="outlined"` | `variant="outlined"` | + +```diff +- ++ + +- ++ +``` + +#### Adornments + +| v5 | v6 | +| ------------------------------------ | --------------------------------------------------------------------------------------------------- | +| `left` / `right` (elements) | `startAccessory` / `endAccessory`, render props receiving `{ style, multiline, disabled, error }` | +| `TextInput.Affix` | `prefix` / `suffix` (plain, non-pressable strings), or a custom `startAccessory` / `endAccessory` | +| n/a | new `counter` (with `maxLength`) | + +When `error` is set and no `endAccessory` is given, an error icon is rendered automatically. + +```diff } +- right={} ++ startAccessory={(p) => } ++ endAccessory={(p) => } ++ maxLength={100} ++ prefix="$" ++ suffix="/100" ++ counter /> - - Enter a valid email - - +``` -// After (v6) - +#### Label and supporting text + +| v5 | v6 | +| ------------------------------------ | ------------------- | +| `label: React.ReactElement \| string` | `label: string` | +| `HelperText` next to the input | `supportingText` | + +```diff +- +- Enter a valid email ++ ``` #### Removed props No direct `TextInput` equivalents for: -- **`dense`**, **`contentStyle`**, **`underlineStyle`** +- **`dense`**, **`contentStyle`**, **`underlineStyle`**, **`outlineStyle`** - **`underlineColor`**, **`activeUnderlineColor`**, **`outlineColor`**, **`activeOutlineColor`**, **`textColor`** -Use **`style`** on the inner input and the **`theme`** for colors. +Use **`style`** on the inner input and the **`theme`** for colors. `selectionColor`, `cursorColor` and `placeholderTextColor` are still accepted as native passthrough props. Only their defaults changed, they now follow the theme (`primary`, or `error` when `error` is set). -```tsx -import { MD3LightTheme, TextInput } from 'react-native-paper'; +```diff ++ import { LightTheme, TextInput } from 'react-native-paper'; ++ ++ const theme = { ++ ...LightTheme, ++ colors: { ...LightTheme.colors, outline: '#79747E', primary: '#6750A4' }, ++ }; -const theme = { - ...MD3LightTheme, - colors: { - ...MD3LightTheme.colors, - outline: '#79747E', - primary: '#6750A4', - }, -}; + +``` -// Before (v5) - +#### Other behavioural changes -// After (v6) - +- **`render`** now receives `TextInputRenderProps` (the native `TextInput` props plus `ref?: React.RefObject`). The v5 `RenderProps` type is gone and `ref` is an object, not a callback. Custom input integrations (masked inputs etc.) need to adapt. +- **`disabled`** is separate from `editable`. Paper sets `editable` itself, so pass `disabled` instead of `editable={false}`. +- **`multiline`** and **`numberOfLines`** are passed straight to the native input. Paper no longer adjusts its own height logic around them. +- **`onChangeText`** is typed `(text: string) => void` (was `Function`). +- Ref handles `focus`, `blur`, `clear`, `isFocused`, `setNativeProps` and `setSelection` are kept. The undocumented `forceFocus` handle was removed, `focus()` does nothing while `disabled`, and `clear()` now also fires `onChangeText('')`. + +#### TextInput.Icon + +`TextInput.Icon` has to be rendered through the accessory render prop. Its `style`, `multiline`, `disabled` and `error` props are now **required** and are supplied by the input (`{...p}` below). + +| v5 | v6 | +| ------------------------------------------- | ----------------------------------- | +| `forceTextInputFocus` | removed, no replacement | +| `color` (string or `(focused) => string`) | `iconColor` (`ColorValue` only) | +| n/a | `style`, `multiline`, `disabled`, `error` are required | + +```diff +- (focused ? 'red' : 'gray')} />} /> ++ } /> +``` + +#### TextInput.Affix + +Removed together with `TextInputAffixProps`. Its `text`, `onPress`, `textStyle`, `onLayout` and `accessibilityLabel` props have no equivalent. `prefix` / `suffix` are non-pressable strings. If you need more than that, render your own `endAccessory`. + +```diff +- } /> ++ ``` + +### ToggleButton + +Only `rippleColor` was removed. See also [Planned for 6.0 stable](#planned-for-60-stable). + +## Planned for 6.0 stable + +:::warning +The changes below are **not** part of `6.0.0-alpha.0`. They are listed so you can plan ahead. The replacement API will be documented here once each change lands. Follow the linked pull requests for status. +::: + +- **`BottomNavigation` → `NavigationBar`** ([#5006](https://github.com/callstack/react-native-paper/pull/5006)). The scene-transition wrapper (`BottomNavigation`) and `BottomNavigation.SceneMap` are removed. `BottomNavigation.Bar` becomes a top-level `NavigationBar` meant to be driven by React Navigation or your own navigator, and the MD2 `shifting` mode goes away. The [BottomNavigation with React Navigation guide](./bottom-navigation) already shows what this migration looks like. +- **`SegmentedButtons` → `ConnectedButtonGroup`** ([#5028](https://github.com/callstack/react-native-paper/pull/5028)). Material 3 replaced segmented buttons with the connected button group. The new component keeps the `buttons` / `value` / `onValueChange` shape to make the migration easier. +- **`ToggleButton`, `ToggleButton.Group`, `ToggleButton.Row`** and the `Button` **`contained` / `contained-tonal`** modes are planned for removal as part of the Button and IconButton modernization. There is no pull request yet. Until there is, they keep working as documented in v5. From 4f59c3e801d4309bf13a9ed30cd81ffdd11fc3b3 Mon Sep 17 00:00:00 2001 From: Mikolaj Adamowicz Date: Mon, 24 Aug 2026 11:21:42 +0200 Subject: [PATCH 2/2] docs: icon migration compatibility update --- docs/6.x/docs/guides/migration.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/6.x/docs/guides/migration.md b/docs/6.x/docs/guides/migration.md index 497691c00e..695bd691e3 100644 --- a/docs/6.x/docs/guides/migration.md +++ b/docs/6.x/docs/guides/migration.md @@ -22,6 +22,35 @@ npm install react-native-reanimated react-native-worklets | ----------------------------------------------------- | ------------------------------------------------------------------------------------------- | | `react`, `react-native`, `react-native-safe-area-context` | `react`, `react-native`, `react-native-safe-area-context`, **`react-native-reanimated >=4.3.0`**, **`react-native-worklets >=0.8.1`** | +### Icons: only `@react-native-vector-icons/material-design-icons` is auto-detected + +This one fails at runtime, not at compile time. In v5, Paper looked for an icon package in this order: `@react-native-vector-icons/material-design-icons`, then `@expo/vector-icons`, then the old single package `react-native-vector-icons`. In v6 only the first one is picked up. With any of the others, every icon renders as broken (the □ placeholder character) and Paper logs a warning. + +| v5 | v6 | +| ---------------------------------------------------------------------------------------- | --------------------------------------------------------- | +| `@react-native-vector-icons/material-design-icons`, `@expo/vector-icons` or `react-native-vector-icons` picked up automatically | only `@react-native-vector-icons/material-design-icons` | + +If you use `@expo/vector-icons` or `react-native-vector-icons` 10.x, either install the supported package: + +```bash npm2yarn +npm install @react-native-vector-icons/material-design-icons +``` + +or keep your current package and pass a custom icon renderer to `PaperProvider`: + +```js +import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons'; +// ... + + , + }} +> + +; +``` + ### ESM-only package The CommonJS build was dropped. `main` now points to `lib/module/index.js` and the `module`, `react-native` and `source` fields are gone. Metro and Re.Pack handle this out of the box. Jest does not, so if your tests import Paper, add it to `transformIgnorePatterns` in your Jest config: