Forráskód Böngészése

Create general and reusable menu-tooltip component and use in selct-filter and menu-button components

sbkwgh 7 éve
szülő
commit
a9c151ac5c

+ 14 - 58
frontend/src/components/MenuButton.vue

@@ -1,10 +1,10 @@
 <template>
-	<div class='menu_button'>
-		<div class='menu_button__overlay' :class='{ "menu_button__overlay--show": show }' @click='setShow(false)'></div>
-		<div class='menu_button__icon' @click='setShow(true)'>
-			<slot ></slot>
+	<menu-tooltip v-model='menuOpen'>
+		<div class='menu_button__icon' @click='menuOpen = true' slot='button'>
+			<slot></slot>
 		</div>
-		<div class='menu_button__options' :class='{ "menu_button__options--show": show }'>
+
+		<template slot='menu'>
 			<div
 				class='menu_button__option'
 				v-for='(option, $index) in options'
@@ -13,26 +13,28 @@
 			>
 				{{option.value}}
 			</div>
-		</div>
-	</div>
+		</template>
+	</menu-tooltip>
 </template>
 
 <script>
+	import MenuTooltip from './MenuTooltip';
+
 	export default {
 		name: 'MenuButton',
 		props: ['options'],
+		components: {
+			MenuTooltip
+		},
 		data () {
 			return {
-				show: false
+				menuOpen: false
 			}
 		},
 		methods: {
-			setShow (val) {
-				this.show = val
-			},
 			emit (option) {
 				this.$emit(option)
-				this.setShow(false)
+				this.menuOpen = false;
 			}
 		}
 	}
@@ -42,48 +44,6 @@
 	@import '../assets/scss/variables.scss';
 
 	.menu_button {
-		position: relative;
-
-		@at-root #{&}__overlay {
-			position: fixed;
-			width: 100%;
-			height: 100%;
-			left: 0;
-			top: 0;
-			z-index: 2;
-			pointer-events: none;
-
-			@at-root #{&}--show {
-				pointer-events: all;
-			}
-		}
-
-		@at-root #{&}__options {
-			position: absolute;
-			background-color: #fff;
-			width: 10rem;
-			border-radius: 0.25rem;
-			overflow: hidden;
-			box-shadow: 0 3px 6px rgba(0, 0, 0, 0.03), 0 3px 6px rgba(0, 0, 0, 0.06);
-			z-index: 3;
-			border: 1px solid $color__gray--darker;
-			pointer-events: none;
-			transform: perspective( 600 ) rotateX( 15deg );
-			-webkit-transform: perspective( 600 ) rotateX( 15deg );
-			opacity: 0;
-			margin-top: -1rem;
-			transition: all 0.2s;
-			top: 0rem;
-			left: 0;
-
-			@at-root #{&}--show {
-				opacity: 1;
-				transform: perspective( 0 ) rotateX( 0 );
-				-webkit-transform: perspective( 0 ) rotateX( 0 );
-				margin-top: 0;
-				pointer-events: all;
-			}
-		}
 		@at-root #{&}__option {
 			padding: 0.5rem;
 			font-size: 0.9rem;
@@ -97,10 +57,6 @@
 
 	@media (max-width: 420px) {
 		.menu_button {
-			@at-root #{&}__options {
-				box-shadow: 0 3px 6px rgba(0, 0, 0, 0.06), 0 3px 6px rgba(0, 0, 0, 0.24);
-			}
-
 			@at-root #{&}__option {
 				padding: 0.75rem;
 				font-size: 1.125rem;

+ 78 - 0
frontend/src/components/MenuTooltip.vue

@@ -0,0 +1,78 @@
+<template>
+	<div class='menu_tooltip'>
+		<div
+			class='menu_tooltip__overlay'
+			:class='{ "menu_tooltip__overlay--show": value }'
+			@click='$emit("input", false)'
+		></div>
+
+		<slot name='button'></slot>
+
+		<div
+			class='menu_tooltip__menu'
+			:class='{ "menu_tooltip__menu--show": value }'
+		>
+			<div class='menu_tooltip__menu__inner'>
+				<slot name='menu'></slot>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	export default {
+		name: 'MenuTooltip',
+		props: ['value']
+	}
+</script>
+
+<style lang='scss' scoped>
+	@import '../assets/scss/variables.scss';
+
+	.menu_tooltip {
+		display: inline-block;
+
+		@at-root #{&}__overlay {
+			height: 100%;
+			left: 0;
+			pointer-events: none;
+			position: fixed;
+			top: 0;
+			width: 100%;
+			z-index: 2;
+
+			@at-root #{&}--show {
+				pointer-events: all;
+			}
+		}
+
+		@at-root #{&}__menu {
+			background-color: #fff;
+			border: 1.5px solid $color__gray--darker;
+			border-radius: 0.25rem;
+			box-shadow: 0 0.25rem 1rem rgba(#000, 0.125);
+			max-height: 10rem;
+			opacity: 0;
+			overflow-y: hidden;
+			position: absolute;
+			pointer-events: none;
+			transform: translateY(-0.25rem);
+			transition: transform 0.2s, opacity 0.2s;
+			width: 15rem;
+			z-index: 3;
+
+			@at-root #{&}--show {
+				opacity: 1;
+				pointer-events: all;
+				transform: translateY(0.125rem);
+			}
+
+			@at-root #{&}__inner {
+				max-height: 10rem;
+				overflow-y: auto;
+				padding: 0.25rem;
+
+			}
+		}
+	}
+</style>

