about summary refs log tree commit diff
path: root/components
diff options
context:
space:
mode:
authorPatryk Niedźwiedziński <pniedzwiedzinski19@gmail.com>2019-12-06 17:42:16 -0500
committerGitHub <noreply@github.com>2019-12-06 17:42:16 -0500
commitc1bb2e70e0a85227df899eccc6ac8cf661afe350 (patch)
treea12f43e34e0d32e68f0a14c9512b2b08af54829b /components
parentfaaf63ad895bd51541a9984273d52c71645a0b28 (diff)
parentc7306cfdbaa50c89639fe38bb1b4005ed3555422 (diff)
downloadpuszcza-c1bb2e70e0a85227df899eccc6ac8cf661afe350.tar.gz
puszcza-c1bb2e70e0a85227df899eccc6ac8cf661afe350.zip
Merge pull request #14 from 19pdh/develop
Storybook and license
Diffstat (limited to 'components')
-rw-r--r--components/Buttons/PlainButton.stories.js18
-rw-r--r--components/Buttons/PlainButton.vue34
-rw-r--r--components/Facebook/FacebookFeed.stories.js13
-rw-r--r--components/Facebook/FacebookFeed.vue (renamed from components/FacebookFeed.vue)10
-rw-r--r--components/Facebook/FacebookFindUsButton.stories.js13
-rw-r--r--components/Facebook/FacebookFindUsButton.vue48
-rw-r--r--components/FacebookFindUsButton.vue35
-rw-r--r--components/JoinUs.stories.js16
-rw-r--r--components/JoinUs.vue18
-rw-r--r--components/NavLink.stories.js19
-rw-r--r--components/NavLink.vue20
-rw-r--r--components/Posts/PostLink.stories.js21
-rw-r--r--components/Posts/PostLink.vue (renamed from components/ChroniclePost.vue)46
-rw-r--r--components/Posts/PostList/PostList.vue34
-rw-r--r--components/Posts/PostList/PurePostList.stories.js30
-rw-r--r--components/Posts/PostList/PurePostList.vue91
-rw-r--r--components/Posts/PostList/README.md42
-rw-r--r--components/Posts/PostList/index.js22
-rw-r--r--components/Posts/PostList/parentMixin.js9
-rw-r--r--components/Ranking/RankingEntry.stories.js19
-rw-r--r--components/Ranking/RankingFirstEntry.stories.js16
-rw-r--r--components/Ranking/RankingFirstEntry.vue1
-rw-r--r--components/Ranking/RankingList.stories.js23
-rw-r--r--components/TheFooter.stories.js29
-rw-r--r--components/TheFooter.vue (renamed from components/Footer.vue)1
-rw-r--r--components/TheHeader.stories.js24
-rw-r--r--components/TheHeader.vue (renamed from components/NavBar.vue)63
27 files changed, 611 insertions, 104 deletions
diff --git a/components/Buttons/PlainButton.stories.js b/components/Buttons/PlainButton.stories.js
new file mode 100644
index 0000000..43efa24
--- /dev/null
+++ b/components/Buttons/PlainButton.stories.js
@@ -0,0 +1,18 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../../.storybook/decorators'
+
+import PlainButton from './PlainButton'
+
+const plainButton = {
+  text: 'Plain Button'
+}
+
+storiesOf('Buttons/PlainButton', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { PlainButton },
+      template: `<plain-button :text="text" />`,
+      data: () => plainButton
+    }
+  })
diff --git a/components/Buttons/PlainButton.vue b/components/Buttons/PlainButton.vue
new file mode 100644
index 0000000..0bf57cc
--- /dev/null
+++ b/components/Buttons/PlainButton.vue
@@ -0,0 +1,34 @@
+<template>
+  <button class="button" @click="$emit('click')">{{ text }}</button>
+</template>
+
+<script>
+export default {
+  name: 'PlainButton',
+  props: {
+    text: {
+      type: String,
+      required: true
+    }
+  }
+}
+</script>
+
+<style scoped>
+.button {
+  background-color: #507b34;
+  padding: 10px;
+  max-width: 150px;
+  border: none;
+
+  cursor: pointer;
+
+  color: #ffffff;
+  text-align: center;
+  font: 16px 'Roboto Slab';
+}
+
+.button:hover {
+  background-color: #42642b;
+}
+</style>
diff --git a/components/Facebook/FacebookFeed.stories.js b/components/Facebook/FacebookFeed.stories.js
new file mode 100644
index 0000000..d9ec30a
--- /dev/null
+++ b/components/Facebook/FacebookFeed.stories.js
@@ -0,0 +1,13 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../../.storybook/decorators'
+
+import FacebookFeed from './FacebookFeed'
+
+storiesOf('Facebook/FacebookFeed', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { FacebookFeed },
+      template: `<facebook-feed />`
+    }
+  })
diff --git a/components/FacebookFeed.vue b/components/Facebook/FacebookFeed.vue
index 9d2d251..56172f4 100644
--- a/components/FacebookFeed.vue
+++ b/components/Facebook/FacebookFeed.vue
@@ -1,12 +1,12 @@
 <template>
   <section class="feed">
     <h1>Zobacz co się dzieje!</h1>
