Provide a globally injected isMobile state for reactivity

This commit is contained in:
Johannes Zellner
2025-12-17 16:44:01 +01:00
parent 16e79c6546
commit b90cdb8686
2 changed files with 23 additions and 9 deletions

View File

@@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
const i18n = useI18n();
const t = i18n.t;
import { onMounted, ref, useTemplateRef, provide } from 'vue';
import { onMounted, onUnmounted, ref, useTemplateRef, provide } from 'vue';
import { Notification, fetcher } from '@cloudron/pankow';
import { setLanguage } from './i18n.js';
import { API_ORIGIN, TOKEN_TYPES } from './constants.js';
@@ -393,14 +393,22 @@ async function onOnline() {
await refreshConfigAndFeatures(); // reload dashboard if needed after an update
}
const isMobile = ref(window.innerWidth <= 576);
function checkForMobile() {
isMobile.value = window.innerWidth <= 576;
}
provide('subscriptionRequiredDialog', subscriptionRequiredDialog);
provide('features', features);
provide('profile', profile);
provide('refreshProfile', refreshProfile);
provide('refreshFeatures', refreshConfigAndFeatures);
provide('dashboardDomain', dashboardDomain);
provide('isMobile', isMobile);
onMounted(async () => {
window.addEventListener('resize', checkForMobile);
const [error, result] = await provisionModel.status();
if (error) return window.cloudron.onError(error);
@@ -434,6 +442,10 @@ onMounted(async () => {
ready.value = true;
});
onUnmounted(() => {
window.removeEventListener('resize', checkForMobile);
});
</script>
<template>

View File

@@ -1,8 +1,10 @@
<script setup>
import { ref, computed, useTemplateRef, watch } from 'vue';
import { ref, computed, useTemplateRef, watch, inject } from 'vue';
import SideBarItem from './SideBarItem.vue';
const isMobile = inject('isMobile');
const emit = defineEmits(['close']);
const props = defineProps({
@@ -37,11 +39,11 @@ const props = defineProps({
}
});
const isExpanded = ref(false);
const isMenuExpanded = ref(false);
const isMenuOpen = ref(false);
watch(() => props.collapsed, () => {
isExpanded.value = false;
isMenuExpanded.value = false;
isMenuOpen.value = false;
});
@@ -100,7 +102,7 @@ function getHiddenElementSize(element) {
const subMenuFlipped = ref(false);
function toggleMenu() {
if (props.collapsed && window.innerWidth >= 576) {
if (props.collapsed && !isMobile.value) {
const size = getHiddenElementSize(subMenuElement.value);
const viewport = getViewport();
@@ -124,7 +126,7 @@ function toggleMenu() {
isMenuOpen.value = true;
} else {
isExpanded.value = !isExpanded.value;
isMenuExpanded.value = !isMenuExpanded.value;
}
}
@@ -138,8 +140,8 @@ function onBackdrop(event) {
<template>
<div v-if="isVisible">
<hr v-if="separator"/>
<a v-else-if="!childItems?.length" class="sidebar-item" :class="{ active: isActive }" :href="route" @click="close()" v-tooltip.right="collapsed ? label : null"><i :class="icon"></i> <span :class="{ 'sidebar-item-label-collapsed': collapsed }">{{ label }}</span></a>
<div v-else-if="childItems.length" ref="elem" class="sidebar-item" :class="{ 'sidebar-item-menu-open': isMenuOpen ? '#e9ecef' : null }" @click="toggleMenu()" v-tooltip.right="collapsed ? label : null"><i :class="icon"></i> <span :class="{ 'sidebar-item-label-collapsed': collapsed }">{{ label }} <i class="collapse fa-solid fa-angle-right" :class="{ expanded: isExpanded }" style="margin-left: 6px;"></i></span></div>
<a v-else-if="!childItems?.length" class="sidebar-item" :class="{ active: isActive }" :href="route" @click="close()" v-tooltip.right="collapsed && !isMobile ? label : null"><i :class="icon"></i> <span :class="{ 'sidebar-item-label-collapsed': collapsed }">{{ label }}</span></a>
<div v-else-if="childItems.length" ref="elem" class="sidebar-item" :class="{ 'sidebar-item-menu-open': isMenuOpen ? '#e9ecef' : null }" @click="toggleMenu()" v-tooltip.right="collapsed && !isMobile ? label : null"><i :class="icon"></i> <span :class="{ 'sidebar-item-label-collapsed': collapsed }">{{ label }} <i class="collapse fa-solid fa-angle-right" :class="{ expanded: isMenuExpanded }" style="margin-left: 6px;"></i></span></div>
<teleport to="#app">
<div class="pankow-menu-backdrop" @click="onBackdrop($event)" @contextmenu="onBackdrop($event)" v-show="isMenuOpen"></div>
@@ -155,7 +157,7 @@ function onBackdrop(event) {
</teleport>
<Transition name="sidebar-item-group-animation">
<div class="sidebar-item-group" v-if="isExpanded">
<div class="sidebar-item-group" v-if="isMenuExpanded">
<SideBarItem v-for="item in childItems" :key="item"
:label="item.label"
:icon="item.icon"