mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-07-19 06:00:16 -04:00
feat: floating save button when editing recipe (#7320)
Co-authored-by: Docker User <user@example.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
<v-container v-show="!isCookMode" key="recipe-page" class="px-0" :class="{ 'pa-0': $vuetify.display.smAndDown }">
|
<v-container v-show="!isCookMode" key="recipe-page" class="px-0" :class="{ 'pa-0': $vuetify.display.smAndDown }">
|
||||||
<v-card flat class="d-print-none">
|
<v-card flat class="d-print-none">
|
||||||
<RecipePageHeader
|
<RecipePageHeader
|
||||||
|
ref="recipeToolbar"
|
||||||
:recipe="recipe"
|
:recipe="recipe"
|
||||||
:recipe-scale="scale"
|
:recipe-scale="scale"
|
||||||
:landscape="landscape"
|
:landscape="landscape"
|
||||||
@@ -112,6 +113,22 @@
|
|||||||
/>
|
/>
|
||||||
<RecipePrintContainer :recipe="recipe" :scale="scale" />
|
<RecipePrintContainer :recipe="recipe" :scale="scale" />
|
||||||
</v-container>
|
</v-container>
|
||||||
|
<!-- Floating save button when toolbar scrolls out of view -->
|
||||||
|
<v-fab
|
||||||
|
v-if="isEditMode && !toolbarVisible"
|
||||||
|
color="success"
|
||||||
|
location="bottom end"
|
||||||
|
size="large"
|
||||||
|
app
|
||||||
|
appear
|
||||||
|
class="d-print-none"
|
||||||
|
@click="saveRecipe"
|
||||||
|
>
|
||||||
|
<v-icon>{{ $globals.icons.save }}</v-icon>
|
||||||
|
<v-tooltip activator="parent" location="left">
|
||||||
|
{{ $t("general.save") }}
|
||||||
|
</v-tooltip>
|
||||||
|
</v-fab>
|
||||||
<!-- Cook mode displayes two columns with ingredients and instructions side by side, each being scrolled individually, allowing to view both at the same time -->
|
<!-- Cook mode displayes two columns with ingredients and instructions side by side, each being scrolled individually, allowing to view both at the same time -->
|
||||||
<!-- The calc is to account for the navabar height (48px) -->
|
<!-- The calc is to account for the navabar height (48px) -->
|
||||||
<v-sheet
|
<v-sheet
|
||||||
@@ -191,6 +208,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { ComponentPublicInstance } from "vue";
|
||||||
import { invoke, until } from "@vueuse/core";
|
import { invoke, until } from "@vueuse/core";
|
||||||
import type { RouteLocationNormalized } from "vue-router";
|
import type { RouteLocationNormalized } from "vue-router";
|
||||||
import RecipeIngredients from "../RecipeIngredients.vue";
|
import RecipeIngredients from "../RecipeIngredients.vue";
|
||||||
@@ -243,6 +261,26 @@ const notLinkedIngredients = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** =============================================================
|
||||||
|
* Floating save button — track toolbar visibility
|
||||||
|
*/
|
||||||
|
const recipeToolbar = ref<ComponentPublicInstance | null>(null);
|
||||||
|
const toolbarVisible = ref(true);
|
||||||
|
let toolbarObserver: IntersectionObserver | undefined;
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick();
|
||||||
|
const el = recipeToolbar.value?.$el as HTMLElement | undefined;
|
||||||
|
if (!el) return;
|
||||||
|
toolbarObserver = new IntersectionObserver(
|
||||||
|
([entry]) => { toolbarVisible.value = entry.isIntersecting; },
|
||||||
|
{ threshold: 0 },
|
||||||
|
);
|
||||||
|
toolbarObserver.observe(el);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => toolbarObserver?.disconnect());
|
||||||
|
|
||||||
/** =============================================================
|
/** =============================================================
|
||||||
* Recipe Snapshot on Mount
|
* Recipe Snapshot on Mount
|
||||||
* this is used to determine if the recipe has been changed since the last save
|
* this is used to determine if the recipe has been changed since the last save
|
||||||
|
|||||||
Reference in New Issue
Block a user