Files
social-media/frontend/src/App.vue
Jonathan Bourdon b7379cf823
Some checks failed
Backend CI/CD / build_and_deploy (push) Has been cancelled
Frontend CI/CD / build_and_deploy (push) Has been cancelled
feat: just getting better and better
2026-05-04 21:34:38 -04:00

108 lines
3.3 KiB
Vue

<template>
<v-app>
<div class="shell-container">
<template v-if="showsAppSidebar">
<div class="shell-sidebar-wrap">
<app-sidebar :is-expanded="isSidebarExpanded" />
<button
class="sidebar-boundary-toggle"
type="button"
@click="isSidebarExpanded = !isSidebarExpanded"
>
<v-icon :icon="isSidebarExpanded ? mdiChevronLeft : mdiChevronRight" />
</button>
</div>
</template>
<div
class="shell-main"
:class="{ 'shell-main-app': showsAppSidebar }"
>
<app-bar v-if="showsAppSidebar" />
<div class="shell-view">
<router-view></router-view>
</div>
</div>
<FeedbackFloatingButton v-if="showsAppSidebar" />
</div>
</v-app>
</template>
<script async setup>
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useDisplay } from 'vuetify';
import { useAuthStore } from '@/features/auth/stores/authStore.js';
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
import AppBar from '@/layouts/main/AppBar.vue';
import AppSidebar from '@/layouts/main/AppSidebar.vue';
import FeedbackFloatingButton from '@/features/feedback/components/FeedbackFloatingButton.vue';
const route = useRoute();
const authStore = useAuthStore();
const { smAndDown } = useDisplay();
const defaultSidebarExpanded = computed(() => !smAndDown.value);
const isSidebarExpanded = ref(defaultSidebarExpanded.value);
const showsAppSidebar = computed(() =>
authStore.isAuthenticated && route.path.startsWith('/app')
);
watch(showsAppSidebar, value => {
if (!value) {
isSidebarExpanded.value = true;
return;
}
isSidebarExpanded.value = defaultSidebarExpanded.value;
}, { immediate: true });
</script>
<style scoped>
.shell-container {
@apply min-h-screen flex flex-row;
@apply w-full font-sans;
background:
radial-gradient(circle at top left, rgba(255, 174, 94, 0.18), transparent 28%),
radial-gradient(circle at top right, rgba(52, 211, 153, 0.16), transparent 24%),
linear-gradient(180deg, #fffaf2 0%, #f6efe2 100%);
color: #172033;
}
.shell-main {
@apply relative flex min-w-0 flex-1 flex-col;
}
.shell-main-app {
@apply min-h-screen;
}
.shell-sidebar-wrap {
@apply sticky top-0 z-30 h-screen flex-shrink-0;
}
.sidebar-boundary-toggle {
@apply absolute left-full top-[1.48rem] z-40 flex h-[1.8rem] w-[1.8rem] -translate-x-1/2 items-center justify-center rounded-full border transition-colors;
background: rgba(255, 250, 242, 0.98);
border-color: rgba(23, 32, 51, 0.12);
color: #44516a;
box-shadow: 0 12px 28px rgba(23, 32, 51, 0.12);
}
.sidebar-boundary-toggle:hover {
background: #172033;
color: #fffaf2;
}
.sidebar-boundary-toggle :deep(.v-icon) {
font-size: 1rem;
}
.shell-view {
@apply flex min-w-0 flex-1;
}
</style>