dashboard scrolls properly now

This commit is contained in:
Justin Visser 2026-02-19 18:45:55 +01:00
parent ae2ca8f149
commit e49e753023
5 changed files with 19 additions and 13 deletions

View file

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from "vue"; import { computed } from "vue";
import { RouterView } from "vue-router"; import { RouterView, useRoute } from "vue-router";
import AppHeader from "@/components/layout/AppHeader.vue"; import AppHeader from "@/components/layout/AppHeader.vue";
import AppNav from "@/components/layout/AppNav.vue"; import AppNav from "@/components/layout/AppNav.vue";
@ -8,7 +8,9 @@ import RequestErrorPanel from "@/components/patterns/RequestErrorPanel.vue";
import { useAuthStore } from "@/stores/auth"; import { useAuthStore } from "@/stores/auth";
const auth = useAuthStore(); const auth = useAuthStore();
const route = useRoute();
const showChrome = computed(() => auth.isAuthenticated); const showChrome = computed(() => auth.isAuthenticated);
const shouldLockMainScroll = computed(() => route.meta.lockMainScroll === true);
</script> </script>
<template> <template>
@ -22,7 +24,11 @@ const showChrome = computed(() => auth.isAuthenticated);
class="grid h-[calc(100dvh-4.5rem)] min-h-0 grid-cols-1 grid-rows-[auto_minmax(0,1fr)] lg:grid-cols-[17rem_minmax(0,1fr)] lg:grid-rows-1" class="grid h-[calc(100dvh-4.5rem)] min-h-0 grid-cols-1 grid-rows-[auto_minmax(0,1fr)] lg:grid-cols-[17rem_minmax(0,1fr)] lg:grid-rows-1"
> >
<AppNav class="min-h-0 overflow-x-hidden lg:overflow-y-auto" /> <AppNav class="min-h-0 overflow-x-hidden lg:overflow-y-auto" />
<main id="app-main" class="min-h-0 min-w-0 overflow-y-auto overflow-x-hidden px-4 py-6 sm:px-6 lg:px-8"> <main
id="app-main"
class="min-h-0 min-w-0 overflow-x-hidden px-4 py-6 sm:px-6 lg:px-8"
:class="shouldLockMainScroll ? 'overflow-y-auto lg:overflow-y-hidden' : 'overflow-y-auto'"
>
<RouterView /> <RouterView />
</main> </main>
</div> </div>

View file

