From 2d896667a9487d8946f6e05b0807d270f70d607e Mon Sep 17 00:00:00 2001 From: Mikolaj Adamowicz Date: Tue, 1 Sep 2026 13:18:37 +0200 Subject: [PATCH] refactor: modernize Divider to latest MD3 spec --- docs/6.x/docs/components/Divider.mdx | 16 +-- docs/6.x/docs/guides/migration.md | 58 +++++++++++ docs/src/data/componentDocs6x.json | 33 +++++-- example/src/Examples/DividerExample.tsx | 67 ++++++++++--- example/src/Examples/FABExample.tsx | 2 +- src/components/Divider.tsx | 65 ++++++++----- src/components/Drawer/DrawerSection.tsx | 1 - src/components/Searchbar.tsx | 1 - src/components/__tests__/Divider.test.tsx | 97 +++++++++++++++++++ .../__snapshots__/DrawerSection.test.tsx.snap | 12 +-- .../__snapshots__/Divider.test.tsx.snap | 40 ++++++++ 11 files changed, 332 insertions(+), 60 deletions(-) create mode 100644 src/components/__tests__/Divider.test.tsx create mode 100644 src/components/__tests__/__snapshots__/Divider.test.tsx.snap diff --git a/docs/6.x/docs/components/Divider.mdx b/docs/6.x/docs/components/Divider.mdx index 02ff41392f..80dfac3a07 100644 --- a/docs/6.x/docs/components/Divider.mdx +++ b/docs/6.x/docs/components/Divider.mdx @@ -10,6 +10,10 @@ import ExtendedExample from '@docs/components/ExtendedExample.tsx'; A divider is a thin, lightweight separator that groups content in lists and page layouts. +Dividers are decorative, so screen readers skip them. If a divider means +something on its own, pass `accessible`, `aria-hidden={false}` and +`role="separator"`. + @@ -42,27 +46,27 @@ export default MyComponent;
-### leftInset Renamed from 'inset' to 'leftInset` in v5.x +### orientation
- +
-### horizontalInset Available in v5.x with theme version 3 +### startInset
- +
-### bold Available in v5.x with theme version 3 +### horizontalInset
- +
diff --git a/docs/6.x/docs/guides/migration.md b/docs/6.x/docs/guides/migration.md index 1fcd32bd25..56eddd6551 100644 --- a/docs/6.x/docs/guides/migration.md +++ b/docs/6.x/docs/guides/migration.md @@ -6,6 +6,64 @@ TBC ## Components +### Divider + +| v5 | v6 | +| --- | --- | +| `leftInset` | `startInset` | +| `bold` | removed, dividers are 1dp thick by default | +| - | `orientation="vertical"` | + +#### Thickness + +Dividers are 1dp thick now, which is what the Material Design 3 spec asks for. In v5 the default was `StyleSheet.hairlineWidth`, thinner than 1dp on most screens, and `bold` was the only way to get a full 1dp line. The `bold` prop is gone. + +```diff +- ++ +``` + +If you want the hairline back, set it in `style`: + +```diff +- ++ +``` + +#### Inset + +`leftInset` set `marginLeft`, so in RTL the inset stayed on the left instead of moving to the leading edge. Use `startInset` instead. It insets the leading edge and follows the writing direction. + +```diff +- ++ +``` + +`horizontalInset` works the same as before. + +#### Orientation + +Dividers can be vertical now. A vertical divider is 1dp wide and stretches to the height of its parent, so the parent has to lay its children out in a row. + +```tsx + + Lemon + + Mango + +``` + +Insets follow the orientation. On a vertical divider, `startInset` insets the top edge, and `horizontalInset` insets the top and bottom edges. + +#### Accessibility + +Dividers are decorative, so screen readers skip them and they stay out of the focus order. If a divider means something on its own, opt back in: + +```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. diff --git a/docs/src/data/componentDocs6x.json b/docs/src/data/componentDocs6x.json index 300c315b99..3557c8369d 100644 --- a/docs/src/data/componentDocs6x.json +++ b/docs/src/data/componentDocs6x.json @@ -5545,38 +5545,53 @@ "Divider": { "filepath": "Divider.tsx", "title": "Divider", - "description": "A divider is a thin, lightweight separator that groups content in lists and page layouts.\n\n## Usage\n```js\nimport * as React from 'react';\nimport { View } from 'react-native';\nimport { Divider, Text } from 'react-native-paper';\n\nconst MyComponent = () => (\n \n Lemon\n \n Mango\n \n \n);\n\nexport default MyComponent;\n```", + "description": "A divider is a thin, lightweight separator that groups content in lists and page layouts.\n\nDividers are decorative, so screen readers skip them. If a divider means\nsomething on its own, pass `accessible`, `aria-hidden={false}` and\n`role=\"separator\"`.\n\n## Usage\n```js\nimport * as React from 'react';\nimport { View } from 'react-native';\nimport { Divider, Text } from 'react-native-paper';\n\nconst MyComponent = () => (\n \n Lemon\n \n Mango\n \n \n);\n\nexport default MyComponent;\n```", "link": "divider", "data": { - "description": "A divider is a thin, lightweight separator that groups content in lists and page layouts.\n\n## Usage\n```js\nimport * as React from 'react';\nimport { View } from 'react-native';\nimport { Divider, Text } from 'react-native-paper';\n\nconst MyComponent = () => (\n \n Lemon\n \n Mango\n \n \n);\n\nexport default MyComponent;\n```", + "description": "A divider is a thin, lightweight separator that groups content in lists and page layouts.\n\nDividers are decorative, so screen readers skip them. If a divider means\nsomething on its own, pass `accessible`, `aria-hidden={false}` and\n`role=\"separator\"`.\n\n## Usage\n```js\nimport * as React from 'react';\nimport { View } from 'react-native';\nimport { Divider, Text } from 'react-native-paper';\n\nconst MyComponent = () => (\n \n Lemon\n \n Mango\n \n \n);\n\nexport default MyComponent;\n```", "displayName": "Divider", "methods": [], "statics": [], "props": { - "leftInset": { + "orientation": { "required": false, "tsType": { - "name": "boolean" + "name": "union", + "raw": "'horizontal' | 'vertical'", + "elements": [ + { + "name": "literal", + "value": "'horizontal'" + }, + { + "name": "literal", + "value": "'vertical'" + } + ] }, - "description": "@renamed Renamed from 'inset' to 'leftInset` in v5.x\nWhether divider has a left inset." + "description": "Orientation of the divider. A vertical divider stretches to the height of\nits parent, so the parent has to lay its children out in a row.", + "defaultValue": { + "value": "'horizontal'", + "computed": false + } }, - "horizontalInset": { + "startInset": { "required": false, "tsType": { "name": "boolean" }, - "description": "@supported Available in v5.x with theme version 3\n Whether divider has a horizontal inset on both sides.", + "description": "Whether the divider is inset from the leading edge, which is the left edge\nin LTR and the right edge in RTL. On a vertical divider it's the top edge.", "defaultValue": { "value": "false", "computed": false } }, - "bold": { + "horizontalInset": { "required": false, "tsType": { "name": "boolean" }, - "description": "@supported Available in v5.x with theme version 3\n Whether divider should be bolded.", + "description": "Whether the divider is inset from both edges: left and right on a\nhorizontal divider, top and bottom on a vertical one.", "defaultValue": { "value": "false", "computed": false diff --git a/example/src/Examples/DividerExample.tsx b/example/src/Examples/DividerExample.tsx index 77df26a85a..a4adb2634b 100644 --- a/example/src/Examples/DividerExample.tsx +++ b/example/src/Examples/DividerExample.tsx @@ -1,28 +1,67 @@ -import { FlatList } from 'react-native'; +import * as React from 'react'; +import { StyleSheet, View } from 'react-native'; -import { Divider, List, useTheme } from 'react-native-paper'; +import { Divider, List, Text } from 'react-native-paper'; import ScreenWrapper from '../ScreenWrapper'; -const items = ['Apple', 'Banana', 'Coconut', 'Lemon', 'Mango', 'Peach']; +const items = ['Apple', 'Banana', 'Coconut']; const DividerExample = () => { - const { colors } = useTheme(); - return ( - - } - keyExtractor={(item) => item} - ItemSeparatorComponent={Divider} - data={items} - alwaysBounceVertical={false} - /> + + + {items.map((item) => ( + + + + + ))} + + + {items.map((item) => ( + + + + + ))} + + + {items.map((item) => ( + + + + + ))} + + + + {items.map((item, index) => ( + + {index > 0 && } + + {item} + + + ))} + + ); }; DividerExample.title = 'Divider'; +const styles = StyleSheet.create({ + row: { + flexDirection: 'row', + marginHorizontal: 16, + }, + column: { + flex: 1, + paddingVertical: 24, + textAlign: 'center', + }, +}); + export default DividerExample; diff --git a/example/src/Examples/FABExample.tsx b/example/src/Examples/FABExample.tsx index 09ce39aa14..db880c2fcf 100644 --- a/example/src/Examples/FABExample.tsx +++ b/example/src/Examples/FABExample.tsx @@ -159,7 +159,7 @@ const FABExample = () => { )} onPress={() => setShowFab((v) => !v)} /> - + & { /** - * @renamed Renamed from 'inset' to 'leftInset` in v5.x - * Whether divider has a left inset. + * Orientation of the divider. A vertical divider stretches to the height of + * its parent, so the parent has to lay its children out in a row. */ - leftInset?: boolean; + orientation?: 'horizontal' | 'vertical'; /** - * @supported Available in v5.x with theme version 3 - * Whether divider has a horizontal inset on both sides. + * Whether the divider is inset from the leading edge, which is the left edge + * in LTR and the right edge in RTL. On a vertical divider it's the top edge. */ - horizontalInset?: boolean; + startInset?: boolean; /** - * @supported Available in v5.x with theme version 3 - * Whether divider should be bolded. + * Whether the divider is inset from both edges: left and right on a + * horizontal divider, top and bottom on a vertical one. */ - bold?: boolean; + horizontalInset?: boolean; style?: StyleProp; /** * @optional @@ -30,6 +33,10 @@ export type Props = $RemoveChildren & { /** * A divider is a thin, lightweight separator that groups content in lists and page layouts. * + * Dividers are decorative, so screen readers skip them. If a divider means + * something on its own, pass `accessible`, `aria-hidden={false}` and + * `role="separator"`. + * * ## Usage * ```js * import * as React from 'react'; @@ -49,25 +56,28 @@ export type Props = $RemoveChildren & { * ``` */ const Divider = ({ - leftInset, + orientation = 'horizontal', + startInset = false, horizontalInset = false, style, theme: themeOverrides, - bold = false, ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const dividerColor = theme.colors.outlineVariant; + const isVertical = orientation === 'vertical'; return ( @@ -75,15 +85,26 @@ const Divider = ({ }; const styles = StyleSheet.create({ - v3LeftInset: { - marginLeft: 16, + horizontal: { + height: THICKNESS, + }, + vertical: { + width: THICKNESS, + alignSelf: 'stretch', + }, + startInset: { + marginStart: INSET, }, horizontalInset: { - marginLeft: 16, - marginRight: 16, + marginStart: INSET, + marginEnd: INSET, + }, + verticalStartInset: { + marginTop: INSET, }, - bold: { - height: 1, + verticalInset: { + marginTop: INSET, + marginBottom: INSET, }, }); diff --git a/src/components/Drawer/DrawerSection.tsx b/src/components/Drawer/DrawerSection.tsx index d267cf4c17..c2b0c50844 100644 --- a/src/components/Drawer/DrawerSection.tsx +++ b/src/components/Drawer/DrawerSection.tsx @@ -102,7 +102,6 @@ const DrawerSection = ({ {showDivider && ( diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index b0819b5710..f269ae3292 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -343,7 +343,6 @@ const Searchbar = ({ right?.({ color: textColor, style: styles.rightStyle, testID })} {!isBarMode && showDivider && (