diff --git a/docs/manifest.json b/docs/manifest.json
index 41fbf7da9dae29..0c8ae73274ed07 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -1043,6 +1043,12 @@
"markdown_source": "../packages/components/src/navigable-container/README.md",
"parent": "components"
},
+ {
+ "title": "Navigation",
+ "slug": "navigation",
+ "markdown_source": "../packages/components/src/navigation/README.md",
+ "parent": "components"
+ },
{
"title": "Notice",
"slug": "notice",
diff --git a/packages/components/src/navigation/README.md b/packages/components/src/navigation/README.md
new file mode 100644
index 00000000000000..87bab075e53e8b
--- /dev/null
+++ b/packages/components/src/navigation/README.md
@@ -0,0 +1,43 @@
+# Navigation
+
+Navigation is a component which renders a component which renders a heirarchy of menu items.
+
+## Usage
+
+```jsx
+import { MenuItem } from '@wordpress/components';
+import { withState } from '@wordpress/compose';
+
+const data = [
+ { title: 'My Navigation', slug: 'root', back: 'Back' },
+ { title: 'Home', slug: 'home', parent: 'root', menu: 'primary' },
+ { title: 'Option one', slug: 'option_one', parent: 'root', menu: 'primary' },
+ { title: 'Option two', slug: 'option_two', parent: 'root', menu: 'primary' },
+ { title: 'Option three', slug: 'option_three', parent: 'root', menu: 'secondary' },
+ { title: 'Child one', slug: 'child_one', parent: 'option_three', menu: 'primary' },
+ { title: 'Child two', slug: 'child_two', parent: 'option_three', menu: 'primary' },
+ { title: 'Child three', slug: 'child_three', parent: 'option_three', menu: 'primary' },
+];
+
+const MyNavigation = () => {
+ return ;
+};
+```
+
+## Props
+
+Navigation supports the following props.
+
+### `data`
+
+- Type: `array`
+- Required: Yes
+
+An array of config objects for each menu item.
+
+### `initial`
+
+- Type: `string`
+- Required: Yes
+
+The active slug.
\ No newline at end of file
diff --git a/packages/components/src/navigation/index.js b/packages/components/src/navigation/index.js
new file mode 100644
index 00000000000000..bf5199edc2cb9e
--- /dev/null
+++ b/packages/components/src/navigation/index.js
@@ -0,0 +1,76 @@
+/**
+ * WordPress dependencies
+ */
+import { useState } from '@wordpress/element';
+import { Icon, arrowLeft } from '@wordpress/icons';
+
+/**
+ * Internal dependencies
+ */
+import Button from '../button';
+import Text from '../text';
+import Item from './item';
+
+const Navigation = ( { data, initial } ) => {
+ const initialActive = data.find( ( item ) => item.slug === initial );
+ const [ active, setActive ] = useState( initialActive );
+ const parent = data.find( ( item ) => item.slug === active.parent );
+ const items = data.filter( ( item ) => item.parent === active.parent );
+
+ const goBack = () => {
+ if ( ! parent.parent ) {
+ // We are at top level, will need to handle this case.
+ return;
+ }
+ const parentalSiblings = data.filter(
+ ( item ) => item.parent === parent.parent
+ );
+ if ( parentalSiblings.length ) {
+ setActive( parentalSiblings[ 0 ] );
+ }
+ };
+
+ return (
+
+
+
+ { parent.title }
+
+
+ { items.map( ( item ) =>
+ item.menu !== 'secondary' ? (
+
+ ) : null
+ ) }
+
+
+ { items.map( ( item ) =>
+ item.menu === 'secondary' ? (
+
+ ) : null
+ ) }
+
+
+ );
+};
+
+export default Navigation;
diff --git a/packages/components/src/navigation/item.js b/packages/components/src/navigation/item.js
new file mode 100644
index 00000000000000..b3453dbbf99793
--- /dev/null
+++ b/packages/components/src/navigation/item.js
@@ -0,0 +1,36 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+import { Icon, chevronRight } from '@wordpress/icons';
+
+/**
+ * Internal dependencies
+ */
+import Button from '../button';
+import Text from '../text';
+
+const Item = ( { data, item, setActive, isActive } ) => {
+ const children = data.filter( ( d ) => d.parent === item.slug );
+ const onSelect = () => {
+ const next = children.length ? children[ 0 ] : item;
+ setActive( next );
+ };
+ const classes = classnames( 'components-navigation__menu-item', {
+ 'is-active': isActive,
+ } );
+ return (
+
+ );
+};
+
+export default Item;
diff --git a/packages/components/src/navigation/stories/index.js b/packages/components/src/navigation/stories/index.js
new file mode 100644
index 00000000000000..ede16f3046136f
--- /dev/null
+++ b/packages/components/src/navigation/stories/index.js
@@ -0,0 +1,90 @@
+/**
+ * Internal dependencies
+ */
+import Navigation from '../';
+
+export default {
+ title: 'Components/Navigation',
+ component: Navigation,
+};
+
+const data = [
+ { title: 'WooCommerce', slug: 'root', back: 'Dashboard' },
+ { title: 'Home', slug: 'home', parent: 'root', menu: 'primary' },
+ {
+ title: 'Analytics',
+ slug: 'analytics',
+ parent: 'root',
+ back: 'WooCommerce Home',
+ menu: 'primary',
+ },
+ {
+ title: 'Orders',
+ slug: 'orders',
+ parent: 'root',
+ back: 'WooCommerce Home',
+ menu: 'primary',
+ },
+ {
+ title: 'Overview',
+ slug: 'overview',
+ parent: 'analytics',
+ },
+ {
+ title: 'Products report',
+ slug: 'products',
+ parent: 'analytics',
+ },
+ {
+ title: 'All orders',
+ slug: 'all_orders',
+ parent: 'orders',
+ },
+ {
+ title: 'Payouts',
+ slug: 'payouts',
+ parent: 'orders',
+ },
+ {
+ title: 'Settings',
+ slug: 'settings',
+ parent: 'root',
+ back: 'WooCommerce Home',
+ menu: 'secondary',
+ },
+ {
+ title: 'Extensions',
+ slug: 'extensions',
+ parent: 'root',
+ back: 'WooCommerce Home',
+ menu: 'secondary',
+ },
+ {
+ title: 'General',
+ slug: 'general',
+ parent: 'settings',
+ },
+ {
+ title: 'Tax',
+ slug: 'tax',
+ parent: 'settings',
+ },
+ {
+ title: 'My extensions',
+ slug: 'my_extensions',
+ parent: 'extensions',
+ },
+ {
+ title: 'Marketplace',
+ slug: 'marketplace',
+ parent: 'extensions',
+ },
+];
+
+function Example() {
+ return ;
+}
+
+export const _default = () => {
+ return ;
+};
diff --git a/packages/components/src/navigation/style.scss b/packages/components/src/navigation/style.scss
new file mode 100644
index 00000000000000..1c90f0573f0439
--- /dev/null
+++ b/packages/components/src/navigation/style.scss
@@ -0,0 +1,30 @@
+.components-navigation {
+ width: 272px;
+ padding: 35px 30px;
+}
+
+.components-navigation__back {
+ margin-bottom: 64px;
+}
+
+.components-navigation__title {
+ margin-bottom: 40px;
+}
+
+.components-navigation__menu-items {
+ display: flex;
+ flex-direction: column;
+
+ &.is-secondary {
+ margin-top: 24px;
+ }
+}
+
+.components-navigation__menu-item {
+ display: flex;
+ justify-content: space-between;
+
+ &.is-active span {
+ border-bottom: 2px solid var(--wp-admin-theme-color);
+ }
+}
diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss
index 36c406c3c7a414..3066b604428cc5 100644
--- a/packages/components/src/style.scss
+++ b/packages/components/src/style.scss
@@ -29,6 +29,7 @@
@import "./menu-item/style.scss";
@import "./menu-items-choice/style.scss";
@import "./modal/style.scss";
+@import "./navigation/style.scss";
@import "./notice/style.scss";
@import "./panel/style.scss";
@import "./placeholder/style.scss";