浏览代码

Adding header bar with menu

Completely new menu, no known functional bugs.
Not perfect yet, TODO: there should be a way to keep the style of both files separated from each other. The Menu links should expand to the full width by them self.
Ecconia 7 年之前
父节点
当前提交
c2a2efac89
共有 2 个文件被更改,包括 196 次插入0 次删除
  1. 59 0
      src/App.vue
  2. 137 0
      src/components/MenuContainer.vue

+ 59 - 0
src/App.vue

@@ -1,5 +1,22 @@
 <template>
 	<div id="app">
+		<header>
+			<div class="logo">
+				<span>RedstoneServer</span>
+			</div>
+
+			<MenuContainer class="menu-container">
+				<router-link class="top-link" :to="link" v-for="(link, text) in menu_entries" :key="link">{{ text }}</router-link>
+			</MenuContainer>
+
+			<div class="user">
+				<div v-if="user">
+					<span>Username: {{ user.username }}</span>
+				</div>
+				<span v-else>Login</span>
+			</div>
+		</header>
+
 		<p>Website under development, please excuse ugly style and broken/missing features as well as missing legal things.</p>
 		<div class="content">
 			<router-view/>
@@ -8,6 +25,27 @@
 	</div>
 </template>
 
+<script>
+	import MenuContainer from './components/MenuContainer.vue'
+
+	export default {
+		data () {
+			return {
+				user: null,
+				menu_entries: {
+					'Startpage': '/',
+					'Applications': '/applications',
+					'Development Blog': '/devblog',
+				}
+			}
+		},
+
+		components: {
+			MenuContainer
+		},
+	}
+</script>
+
 <style>
 	body {
 		font-family: sans-serif;
@@ -26,6 +64,27 @@
 </style>
 
 <style scoped>
+	header {
+		font-size: 1.5em;
+		color: #aaa;
+		background-color: #222;
+		display: flex;
+	}
+
+	header .logo {
+		display: inline-block;
+		padding: 0.2em 1em;
+	}
+
+	header .menu-container {
+		flex-grow: 100;
+		box-sizing: border-box;
+	}
+
+	header .user {
+		padding: 0.2em 1em;
+	}
+
 	.content {
 		margin-left: 8px;
 		margin-right: 8px;

+ 137 - 0
src/components/MenuContainer.vue

@@ -0,0 +1,137 @@
+<template>
+	<div ref="whole">
+		<div class="topbar" ref="topbar">
+			<slot class="top-link"></slot>
+		</div>
+		<span class="arrow">
+			<span class="top-link" ref="dropdownbutton">vv</span>
+			<div class="dropdown" ref="dropdown" />
+		</span>
+	</div>
+</template>
+
+<script>
+	export default {
+		methods: {
+			onResize() {
+				this.update()
+			},
+
+			update() {
+				let topbar = this.$refs.topbar
+				let dropdown = this.$refs.dropdown
+				
+				let dropDownButton = this.$refs.dropdownbutton
+				dropDownButton.classList.remove('alone', 'full')
+				let dropdownWidth = dropDownButton.offsetWidth
+				
+				let topbarElements = Array.from(topbar.childNodes)
+				let dropboxElements = Array.from(dropdown.childNodes)
+				for(let el of dropboxElements) {
+					dropdown.removeChild(el)
+					topbar.appendChild(el)
+				}
+
+				let childAndSize = []
+				for(let child of topbarElements.concat(dropboxElements)) {
+					childAndSize.push([child.offsetWidth, child])
+				}
+
+				topbar.innerHTML = ''
+				let width = this.$refs.whole.clientWidth - dropdownWidth - 50
+				let tmp = 0
+				for(let child of childAndSize) {
+					tmp += child[0]
+
+					if(width > tmp) {
+						topbar.appendChild(child[1])
+					} else {
+						dropdown.appendChild(child[1])
+					}
+				}
+
+				if(dropdown.childNodes.length === 0) {
+					dropDownButton.classList.add('full')
+				} else if(topbar.childNodes.length === 0) {
+					dropDownButton.classList.add('alone')
+				}
+			}
+		},
+
+		mounted() {
+			window.addEventListener('resize', this.onResize)
+			//Initial menu sorting
+			this.update()			
+		},
+
+		beforeDestroy() {
+			//TBI never will be closed...!
+			window.removeEventListener('resize', this.onResize)
+		}
+	}
+</script>
+
+<style scoped>
+	.whole {
+		box-sizing: border-box;
+	}
+
+	.topbar > .top-link:first-child {
+		border: none;
+	}
+	.top-link {
+		box-sizing: border-box;
+		white-space: nowrap;
+		display: inline-block;
+		padding: 0.2em 0.3em 0.2em 0.3em;
+		border-left: solid 1px #aaa;
+
+		color: #aaa;
+		text-decoration: none;
+	}
+
+	.alone {
+		border-left: none;
+	}
+
+	.full {
+		display: none;
+	}
+
+	.topbar {
+		box-sizing: border-box;
+		display: inline-block;
+	}
+	.arrow {
+		position: relative;
+	}
+
+	.dropdown {
+		display: none;
+		position: absolute;
+		
+		z-index: 1;
+
+		min-width: 100%;
+		top: 1.3em;
+		left: 50%;
+		transform: translateX(-50%);
+	}
+
+	.dropdown .top-link {
+		border: none;
+		border-top: 1px solid #aaa;
+		display: block;
+		position: relative;
+		background-color: #222;
+	}
+
+	.arrow:hover .dropdown {
+		display: inline-block;
+	}
+
+	.top-link:hover {
+		background-color: #333;
+		color: #ddd;
+	}
+</style>