@ -28,7 +28,7 @@ export const router = createRouter({
path: "/dashboard", path: "/dashboard",
name: "dashboard", name: "dashboard",
component: DashboardPage, component: DashboardPage,
meta: { requiresAuth: true }, meta: { requiresAuth: true, lockMainScroll: true },
}, },
{ {
path: "/scholars", path: "/scholars",

View file

@ -15,7 +15,7 @@ const props = withDefaults(
<section <section
:class=" :class="
props.fill props.fill
? 'min-w-0 flex min-h-0 flex-col gap-6 lg:h-full' ? 'min-w-0 flex min-h-0 flex-col gap-6 lg:h-full lg:overflow-hidden'
: 'page-stack min-w-0' : 'page-stack min-w-0'
" "
> >
@ -23,7 +23,7 @@ const props = withDefaults(
<h1 class="page-title">{{ props.title }}</h1> <h1 class="page-title">{{ props.title }}</h1>
<p v-if="props.subtitle" class="page-subtitle">{{ props.subtitle }}</p> <p v-if="props.subtitle" class="page-subtitle">{{ props.subtitle }}</p>
</header> </header>
<div v-if="props.fill" class="min-h-0 flex-1"> <div v-if="props.fill" class="flex min-h-0 flex-1 flex-col">
<slot /> <slot />
</div> </div>
<slot v-else /> <slot v-else />

View file

@ -40,7 +40,7 @@ function countQueueStatuses(statuses: string[]): QueueHealth {
export async function fetchDashboardSnapshot(): Promise<DashboardSnapshot> { export async function fetchDashboardSnapshot(): Promise<DashboardSnapshot> {
const [publications, runs, queueItems] = await Promise.all([ const [publications, runs, queueItems] = await Promise.all([
listPublications({ mode: "new", limit: 20 }), listPublications({ mode: "new", limit: 20 }),
listRuns({ limit: 5 }), listRuns({ limit: 20 }),
listQueueItems(200), listQueueItems(200),
]); ]);

View file

@ -87,7 +87,7 @@ onMounted(() => {
subtitle="Track recent publication updates and monitor background profile checks." subtitle="Track recent publication updates and monitor background profile checks."
fill fill
> >
<div class="flex min-h-0 flex-1 flex-col gap-4"> <div class="flex min-h-0 flex-1 flex-col gap-4 xl:overflow-hidden">
<RequestStateAlerts <RequestStateAlerts
:success-message="successMessage" :success-message="successMessage"
:error-message="errorMessage" :error-message="errorMessage"
@ -96,10 +96,10 @@ onMounted(() => {
@dismiss-success="successMessage = null" @dismiss-success="successMessage = null"
/> />
<div class="min-h-0 flex-1"> <div class="h-0 min-h-0 flex-1 xl:overflow-hidden">
<AsyncStateGate :loading="loading" :loading-lines="6" :show-empty="false"> <AsyncStateGate :loading="loading" :loading-lines="6" :show-empty="false">
<template v-if="snapshot"> <template v-if="snapshot">
<section class="grid min-h-0 gap-4 xl:h-full xl:grid-cols-2"> <section class="grid min-h-0 gap-4 xl:h-full xl:grid-cols-2 xl:grid-rows-[minmax(0,1fr)] xl:overflow-hidden">
<AppCard class="flex min-h-0 flex-col gap-4 xl:h-full xl:overflow-hidden"> <AppCard class="flex min-h-0 flex-col gap-4 xl:h-full xl:overflow-hidden">
<div class="flex flex-wrap items-center justify-between gap-2"> <div class="flex flex-wrap items-center justify-between gap-2">
<div class="space-y-1"> <div class="space-y-1">
@ -120,7 +120,7 @@ onMounted(() => {
body="When a completed update check discovers changes, they will appear here." body="When a completed update check discovers changes, they will appear here."
/> />
<ul v-else class="grid min-h-0 flex-1 gap-3 overflow-y-auto pr-1"> <ul v-else class="grid min-h-0 flex-1 content-start gap-3 overflow-y-scroll overscroll-contain pr-1">
<li <li
v-for="item in snapshot.recentPublications.slice(0, 20)" v-for="item in snapshot.recentPublications.slice(0, 20)"
:key="item.publication_id" :key="item.publication_id"
@ -149,7 +149,7 @@ onMounted(() => {
</ul> </ul>
</AppCard> </AppCard>
<div class="grid min-h-0 gap-4 xl:h-full xl:grid-rows-[auto_minmax(0,1fr)]"> <div class="grid min-h-0 gap-4 xl:h-full xl:grid-rows-[auto_minmax(0,1fr)] xl:overflow-hidden">
<AppCard class="flex min-h-0 flex-col gap-4"> <AppCard class="flex min-h-0 flex-col gap-4">
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">
<h2 class="text-lg font-semibold text-ink-primary">Overview</h2> <h2 class="text-lg font-semibold text-ink-primary">Overview</h2>
@ -237,14 +237,14 @@ onMounted(() => {
body="Start an update check to begin monitoring activity." body="Start an update check to begin monitoring activity."
/> />
<div class="grid min-h-0 flex-1 gap-2 xl:overflow-hidden"> <div class="flex min-h-0 flex-1 flex-col gap-2 xl:overflow-hidden">
<p class="text-xs font-semibold uppercase tracking-wide text-muted">Recent checks</p> <p class="text-xs font-semibold uppercase tracking-wide text-muted">Recent checks</p>
<AppEmptyState <AppEmptyState
v-if="snapshot.recentRuns.length === 0" v-if="snapshot.recentRuns.length === 0"
title="No checks yet" title="No checks yet"
body="Check history will appear here." body="Check history will appear here."
/> />
<ul v-else class="grid gap-2 overflow-y-auto pr-1"> <ul v-else class="grid min-h-0 flex-1 content-start gap-2 overflow-y-auto overscroll-contain pr-1">
<li <li
v-for="run in snapshot.recentRuns" v-for="run in snapshot.recentRuns"
:key="run.id" :key="run.id"