-    <FacebookFindUsButton />
+    <facebook-find-us-button />
   </section>
 </template>
 
 <script>
-import FacebookFindUsButton from "./FacebookFindUsButton.vue";
+import FacebookFindUsButton from './FacebookFindUsButton.vue'
 
 export default {
   components: {
@@ -15,11 +15,15 @@ export default {
   props: {
     pageId: String
   }
-};
+}
 </script>
 
 <style scoped>
 .feed {
   margin: 50px 0;
 }
+
+.feed > h1 {
+  text-align: center;
+}
 </style>
\ No newline at end of file
diff --git a/components/Facebook/FacebookFindUsButton.stories.js b/components/Facebook/FacebookFindUsButton.stories.js
new file mode 100644
index 0000000..e6a298b
--- /dev/null
+++ b/components/Facebook/FacebookFindUsButton.stories.js
@@ -0,0 +1,13 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../../.storybook/decorators'
+
+import FacebookFindUsButton from './FacebookFindUsButton'
+
+storiesOf('Facebook/FacebookFindUsButton', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { FacebookFindUsButton },
+      template: `<facebook-find-us-button />`
+    }
+  })
diff --git a/components/Facebook/FacebookFindUsButton.vue b/components/Facebook/FacebookFindUsButton.vue
new file mode 100644
index 0000000..b955b0b
--- /dev/null
+++ b/components/Facebook/FacebookFindUsButton.vue
@@ -0,0 +1,48 @@
+<template>
+  <a
+    class="button"
+    href="https://facebook.com/19pdhpuszcza"
+    target="_blank"
+    rel="noopener"
+  >
+    <div class="button-container">
+      <img
+        class="image"
+        src="/assets/social/find_us_fb.png"
+        alt="Find us on Facebook"
+      />
+    </div>
+  </a>
+</template>
+
+<style scoped>
+.button {
+  margin: 10px;
+}
+
+.button:hover .button-container {
+  background-color: #efefef;
+}
+
+.button-container {
+  border: 2px solid #c4c4c4;
+  border-radius: 4px;
+  padding: 15px 40px;
+}
+
+.image {
+  width: 200px;
+  display: block;
+  margin: auto;
+}
+
+@media (max-width: 500px) {
+  a {
+    width: 100%;
+  }
+
+  .image {
+    width: 150px;
+  }
+}
+</style>
diff --git a/components/FacebookFindUsButton.vue b/components/FacebookFindUsButton.vue
deleted file mode 100644
index 9a27c11..0000000
--- a/components/FacebookFindUsButton.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-<template>
-  <a href="https://facebook.com/19pdhpuszcza" target="_blank" rel="noopener">
-    <div class="button">
-      <img class="image" src="/assets/social/find_us_fb.png" alt="Find us on Facebook" />
-    </div>
-  </a>
-</template>
-
-<style scoped>
-.button {
-  border: 2px solid #c4c4c4;
-  border-radius: 4px;
-
-  padding: 15px 40px;
-  margin: 10px;
-}
-
-.button:hover {
-  background-color: #efefef;
-}
-
-.image {
-  width: 200px;
-}
-
-@media (max-width: 500px) {
-  a {
-    width: 100%;
-  }
-
-  .image {
-    width: 150px;
-  }
-}
-</style>
\ No newline at end of file
diff --git a/components/JoinUs.stories.js b/components/JoinUs.stories.js
new file mode 100644
index 0000000..81bf934
--- /dev/null
+++ b/components/JoinUs.stories.js
@@ -0,0 +1,16 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../.storybook/decorators'
+
+import JoinUs from './JoinUs'
+
+const joinUs = {}
+
+storiesOf('JoinUs', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { JoinUs },
+      template: `<join-us />`,
+      data: () => joinUs
+    }
+  })
diff --git a/components/JoinUs.vue b/components/JoinUs.vue
index f534d22..d8bfadf 100644
--- a/components/JoinUs.vue
+++ b/components/JoinUs.vue
@@ -4,13 +4,22 @@
       <div class="title">
         <div class="text">Rozpocznij swoją harcerską przygodę!</div>
       </div>
