feat: add see menu btn
This commit is contained in:
11
src/components.d.ts
vendored
11
src/components.d.ts
vendored
@@ -8,15 +8,16 @@ declare module '@vue/runtime-core' {
|
|||||||
BaseFooter: typeof import('./components/BaseFooter.vue')['default']
|
BaseFooter: typeof import('./components/BaseFooter.vue')['default']
|
||||||
ChooseFood: typeof import('./components/ChooseFood.vue')['default']
|
ChooseFood: typeof import('./components/ChooseFood.vue')['default']
|
||||||
Counter: typeof import('./components/Counter.vue')['default']
|
Counter: typeof import('./components/Counter.vue')['default']
|
||||||
DishTag: typeof import('./components/DishTag.vue')['default']
|
DishTag: typeof import('./components/tags/DishTag.vue')['default']
|
||||||
MeatTag: typeof import('./components/MeatTag.vue')['default']
|
MeatTag: typeof import('./components/tags/MeatTag.vue')['default']
|
||||||
Menu: typeof import('./components/Menu.vue')['default']
|
Menu: typeof import('./components/Menu.vue')['default']
|
||||||
README: typeof import('./components/README.md')['default']
|
README: typeof import('./components/README.md')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
StapleTag: typeof import('./components/StapleTag.vue')['default']
|
StapleTag: typeof import('./components/tags/StapleTag.vue')['default']
|
||||||
ToolTag: typeof import('./components/ToolTag.vue')['default']
|
Switch: typeof import('./components/Switch.vue')['default']
|
||||||
VegetableTag: typeof import('./components/VegetableTag.vue')['default']
|
ToolTag: typeof import('./components/tags/ToolTag.vue')['default']
|
||||||
|
VegetableTag: typeof import('./components/tags/VegetableTag.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useGtm } from '@gtm-support/vue-gtm'
|
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 type { StuffItem } from '~/data/food'
|
||||||
import { meat, staple, tools, vegetable } from '~/data/food'
|
import { meat, staple, tools, vegetable } from '~/data/food'
|
||||||
import recipeData from '~/data/recipe.json'
|
import recipeData from '~/data/recipe.json'
|
||||||
import type { Recipe } from '~/types'
|
import type { Recipe } from '~/types'
|
||||||
import { useRecipeStore } from '~/stores/recipe'
|
import { useRecipeStore } from '~/stores/recipe'
|
||||||
|
|
||||||
|
import { useInvisibleElement } from '~/composables/helper'
|
||||||
|
|
||||||
const recipe = ref<Recipe>(recipeData as Recipe)
|
const recipe = ref<Recipe>(recipeData as Recipe)
|
||||||
|
|
||||||
const rStore = useRecipeStore()
|
const rStore = useRecipeStore()
|
||||||
@@ -61,9 +60,25 @@ const clickTool = (item: StuffItem) => {
|
|||||||
label: '工具',
|
label: '工具',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const recipePanel = ref()
|
||||||
|
const { isVisible, show } = useInvisibleElement(recipePanel)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 m="t-4" text="xl" font="bold" p="1">
|
||||||
🥘 先选一下食材
|
🥘 先选一下食材
|
||||||
</h2>
|
</h2>
|
||||||
@@ -142,20 +157,7 @@ const clickTool = (item: StuffItem) => {
|
|||||||
</ToolTag>
|
</ToolTag>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="inline-flex justify-center items-center" m="y-4">
|
<div ref="recipePanel" m="2 t-4" p="2" class="transition shadow hover:shadow-md" bg="gray-400/8">
|
||||||
<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">
|
|
||||||
<h2 text="xl" font="bold" p="1">
|
<h2 text="xl" font="bold" p="1">
|
||||||
🍲 来看看组合出的菜谱吧!
|
🍲 来看看组合出的菜谱吧!
|
||||||
</h2>
|
</h2>
|
||||||
@@ -184,63 +186,3 @@ const clickTool = (item: StuffItem) => {
|
|||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</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
81
src/components/Switch.vue
Normal 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
27
src/composables/helper.ts
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import { acceptHMRUpdate, defineStore } from 'pinia'
|
import { acceptHMRUpdate, defineStore } from 'pinia'
|
||||||
|
|
||||||
export const useRecipeStore = defineStore('recipe', () => {
|
export const useRecipeStore = defineStore('recipe', () => {
|
||||||
|
const strict = ref(true)
|
||||||
|
|
||||||
const curStuff = ref(new Set<string>())
|
const curStuff = ref(new Set<string>())
|
||||||
const curTools = ref(new Set<string>())
|
const curTools = ref(new Set<string>())
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ export const useRecipeStore = defineStore('recipe', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
strict,
|
||||||
selectedTools,
|
selectedTools,
|
||||||
selectedStuff,
|
selectedStuff,
|
||||||
toggleStuff,
|
toggleStuff,
|
||||||
|
|||||||
Reference in New Issue
Block a user