diff --git a/.storybook/preview.js b/.storybook/preview.js
index 9888b23ab..16f8c38fc 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -4,11 +4,9 @@ import * as configs from '../src/config';
import '../src/assets/styles/main.scss';
-for (const configName in configs) {
- const config = configs[configName];
- config.configure();
-}
+configs.icons.configure();
+Vue.use(configs.constants);
Vue.component('font-awesome-icon', FontAwesomeIcon);
export const parameters = {
diff --git a/.storybook/routeDecorator.js b/.storybook/routeDecorator.js
new file mode 100644
index 000000000..059a9cc31
--- /dev/null
+++ b/.storybook/routeDecorator.js
@@ -0,0 +1,21 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+
+// abbreviated example of https://github.com/gvaldambrini/storybook-router/blob/master/packages/vue/vue.js
+
+export default (path = '/') => {
+ return (storyFn) => {
+ Vue.use(VueRouter);
+ const router = new VueRouter({ mode: 'history' });
+
+ router.replace(path);
+
+ const WrappedComponent = storyFn();
+
+ return Vue.extend({
+ router,
+ components: { WrappedComponent },
+ template: ''
+ });
+ }
+}
\ No newline at end of file
diff --git a/.stylelintrc b/.stylelintrc
index 40db42c66..500a7d3e4 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -1,3 +1,6 @@
{
- "extends": "stylelint-config-standard"
+ "extends": "stylelint-config-standard",
+ "rules": {
+ "at-rule-no-unknown": null
+ }
}
diff --git a/package-lock.json b/package-lock.json
index 7c7257d8c..2ad052226 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,8 @@
"@fortawesome/pro-light-svg-icons": "^5.15.3",
"@fortawesome/vue-fontawesome": "^2.0.2",
"core-js": "^3.6.5",
- "vue": "^2.6.11"
+ "vue": "^2.6.11",
+ "vue-router": "^3.5.1"
},
"devDependencies": {
"@babel/core": "^7.13.16",
@@ -31438,6 +31439,11 @@
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
"dev": true
},
+ "node_modules/vue-router": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz",
+ "integrity": "sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw=="
+ },
"node_modules/vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@@ -58496,6 +58502,11 @@
}
}
},
+ "vue-router": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz",
+ "integrity": "sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw=="
+ },
"vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
diff --git a/package.json b/package.json
index f413e3223..0ece67f26 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,8 @@
"@fortawesome/pro-light-svg-icons": "^5.15.3",
"@fortawesome/vue-fontawesome": "^2.0.2",
"core-js": "^3.6.5",
- "vue": "^2.6.11"
+ "vue": "^2.6.11",
+ "vue-router": "^3.5.1"
},
"devDependencies": {
"@babel/core": "^7.13.16",
diff --git a/src/assets/images/iconOverview.svg b/src/assets/images/iconOverview.svg
new file mode 100644
index 000000000..0a975c0e9
--- /dev/null
+++ b/src/assets/images/iconOverview.svg
@@ -0,0 +1,20 @@
+
diff --git a/src/components/MainNavigation/MainNavigation.mdx b/src/components/MainNavigation/MainNavigation.mdx
new file mode 100644
index 000000000..c7633959d
--- /dev/null
+++ b/src/components/MainNavigation/MainNavigation.mdx
@@ -0,0 +1,92 @@
+import {
+ Preview,
+ Story,
+ ArgsTable,
+ PRIMARY_STORY,
+} from "@storybook/addon-docs/blocks";
+import MainNavigation from "./MainNavigation.vue";
+import MainNavigationItem from "./MainNavigationItem.vue";
+import MainNavigationChildItem from "./MainNavigationChildItem.vue";
+
+# MainNavigation
+
+The main navigation component is used for displaying the main, vertical navigation.
+
+
+
+
+
+## How to Use
+
+The main navigation renders a semantic `nav` element with a `ul`. It is made to work with `main-navigation-item` components. However, you can also write custom components for its slot as long as the root element is an `li` (for accessibility).
+
+The main navigation has a single prop, `collapsible` to control whether it has a click event on desktop that animates the navigation on click to slide in to a smaller width. This can give the user more screen real estate. `collapsible` defaults to true. If you do not want this animation, set this to false.
+
+When `collapsible` is true, the main navigation component passes information about it's expanded/collapsed state through slot props. This requires you passes the expanded prop to the child components in the template (see example below).
+
+Example of using this component in a template
+```html
+
+
+
+
+
+
+
+
+
+```
+
+# Main Navigation Item
+
+The main navigation item component is used for displaying a top level navigation item in the main, vertical navigation.
+
+
+
+
+
+## How to Use
+
+The main navigation item component can render as a traditional link (hooked up to your app's routing) or as a button that will show its child nav items on click.
+
+If you pass a `to` property, it will render as a link. Otherwise, it will render as a button.
+
+The `expanded` prop should come from the parent main navigation component and will control whether the item renders at full width on desktop or only renders wide enough to show its icon.
+
+Example of using this component in a template as a link.
+```html
+
+```
+
+If you provide children elements in the default slot, it will bind a click event to the button to hide/show the child nav items. If you do not want to allow the user to collapse this subnavigation (i.e. you want the child items always visible), set the `collapsible` prop on the main navigation item component to false.
+
+If you want the component to render with the child items collapsed by default, you can use the `subNavCollapsed` prop set to true.
+
+Example of using this component in a template as a button with child nav items.
+```html
+
+
+
+
+```
+
+# MainNavigationChildItem
+
+The main navigation child item component is used for displaying a sub level navigation item in the main, vertical navigation.
+
+
+
+
+
+## How to Use
+
+The main navigation child item component renders as link (hooked up to your app's routing).
+
+Example of using this component in a template
+```html
+
+```
+
+## Props
+
+
\ No newline at end of file
diff --git a/src/components/MainNavigation/MainNavigation.stories.js b/src/components/MainNavigation/MainNavigation.stories.js
new file mode 100644
index 000000000..823e12d19
--- /dev/null
+++ b/src/components/MainNavigation/MainNavigation.stories.js
@@ -0,0 +1,109 @@
+import routeDecorator from '../../../.storybook/routeDecorator';
+
+import MainNavigation from './MainNavigation.vue';
+import MainNavigationItem from './MainNavigationItem.vue';
+import MainNavigationChildItem from './MainNavigationChildItem.vue';
+import mdx from './MainNavigation.mdx';
+import iconOverview from '../../assets/images/iconOverview.svg';
+
+export default {
+ title: 'Components/Main Navigation',
+ component: MainNavigation,
+ subcomponents: { MainNavigationItem, MainNavigationChildItem },
+ decorators: [
+ () => ({ template: '