+ 29 - 79
frontend/src/components/SelectFilter.vue

@@ -1,56 +1,51 @@
 <template>
-	<div class='select_filter'>
-		<div
-			class='select_filter__overlay'
-			:class='{ "select_filter__overlay--show": menuOpen }'
-			@click='menuOpen = false'
-		></div>
-
+	<menu-tooltip v-model='menuOpen'>
 		<button
+			slot='button'
 			class='button select_filter__button'
 			:class='{ "select_filter__button--selected": menuOpen }'
-			@click='menuOpen = !menuOpen'
+			@click='menuOpen = true'
 		>
 			{{name}}
 			<span class='fa fa-chevron-down'></span>
 		</button>
 
-		<div
-			class='select_filter__menu'
-			:class='{ "select_filter__menu--show": menuOpen }'
-		>
-			<div class='select_filter__menu__inner'>
+		<template slot='menu'>
+			<div
+				class='select_filter__item select_filter__item--select_all'
+				@click='toggleSelectAll'
+			>
 				<div
-					class='select_filter__item select_filter__item--select_all'
-					@click='toggleSelectAll'
-				>
-					<div
-						class='select_filter__checkbox'
-						:class='{ "select_filter__checkbox--selected": selected.length === options.length }'
-					></div>
-					<span>Select all</span>
-				</div>
+					class='select_filter__checkbox'
+					:class='{ "select_filter__checkbox--selected": selected.length === options.length }'
+				></div>
+				<span>Select all</span>
+			</div>
 
+			<div
+				class='select_filter__item'
+				v-for='(item, $index) in options'
+				@click='toggledSelectItem($index)'
+			>
 				<div
-					class='select_filter__item'
-					v-for='(item, $index) in options'
-					@click='toggledSelectItem($index)'
-				>
-					<div
-						class='select_filter__checkbox'
-						:class='{ "select_filter__checkbox--selected": selected.includes($index) }'
-					></div>
-					<span>{{item.name}}</span>
-				</div>
+					class='select_filter__checkbox'
+					:class='{ "select_filter__checkbox--selected": selected.includes($index) }'
+				></div>
+				<span>{{item.name}}</span>
 			</div>
-		</div>
-	</div>
+		</template>
+	</menu-tooltip>
 </template>
 
 <script>
+	import MenuTooltip from './MenuTooltip';
+
 	export default {
 		name: 'SelectFilter',
 		props: ['name', 'options', 'value'],
+		components: {
+			MenuTooltip
+		},
 		data () {
 			return {
 				menuOpen: false,
@@ -95,22 +90,6 @@
 	@import '../assets/scss/variables.scss';
 
 	.select_filter {
-		display: inline-block;
-
-		@at-root #{&}__overlay {
-			height: 100%;
-			left: 0;
-			pointer-events: none;
-			position: fixed;
-			top: 0;
-			width: 100%;
-			z-index: 2;
-
-			@at-root #{&}--show {
-				pointer-events: all;
-			}
-		}
-
 		@at-root #{&}__button {
 			border-radius: 0.25rem;
 			cursor: pointer;
@@ -136,35 +115,6 @@
 			}
 		}
 
-		@at-root #{&}__menu {
-			background-color: #fff;
-			border: 1.5px solid $color__gray--darker;
-			border-radius: 0.25rem;
-			box-shadow: 0 0.25rem 1rem rgba(#000, 0.125);
-			max-height: 10rem;
-			opacity: 0;
-			overflow-y: hidden;
-			position: absolute;
-			pointer-events: none;
-			transform: translateY(-0.25rem);
-			transition: transform 0.2s, opacity 0.2s;
-			width: 15rem;
-			z-index: 3;
-
-			@at-root #{&}--show {
-				opacity: 1;
-				pointer-events: all;
-				transform: translateY(0.125rem);
-			}
-
-			@at-root #{&}__inner {
-				max-height: 10rem;
-				overflow-y: auto;
-				padding: 0.25rem;
-
-			}
-		}
-
 		@at-root #{&}__item {
 			align-items: center;
 			background-color: #fff;