trypost/resources/js/layouts/app/AppSidebarLayout.vue
Paulo Castellano fd557fe559 fix(ui): align the mobile sidebar trigger with the header buttons
Move the floating hamburger from left-2/top-2 to left-4/top-3 so it lines up
with the header's content padding (and the calendar's nav buttons); bump the
non-header page top reserve to pt-14 to clear the taller trigger.
2026-07-18 08:59:55 -03:00

80 lines
2.6 KiB
Vue

<script setup lang="ts">
import { useHttp, usePage } from '@inertiajs/vue3';
import { onBeforeUnmount, onMounted } from 'vue';
import AppHeader from '@/components/AppHeader.vue';
import AppSidebar from '@/components/AppSidebar.vue';
import Toast from '@/components/Toast.vue';
import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
import { heartbeat as heartbeatRoute } from '@/routes/app/presence';
const page = usePage();
const isOpen = page.props.sidebarOpen;
type Props = {
fullWidth?: boolean;
};
withDefaults(defineProps<Props>(), {
fullWidth: false,
});
const heartbeatHttp = useHttp<Record<string, never>, { ok: boolean }>({});
let heartbeatTimer: ReturnType<typeof setInterval> | null = null;
const sendHeartbeat = () => {
if (typeof document === 'undefined' || document.hidden) return;
void heartbeatHttp.post(heartbeatRoute.url()).catch(() => undefined);
};
onMounted(() => {
sendHeartbeat();
heartbeatTimer = setInterval(sendHeartbeat, 30_000);
});
onBeforeUnmount(() => {
if (heartbeatTimer) clearInterval(heartbeatTimer);
});
</script>
<template>
<SidebarProvider :default-open="isOpen">
<AppSidebar />
<SidebarInset class="overflow-x-hidden">
<AppHeader v-if="$slots['header'] || $slots['header-actions']">
<template v-if="$slots['header']" #left>
<slot name="header" />
</template>
<template v-if="$slots['header-actions']" #right>
<slot name="header-actions" />
</template>
</AppHeader>
<SidebarTrigger
v-else
class="absolute left-4 top-3 z-30 size-10 rounded-md border-2 border-foreground bg-card text-foreground shadow-2xs md:hidden"
/>
<div
:class="
fullWidth
? 'flex min-h-0 flex-1 flex-col overflow-y-auto'
: 'flex-1 overflow-y-auto'
"
>
<div
:class="[
fullWidth
? 'flex min-h-0 flex-1 flex-col'
: 'mx-auto w-full max-w-7xl',
!fullWidth && !$slots['header'] && !$slots['header-actions']
? 'pt-14 md:pt-0'
: '',
]"
>
<slot />
</div>
</div>
</SidebarInset>
</SidebarProvider>
<Toast />
</template>