-      <div class="button">
-        <router-link to="/kontakt">Dołącz do nas!</router-link>
-      </div>
+      <plain-button @click="$router.push('/kontakt')" text="Dołącz do nas" />
     </div>
   </section>
 </template>
 
+<script>
+import PlainButton from './Buttons/PlainButton'
+
+export default {
+  name: 'JoinUs',
+  components: {
+    PlainButton
+  }
+}
+</script>
+
 <style scoped>
 .joinus {
   width: 100%;
@@ -53,10 +62,11 @@
   background-color: #507b34;
   padding: 10px;
   max-width: 150px;
+  color: #ffffff;
+  text-align: center;
 }
 
 .button a {
-  color: #ffffff;
   text-decoration: none;
 }
 
diff --git a/components/NavLink.stories.js b/components/NavLink.stories.js
new file mode 100644
index 0000000..44fe6ae
--- /dev/null
+++ b/components/NavLink.stories.js
@@ -0,0 +1,19 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../.storybook/decorators'
+
+import NavLink from './NavLink'
+
+const navLink = {
+  name: 'Test',
+  link: '/test'
+}
+
+storiesOf('NavLink', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { NavLink },
+      template: `<nav-link :name="name" :link="link" />`,
+      data: () => navLink
+    }
+  })
diff --git a/components/NavLink.vue b/components/NavLink.vue
index bb86ef8..0418172 100644
--- a/components/NavLink.vue
+++ b/components/NavLink.vue
@@ -9,10 +9,22 @@
 <script>
 export default {
   props: {
-    link: String,
-    name: String,
-    external: { type: Boolean, default: false },
-    pure: { type: Boolean, default: false }
+    link: {
+      type: String,
+      required: true
+    },
+    name: {
+      type: String,
+      required: true
+    },
+    external: {
+      type: Boolean,
+      default: false
+    },
+    pure: {
+      type: Boolean,
+      default: false
+    }
   }
 }
 </script>
diff --git a/components/Posts/PostLink.stories.js b/components/Posts/PostLink.stories.js
new file mode 100644
index 0000000..9b12c29
--- /dev/null
+++ b/components/Posts/PostLink.stories.js
@@ -0,0 +1,21 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../../.storybook/decorators'
+
+import PostLink from './PostLink'
+
+export const postLink = {
+  title: 'Test PostLink',
+  description:
+    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar non ex non sagittis. Quisque in enim tellus. Aliquam consequat mi id sapien congue, sit amet vulputate tortor viverra. Donec.',
+  route: '/kronika/2019/20/11/test'
+}
+
+storiesOf('Posts/PostLink', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { PostLink },
+      template: `<post-link :title="title" :description="description" :route="route"/>`,
+      data: () => postLink
+    }
+  })
diff --git a/components/ChroniclePost.vue b/components/Posts/PostLink.vue
index 7b2c527..54cd934 100644
--- a/components/ChroniclePost.vue
+++ b/components/Posts/PostLink.vue
@@ -1,15 +1,17 @@
 <template>
