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;
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 && (
{
+ const tree = (await render()).toJSON();
+
+ expect(tree).toMatchSnapshot();
+});
+
+it('renders vertical divider', async () => {
+ const tree = (await render()).toJSON();
+
+ expect(tree).toMatchSnapshot();
+});
+
+it('renders 1dp thick horizontal line by default', async () => {
+ await render();
+
+ expect(screen.getByTestId('divider', hidden)).toHaveStyle({
+ height: 1,
+ backgroundColor: defaultThemes.light.colors.outlineVariant,
+ });
+});
+
+it('renders 1dp thick line stretched to the parent when vertical', async () => {
+ await render();
+
+ expect(screen.getByTestId('divider', hidden)).toHaveStyle({
+ width: 1,
+ alignSelf: 'stretch',
+ backgroundColor: defaultThemes.light.colors.outlineVariant,
+ });
+ expect(screen.getByTestId('divider', hidden)).not.toHaveStyle({ height: 1 });
+});
+
+it('insets the start edge in a writing direction aware way', async () => {
+ await render();
+
+ const divider = screen.getByTestId('divider', hidden);
+
+ expect(divider).toHaveStyle({ marginStart: 16 });
+ expect(divider).not.toHaveStyle({ marginLeft: 16 });
+});
+
+it('insets both edges', async () => {
+ await render();
+
+ const divider = screen.getByTestId('divider', hidden);
+
+ expect(divider).toHaveStyle({ marginStart: 16, marginEnd: 16 });
+ expect(divider).not.toHaveStyle({ marginLeft: 16 });
+ expect(divider).not.toHaveStyle({ marginRight: 16 });
+});
+
+it('insets the leading end of a vertical divider', async () => {
+ await render();
+
+ const divider = screen.getByTestId('divider', hidden);
+
+ expect(divider).toHaveStyle({ marginTop: 16 });
+ expect(divider).not.toHaveStyle({ marginStart: 16 });
+});
+
+it('insets both ends of a vertical divider', async () => {
+ await render(
+
+ );
+
+ expect(screen.getByTestId('divider', hidden)).toHaveStyle({
+ marginTop: 16,
+ marginBottom: 16,
+ });
+});
+
+it('applies custom styles over the defaults', async () => {
+ await render();
+
+ expect(screen.getByTestId('divider', hidden)).toHaveStyle({ height: 4 });
+});
+
+it('stays out of the accessibility tree', async () => {
+ await render();
+
+ expect(screen.queryByTestId('divider')).toBeNull();
+ expect(screen.getByTestId('divider', hidden)).toHaveProp('aria-hidden', true);
+});
+
+it('can be exposed as a separator', async () => {
+ await render();
+
+ expect(screen.getByRole('separator')).toBeOnTheScreen();
+});
diff --git a/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap
index bcd35191f0..2962eb2958 100644
--- a/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap
+++ b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap
@@ -13,19 +13,19 @@ exports[`DrawerSection renders properly 1`] = `
>
+`;
+
+exports[`renders vertical divider 1`] = `
+
+`;