feat(search): add keyboard hide button and auto-hide Dock

- Add floating keyboard hide button that appears on search input focus
- Create KeyboardStore to manage keyboard state globally
- Auto-hide Dock component when keyboard is open on search page
- Position keyboard hide button at bottom when Dock is hidden
- Update keyboard state on focus, blur, and hide actions
This commit is contained in:
2025-12-01 22:37:30 +03:00
parent 17ff888c05
commit db8d1360fc
3 changed files with 32 additions and 2 deletions

View File

@@ -42,6 +42,7 @@ import {FullscreenViewport, useMiniApp, useWebAppViewport} from 'vue-tg';
import {useRoute, useRouter} from "vue-router";
import {useSettingsStore} from "@/stores/SettingsStore.js";
import {useProductFiltersStore} from "@/stores/ProductFiltersStore.js";
import {useKeyboardStore} from "@/stores/KeyboardStore.js";
import CartButton from "@/components/CartButton.vue";
import Dock from "@/components/Dock.vue";
import AppDebugMessage from "@/components/AppDebugMessage.vue";
@@ -58,6 +59,7 @@ const router = useRouter();
const route = useRoute();
const settings = useSettingsStore();
const filtersStore = useProductFiltersStore();
const keyboardStore = useKeyboardStore();
const backButton = window.Telegram.WebApp.BackButton;
const haptic = window.Telegram.WebApp.HapticFeedback;
const drawerOpen = ref(false);
@@ -70,7 +72,14 @@ const routesToHideAppDock = [
];
const isAppDockShown = computed(() => {
return routesToHideAppDock.indexOf(route.name) === -1;
if (routesToHideAppDock.indexOf(route.name) === -1) {
// Скрываем Dock, если клавиатура открыта на странице поиска
if (route.name === 'search' && keyboardStore.isOpen) {
return false;
}
return true;
}
return false;
});
function navigateBack() {

View File

@@ -0,0 +1,15 @@
import {defineStore} from "pinia";
import {ref} from "vue";
export const useKeyboardStore = defineStore('keyboard', {
state: () => ({
isOpen: false,
}),
actions: {
setOpen(value) {
this.isOpen = value;
},
},
});

View File

@@ -108,7 +108,7 @@
<button
v-if="showHideKeyboardButton"
@click="handleHideKeyboardClick"
class="btn btn-circle btn-primary fixed bottom-20 right-4 z-50 shadow-lg"
class="btn btn-circle btn-primary fixed bottom-4 right-4 z-50 shadow-lg"
type="button"
aria-label="Скрыть клавиатуру"
>
@@ -124,6 +124,7 @@ import {useSearchStore} from "@/stores/SearchStore.js";
import {useDebounceFn} from "@vueuse/core";
import {computed, onMounted, ref} from "vue";
import {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
import {useKeyboardStore} from "@/stores/KeyboardStore.js";
import {useRoute} from "vue-router";
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
import BaseViewWrapper from "@/views/BaseViewWrapper.vue";
@@ -133,6 +134,7 @@ import {renderSmartNumber} from "../helpers.js";
const route = useRoute();
const yaMetrika = useYaMetrikaStore();
const searchStore = useSearchStore();
const keyboardStore = useKeyboardStore();
const searchInput = ref(null);
const debouncedSearch = useDebounceFn(() => searchStore.performSearch(), 800);
@@ -156,24 +158,28 @@ const handleEnter = (event) => {
const handleSearch = () => {
hideKeyboard();
showHideKeyboardButton.value = false;
keyboardStore.setOpen(false);
};
const showHideKeyboardButton = ref(false);
const handleFocus = () => {
showHideKeyboardButton.value = true;
keyboardStore.setOpen(true);
};
const handleBlur = () => {
// Не скрываем сразу, даем время на клик по кнопке
setTimeout(() => {
showHideKeyboardButton.value = false;
keyboardStore.setOpen(false);
}, 200);
};
const handleHideKeyboardClick = () => {
hideKeyboard();
showHideKeyboardButton.value = false;
keyboardStore.setOpen(false);
if (searchInput.value) {
searchInput.value.blur();
}