feat: add see menu btn

This commit is contained in:
YunYouJun
2022-04-17 01:42:52 +08:00
parent 439f9a080d
commit 7163fd350b
10 changed files with 136 additions and 82 deletions

11
src/components.d.ts vendored
View File

@@ -8,15 +8,16 @@ declare module '@vue/runtime-core' {
BaseFooter: typeof import('./components/BaseFooter.vue')['default']
ChooseFood: typeof import('./components/ChooseFood.vue')['default']
Counter: typeof import('./components/Counter.vue')['default']
DishTag: typeof import('./components/DishTag.vue')['default']
MeatTag: typeof import('./components/MeatTag.vue')['default']
DishTag: typeof import('./components/tags/DishTag.vue')['default']
MeatTag: typeof import('./components/tags/MeatTag.vue')['default']
Menu: typeof import('./components/Menu.vue')['default']
README: typeof import('./components/README.md')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
StapleTag: typeof import('./components/StapleTag.vue')['default']
ToolTag: typeof import('./components/ToolTag.vue')['default']
VegetableTag: typeof import('./components/VegetableTag.vue')['default']
StapleTag: typeof import('./components/tags/StapleTag.vue')['default']
Switch: typeof import('./components/Switch.vue')['default']
ToolTag: typeof import('./components/tags/ToolTag.vue')['default']
VegetableTag: typeof import('./components/tags/VegetableTag.vue')['default']
}
}

View File

@@ -1,14 +1,13 @@
<script lang="ts" setup>
import { useGtm } from '@gtm-support/vue-gtm'
import MeatTag from './MeatTag.vue'
import StapleTag from './StapleTag.vue'
import DishTag from './DishTag.vue'
import type { StuffItem } from '~/data/food'
import { meat, staple, tools, vegetable } from '~/data/food'
import recipeData from '~/data/recipe.json'
import type { Recipe } from '~/types'
import { useRecipeStore } from '~/stores/recipe'
import { useInvisibleElement } from '~/composables/helper'
const recipe = ref<Recipe>(recipeData as Recipe)
const rStore = useRecipeStore()
@@ -61,9 +60,25 @@ const clickTool = (item: StuffItem) => {
label: '工具',
})
}
const recipePanel = ref()
const { isVisible, show } = useInvisibleElement(recipePanel)
</script>
<template>
<Transition>
<button
v-if="displayedRecipe.length !== recipe.length && displayedRecipe.length && !isVisible"
class="fixed inline-flex justify-center items-center rounded rounded-full shadow hover:shadow-md"
bg="green-50" w="10" h="10" bottom="4" right="4"
text="green-600"
@click="show"
>
<!-- <div i-mdi-bowl-mix-outline /> -->
🍲
</button>
</Transition>
<h2 m="t-4" text="xl" font="bold" p="1">
🥘 先选一下食材
</h2>
@@ -142,20 +157,7 @@ const clickTool = (item: StuffItem) => {
</ToolTag>
</div>
<!-- <div class="inline-flex justify-center items-center" m="y-4">
<span :class="!strict && 'text-green-600'" font="bold" m="x-1" @click="strict = false">
可做的所有菜
</span>
<label m="x-1" class="switch">
<input v-model="strict" type="checkbox">
<span class="inline-flex justify-center items-center slider round" />
</label>
<span :class="strict && 'text-green-600'" font="bold" m="x-1" @click="strict = true">
一起做一道菜
</span>
</div> -->
<div m="2 t-4" p="2" class="transition shadow hover:shadow-md" bg="gray-400/8">
<div ref="recipePanel" m="2 t-4" p="2" class="transition shadow hover:shadow-md" bg="gray-400/8">
<h2 text="xl" font="bold" p="1">
🍲 来看看组合出的菜谱吧
</h2>
@@ -184,63 +186,3 @@ const clickTool = (item: StuffItem) => {
</Transition>
</div>
</template>
<style lang="scss">
.switch {
position: relative;
display: inline-block;
width: 48px;
height: 28px;
input {
opacity: 0;
width: 0;
height: 0;
}
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(122,122,122,0.3);
-webkit-transition: .4s;
transition: .4s;
}
$size: 20px;
.slider:before {
position: absolute;
content: "";
height: $size;
width: $size;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
@apply bg-green-600;
}
input:checked + .slider:before {
-webkit-transform: translateX($size);
-ms-transform: translateX($size);
transform: translateX($size);
}
/* Rounded sliders */
.slider.round {
border-radius: 28px;
&:before {
border-radius: 50%;
}
}
</style>

81
src/components/Switch.vue Normal file
View File

@@ -0,0 +1,81 @@
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { useRecipeStore } from '~/stores/recipe'
const rStore = useRecipeStore()
const { strict } = storeToRefs(rStore)
</script>
<template>
<div class="inline-flex justify-center items-center" m="y-4">
<span :class="!strict && 'text-green-600'" font="bold" m="x-1" @click="strict = false">
可做的所有菜
</span>
<label m="x-1" class="switch">
<input v-model="strict" type="checkbox">
<span class="inline-flex justify-center items-center slider round" />
</label>
<span :class="strict && 'text-green-600'" font="bold" m="x-1" @click="strict = true">
一起做一道菜
</span>
</div>
</template>
<style lang="scss">
.switch {
position: relative;
display: inline-block;
width: 48px;
height: 28px;
input {
opacity: 0;
width: 0;
height: 0;
}
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(122,122,122,0.3);
-webkit-transition: .4s;
transition: .4s;
}
$size: 20px;
.slider:before {
position: absolute;
content: "";
height: $size;
width: $size;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
@apply bg-green-600;
}
input:checked + .slider:before {
-webkit-transform: translateX($size);
-ms-transform: translateX($size);
transform: translateX($size);
}
/* Rounded sliders */
.slider.round {
border-radius: 28px;
&:before {
border-radius: 50%;
}
}
</style>

27
src/composables/helper.ts Normal file
View File

@@ -0,0 +1,27 @@
import { useElementBounding, useIntersectionObserver } from '@vueuse/core'
import type { Ref } from 'vue'
import { ref } from 'vue'
/**
* trigger show invisible element
* @param target
* @returns
*/
export function useInvisibleElement(target: Ref<HTMLElement>) {
const isVisible = ref(false)
const { top } = useElementBounding(target)
useIntersectionObserver(target, ([{ isIntersecting }]) => {
isVisible.value = isIntersecting
})
const show = () => {
// scroll when collapse is not visible
if (!isVisible.value)
window.scrollTo(0, top.value)
}
return {
isVisible,
show,
}
}

View File

@@ -1,6 +1,8 @@
import { acceptHMRUpdate, defineStore } from 'pinia'
export const useRecipeStore = defineStore('recipe', () => {
const strict = ref(true)
const curStuff = ref(new Set<string>())
const curTools = ref(new Set<string>())
@@ -34,6 +36,7 @@ export const useRecipeStore = defineStore('recipe', () => {
}
return {
strict,
selectedTools,
selectedStuff,
toggleStuff,