Tabs redesigned, update url and can show counter.
Tabs have been redesigned and can now display a counter. This counter
can be set by emiting a "counter" event from the child.
Tabs read and set a ?tab={slug} query parameter when changing tab, when
loaded we check for this parameter to automatically select the correct
tab.
			
			
This commit is contained in:
		| @@ -1,51 +1,80 @@ | |||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|     <div class="tab-container"> |     <nav class="tab-container"> | ||||||
|       <div |       <a | ||||||
|         class="tab" |         class="tab" | ||||||
|         v-for="(tab, index) in tabs" |         v-for="(tab, index) in tabs" | ||||||
|         :key="index" |         :key="index" | ||||||
|         @click="changeTab(index)" |         @click="changeTab(index)" | ||||||
|  |         @keydown.enter="changeTab(index)" | ||||||
|  |         tabindex="0" | ||||||
|         :class="chosenTab == index ? 'active' : null" |         :class="chosenTab == index ? 'active' : null" | ||||||
|       >{{ tab.name }}</div> |       > | ||||||
|     </div> |         {{ tab.name }} | ||||||
|  |  | ||||||
|  |         <span v-if="tab.counter" class="counter">{{ tab.counter }}</span> | ||||||
|  |       </a> | ||||||
|  |     </nav> | ||||||
|  |  | ||||||
|     <div class="tab-elements"> |     <div class="tab-elements"> | ||||||
|       <component :is="tabs[chosenTab].component" /> |       <component :is="tabs[chosenTab].component" @counter="updateCounter" /> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import eventBus from "@/mixins/EventBus"; |  | ||||||
| export default { | export default { | ||||||
|   props: { |   props: { | ||||||
|     tabs: { |     tabs: { | ||||||
|       type: Array |       type: Array | ||||||
|     }, |  | ||||||
|     active: { |  | ||||||
|       type: Number, |  | ||||||
|       default: 0 |  | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   beforeMount() { |   beforeMount() { | ||||||
|     this.chosenTab = this.active; |     const url = location.href; | ||||||
|  |  | ||||||
|  |     if (url.includes("tab=")) { | ||||||
|  |       const tabParameter = url.split("tab=")[1]; | ||||||
|  |       const matchingSlug = this.tabs.findIndex(tab => tab.slug == tabParameter); | ||||||
|  |       console.log("matchingSlug:", matchingSlug); | ||||||
|  |       this.chosenTab = matchingSlug; | ||||||
|  |     } | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       chosenTab: 0 |       chosenTab: 0 | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|  |   computed: { | ||||||
|  |     activeTab() { | ||||||
|  |       return this.tabs[this.chosenTab]; | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     changeTab: function(num) { |     changeTab(num) { | ||||||
|       this.chosenTab = num; |       this.chosenTab = num; | ||||||
|       this.$emit("tabChange", num); |  | ||||||
|       eventBus.$emit("tab-change"); |       let url = location.href; | ||||||
|  |       const tabParameterIndex = url.indexOf("tab="); | ||||||
|  |  | ||||||
|  |       if (tabParameterIndex > 0) { | ||||||
|  |         url = url.split("tab=")[0] + `tab=${this.activeTab.slug}`; | ||||||
|  |       } else { | ||||||
|  |         url = url + `?tab=${this.activeTab.slug}`; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       window.history.pushState({}, "", url); | ||||||
|  |     }, | ||||||
|  |     updateCounter(val) { | ||||||
|  |       this.activeTab.counter = val; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
|  | @import "@/styles/variables.scss"; | ||||||
|  | @import "@/styles/media-queries.scss"; | ||||||
|  |  | ||||||
| h1 { | h1 { | ||||||
|   text-align: center; |   text-align: center; | ||||||
| } | } | ||||||
| @@ -54,28 +83,50 @@ h1 { | |||||||
|   display: flex; |   display: flex; | ||||||
|   flex-direction: row; |   flex-direction: row; | ||||||
|   justify-content: center; |   justify-content: center; | ||||||
|   margin-top: 25px; |   // margin-top: 25px; | ||||||
|   border-bottom: 1px solid #333333; |   border-bottom: 1px solid var(--underlinenav-text); | ||||||
|  |  | ||||||
|  |   margin-top: 2rem; | ||||||
|  |  | ||||||
|  |   @include mobile { | ||||||
|  |     flex-direction: column; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| .tab { | .tab { | ||||||
|   cursor: pointer; |   cursor: pointer; | ||||||
|   font-size: 1.2rem; |   font-size: 1.1rem; | ||||||
|   display: flex; |   padding: 8px 16px; | ||||||
|   justify-content: center; |   border-bottom: 2px solid transparent; | ||||||
|   align-items: center; |   color: rgba($matte-text-color, 0.9); | ||||||
|   padding: 20px; |  | ||||||
|   margin: 0 15px; |  | ||||||
|   border: 1px solid #333333; |  | ||||||
|   border-top-left-radius: 5px; |  | ||||||
|   border-top-right-radius: 5px; |  | ||||||
|   background: #00000008; |  | ||||||
|   border-bottom: 1px solid #333333; |  | ||||||
|   margin-bottom: -1px; |  | ||||||
|  |  | ||||||
|   &.active { |   &.active { | ||||||
|     border-bottom: 1px solid white; |     color: $matte-text-color; | ||||||
|  |     border-color: var(--underlinenav-text-active) !important; | ||||||
|     background: white; |     background: white; | ||||||
|  |     font-weight: 600; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   &:hover, | ||||||
|  |   &:focus { | ||||||
|  |     border-color: var(--underlinenav-text-hover); | ||||||
|  |     outline: 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   & .counter { | ||||||
|  |     margin-left: 4px; | ||||||
|  |     box-sizing: border-box; | ||||||
|  |  | ||||||
|  |     display: inline-block; | ||||||
|  |     min-width: 20px; | ||||||
|  |     padding: 0 6px; | ||||||
|  |     font-size: 14px; | ||||||
|  |     font-weight: 600; | ||||||
|  |     line-height: 18px; | ||||||
|  |     text-align: center; | ||||||
|  |     background-color: rgba(209, 213, 218, 0.5); | ||||||
|  |     border: 1px solid transparent; | ||||||
|  |     border-radius: 2em; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user