-  <a :href="route" class="post">
-    <div>
-      <h4 class="post-title">{{title}}</h4>
-      <p class="post-description">{{shortenedDescription}}...</p>
-    </div>
-  </a>
+  <div class="post-link">
+    <a :href="route">
+      <div class="post-container">
+        <h4 class="post-title">{{ title }}</h4>
+        <p class="post-description">{{ shortenedDescription }}...</p>
+      </div>
+    </a>
+  </div>
 </template>
 
 <script>
 export default {
-  name: 'ChroniclePost',
+  name: 'PostLink',
   props: {
     title: {
       type: String,
@@ -34,27 +36,39 @@ export default {
 </script>
 
 <style scoped>
-.post {
+.post-link {
   margin: 20px;
   flex-basis: 410px;
+  max-width: 410px;
+  /* height: 250px; */
+  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25);
+  background: #ffffff;
+  text-align: left;
+  transition: transform 300ms ease-in-out;
+}
+
+.post-link:hover {
+  box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
+  transform: scale(1.02);
+}
+
+.post-link > a {
   text-decoration: none;
+  height: 100%;
 }
 
-.post > div {
-  background: #ffffff;
-  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25);
+.post-link .post-container {
   padding: 20px;
-
-  text-align: left;
+  height: 100%;
 }
 
-.post-title {
+.post-link .post-title {
   color: #181818;
   font-size: 1.3em;
 }
 
-.post-description {
+.post-link .post-description {
   color: #484848;
   font-size: 0.9em;
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/components/Posts/PostList/PostList.vue b/components/Posts/PostList/PostList.vue
new file mode 100644
index 0000000..80369a8
--- /dev/null
+++ b/components/Posts/PostList/PostList.vue
@@ -0,0 +1,34 @@
+<template>
+  <pure-post-list v-if="posts" :posts="parsedPosts" :loading="loading" />
+</template>
+
+<script>
+import PurePostList from './PurePostList'
+
+export default {
+  name: 'PostList',
+  components: { PurePostList },
+  props: {
+    max: {
+      type: Number,
+      required: false,
+      default: () => 4
+    },
+    posts: {
+      type: Array,
+      required: false
+    }
+  },
+  computed: {
+    parsedPosts() {
+      if (this.max) {
+        return this.posts.slice(0, this.max)
+      }
+      return this.posts
+    },
+    loading() {
+      return this.posts === undefined
+    }
+  }
+}
+</script>
diff --git a/components/Posts/PostList/PurePostList.stories.js b/components/Posts/PostList/PurePostList.stories.js
new file mode 100644
index 0000000..e2c39de
--- /dev/null
+++ b/components/Posts/PostList/PurePostList.stories.js
@@ -0,0 +1,30 @@
+import { storiesOf } from '@storybook/vue'
+
+import { postLink } from '../PostLink.stories'
+
+import PurePostList from './PurePostList'
+
+export const posts = Array(5).fill(postLink)
+
+storiesOf('Posts/PurePostList', module)
+  .add('default', () => {
+    return {
+      components: { PurePostList },
+      template: `<pure-post-list :posts="posts"/>`,
+      data: () => ({ posts })
+    }
+  })
+  .add('loading', () => {
+    return {
+      components: { PurePostList },
+      template: `<pure-post-list :posts="posts" loading/>`,
+      data: () => ({ posts: [] })
+    }
+  })
+  .add('no posts', () => {
+    return {
+      components: { PurePostList },
+      template: `<pure-post-list :posts="posts"/>`,
+      data: () => ({ posts: [] })
+    }
+  })
diff --git a/components/Posts/PostList/PurePostList.vue b/components/Posts/PostList/PurePostList.vue
new file mode 100644
index 0000000..ace069f
--- /dev/null
+++ b/components/Posts/PostList/PurePostList.vue
@@ -0,0 +1,91 @@
+<template>
+  <div class="post-list">
+    <div v-if="loading" class="post-list-container">
+      <div class="loading-post" v-for="(_, index) in 4" :key="index"></div>
+    </div>
+    <div v-else-if="!posts" class="no-posts">Brak wpisów</div>
+    <transition name="fade-in">
+      <div v-if="posts && !loading" class="post-list-container">
+        <post-link
+          v-for="(post, index) in posts"
+          :key="index"
+          :route="post.route"
+          :title="post.title"
+          :description="post.description"
+        />
+      </div>
+    </transition>
+  </div>
+</template>
+
+<script>
+import PostLink from '../PostLink'
+
+export default {
+  name: 'PurePostList',
+  components: { PostLink },
+  props: {
+    posts: {
+      type: Array,
+      required: true
+    },
+    loading: {
+      type: Boolean,
+      required: false,
+      default: () => false
+    }
+  }
+}
+</script>
+
+<style scoped>
+.post-list {
+  width: 100%;
+  max-width: 900px;
+  justify-content: center;
+  margin: 0 auto;
+}
+
+.post-list-container {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+}
+
+@keyframes loading {
+  0%,
+  100% {
+    opacity: 1;
+  }
+  50% {
+    opacity: 0.5;
+  }
+}
+
+.loading-post {
+  background: #efefef;
+  animation: loading 1.5s ease-in-out infinite;
+  margin: 20px;
+  flex-basis: 410px;
+  width: 410px;
+  height: 250px;
+  text-align: left;
+}
+
+.no-posts {
+  text-align: center;
+}
+
+@keyframes fade-in {
+  0% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+
+.fade-in-enter-active {
+  animation: fade-in 0.3s reverse;
+}
+</style>
diff --git a/components/Posts/PostList/README.md b/components/Posts/PostList/README.md
new file mode 100644
index 0000000..839f9c2
--- /dev/null
+++ b/components/Posts/PostList/README.md
@@ -0,0 +1,42 @@
+## PostList
+
+This component creates a list of posts
+
+### Usage
+
+```html
+<template>
+  <post-list :posts="posts">
+</template>
+
+<script>
+import PostList, { getPosts } from '~/components/Posts/PostList';
+
+export default {
+  components: { PostList },
+  async asyncData() {
+    return {
+      posts: await getPosts()
+    }
+  }
+}
+</script>
+```
+
+Or by using the mixin
+
+```html
+<template>
+  <post-list :posts="posts">
+</template>
+
+<script>
+import PostList from '~/components/Posts/PostList';
+import postListParentMixin from '~/components/Posts/PostList/parentMixin';
+
+export default {
+  components: { PostList },
+  mixins: [postListParentMixin]
+}
+</script>
+```
diff --git a/components/Posts/PostList/index.js b/components/Posts/PostList/index.js
new file mode 100644
index 0000000..11d44ff
--- /dev/null
+++ b/components/Posts/PostList/index.js
@@ -0,0 +1,22 @@
+import axios from 'axios'
+
+import k from '~/api'
+import PostList from './PostList'
+
+export const getPosts = async () => {
+  if (process.client) {
+    let posts = await axios.get(`${window.location.origin}/api/posts.json`)
+    return parsePosts(posts.data)
+  } else {
+    return parsePosts(k.getPosts())
+  }
+}
+
+export const parsePosts = posts =>
+  posts.map(post => ({
+    title: post.content.meta.title,
+    description: post.content.description,
+    route: post.route
+  }))
+
+export default PostList
diff --git a/components/Posts/PostList/parentMixin.js b/components/Posts/PostList/parentMixin.js
new file mode 100644
index 0000000..e5b06ed
--- /dev/null
+++ b/components/Posts/PostList/parentMixin.js
@@ -0,0 +1,9 @@
+import { getPosts } from './index'
+
+export default {
+  async asyncData() {
+    return {
+      posts: await getPosts()
+    }
+  }
+}
diff --git a/components/Ranking/RankingEntry.stories.js b/components/Ranking/RankingEntry.stories.js
new file mode 100644
index 0000000..20bf6e1
--- /dev/null
+++ b/components/Ranking/RankingEntry.stories.js
@@ -0,0 +1,19 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../../.storybook/decorators'
+
+import RankingEntry from './RankingEntry'
+
+export const rankingEntry = {
+  troop: 'Test',
+  points: 32
+}
+
+storiesOf('Ranking/RankingEntry', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { RankingEntry },
+      template: `<ranking-entry :troop="troop" :points="points" />`,
+      data: () => rankingEntry
+    }
+  })
diff --git a/components/Ranking/RankingFirstEntry.stories.js b/components/Ranking/RankingFirstEntry.stories.js
new file mode 100644
index 0000000..05fa517
--- /dev/null
+++ b/components/Ranking/RankingFirstEntry.stories.js
@@ -0,0 +1,16 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../../.storybook/decorators'
+
+import RankingFirstEntry from './RankingFirstEntry'
+
+import { rankingEntry } from './RankingEntry.stories'
+
+storiesOf('Ranking/RankingFirstEntry', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { RankingFirstEntry },
+      template: `<ranking-first-entry :troop="troop" :points="points" />`,
+      data: () => rankingEntry
+    }
+  })
diff --git a/components/Ranking/RankingFirstEntry.vue b/components/Ranking/RankingFirstEntry.vue
index d9f290b..ad0bea0 100644
--- a/components/Ranking/RankingFirstEntry.vue
+++ b/components/Ranking/RankingFirstEntry.vue
@@ -44,6 +44,7 @@ export default {
 
 .ranking-first-entry__troop {
   grid-column: 2;
+  text-align: center;
 }
 
 .ranking-first-entry__points {
diff --git a/components/Ranking/RankingList.stories.js b/components/Ranking/RankingList.stories.js
new file mode 100644
index 0000000..ad3576b
--- /dev/null
+++ b/components/Ranking/RankingList.stories.js
@@ -0,0 +1,23 @@
+import { storiesOf } from '@storybook/vue'
+import { center } from '../../.storybook/decorators'
+
+import RankingList from './RankingList'
+
+import { rankingEntry } from './RankingEntry.stories'
+
+const rankingList = {
+  scores: Array.from(Array(3).keys()).map(i => ({
+    ...rankingEntry,
+    troop: `Troop${i}`
+  }))
+}
+
+storiesOf('Ranking/RankingList', module)
+  .addDecorator(center)
+  .add('default', () => {
+    return {
+      components: { RankingList },
+      template: `<ranking-list :scores="scores" />`,
+      data: () => rankingList
+    }
+  })
diff --git a/components/TheFooter.stories.js b/components/TheFooter.stories.js
new file mode 100644
index 0000000..ceb5015
--- /dev/null
+++ b/components/TheFooter.stories.js
@@ -0,0 +1,29 @@
+import { storiesOf } from '@storybook/vue'
+import { action } from '@storybook/addon-actions'
+
+import TheFooter from './TheFooter'
+
+export const routes = [
+  { path: '/', name: 'Strona główna' },
+  { path: '/download', name: 'Do pobrania' },
+  { path: '/kontakt', name: 'Kontakt' },
+  { path: '/kronika', name: 'Kronika' }
+]
+
+const footer = {
+  routes
+}
+
+const alwaysBottom = () => ({
+  template: `<div style="display:flex;flex-direction:column;min-height:100vh"><div style="flex:1"></div><story/></div>`
+})
+
+storiesOf('TheFooter', module)
+  .addDecorator(alwaysBottom)
+  .add('default', () => {
+    return {
+      components: { TheFooter },
+      template: `<the-footer :routes="routes" />`,
+      data: () => footer
+    }
+  })
diff --git a/components/Footer.vue b/components/TheFooter.vue
index 69ea76a..e19c86a 100644
--- a/components/Footer.vue
+++ b/components/TheFooter.vue
@@ -25,6 +25,7 @@
 
 <script>
 export default {
+  name: 'TheFooter',
   props: {
     routes: Array,
     specialRoutes: Array,
diff --git a/components/TheHeader.stories.js b/components/TheHeader.stories.js
new file mode 100644
index 0000000..ee320b7
--- /dev/null
+++ b/components/TheHeader.stories.js
@@ -0,0 +1,24 @@
+import { storiesOf } from '@storybook/vue'
+import { routes } from './TheFooter.stories'
+
+import TheHeader from './TheHeader'
+
+const header = {
+  routes,
+  title: '19 PDH Puszcza',
+  logo: '/assets/krajka-logo.svg'
+}
+
+const alwaysTop = () => ({
+  template: `<div style="display:flex;flex-direction:column;min-height:100vh"><story/><div style="flex:1"></div></div>`
+})
+
+storiesOf('TheHeader', module)
+  .addDecorator(alwaysTop)
+  .add('default', () => {
+    return {
+      components: { TheHeader },
+      template: `<the-header :routes="routes" :title="title" :logo="logo"/>`,
+      data: () => header
+    }
+  })
diff --git a/components/NavBar.vue b/components/TheHeader.vue
index 4bbae72..4d17616 100644
--- a/components/NavBar.vue
+++ b/components/TheHeader.vue
@@ -1,27 +1,20 @@
 <template>
-  <nav :class="navbarClass">
+  <nav class="navbar" :class="{ 'menu-open': showMenu }">
     <div class="title">
       <img v-if="logo" class="logo" :src="logo" alt="ZHR" />
-      <nuxt-link :class="titleClass" to="/">{{ title }}</nuxt-link>
+      <nuxt-link class="title-name" :class="{ margin: logo }" to="/">{{
+        title
+      }}</nuxt-link>
     </div>
     <div class="space"></div>
     <button @click="toggleMenu" class="menu-toggler">Menu</button>
-    <ul :class="linksClass" @click="toggleMenu">
+    <ul class="links" :class="{ show: this.showMenu }" @click="toggleMenu">
       <!-- Loop for generating links -->
-      <NavLink v-for="route in routes" :key="route.path" :link="route.path" :name="route.name" />
-      <NavLink
-        v-for="route in staticRoutes"
+      <nav-link
+        v-for="route in routes"
         :key="route.path"
         :link="route.path"
         :name="route.name"
-        pure
-      />
-      <NavLink
-        v-for="route in externalRoutes"
-        :key="route.path"
-        :link="route.path"
-        :name="route.name"
-        external
       />
     </ul>
   </nav>
@@ -31,47 +24,33 @@
 import NavLink from './NavLink'
 
 export default {
+  name: 'TheHeader',
   components: {
     NavLink
   },
   props: {
-    routes: Array,
-    externalRoutes: Array,
-    staticRoutes: Array,
-    title: String,
-    logo: String
-  },
-  computed: {
-    titleClass() {
-      if (this.logo) {
-        return 'title-name margin'
-      }
-      return 'title-name'
+    routes: {
+      type: Array,
+      required: true
     },
-    navbarClass() {
-      if (this.menuCollapsed) {
-        return 'navbar'
-      }
-      return 'navbar menu-open'
+    title: {
+      type: String,
+      required: true
     },
-    linksClass() {
-      if (this.menuCollapsed) {
-        return 'links'
-      }
-      return 'links show'
+    logo: {
+      type: String,
+      required: false,
+      default: () => ''
     }
   },
   data: function() {
     return {
-      menuCollapsed: true
+      showMenu: false
     }
   },
   methods: {
     toggleMenu() {
-      this.menuCollapsed = !this.menuCollapsed
-    },
-    linksClick() {
-      this.toggleMenu()
+      this.showMenu = !this.showMenu
     }
   }
 }
@@ -208,4 +187,4 @@ export default {
     height: calc(100% - 80px);
   }
 }
-</style>
\ No newline at end of file
+</style>