Fix Steam game transition jumping to top of container
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m28s

Wrap Transition in a relative-positioned game-container div so the
leaving element's absolute positioning is scoped to the game area,
not the full wrapper. Use flex layout so the container fills only
the space below the header.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 02:10:21 +00:00
parent d4a6343d5e
commit 7798b54391

View File

@@ -17,91 +17,105 @@ let nextId = null;
let refreshId = null; let refreshId = null;
function nextGame() { function nextGame() {
clearTimeout(nextId); clearTimeout(nextId);
nextId = setTimeout(nextGame, 5000); nextId = setTimeout(nextGame, 5000);
if (steamStatus.value.recentGames.length) { if (steamStatus.value.recentGames.length) {
idx.value = (idx.value + 1) % steamStatus.value.recentGames.length; idx.value = (idx.value + 1) % steamStatus.value.recentGames.length;
} }
} }
onMounted(() => { onMounted(() => {
nextId = setTimeout(nextGame, 5000); nextId = setTimeout(nextGame, 5000);
refreshId = setInterval(() => steamStore.fetchSteam(), 5 * 60 * 1000); refreshId = setInterval(() => steamStore.fetchSteam(), 5 * 60 * 1000);
}); });
onUnmounted(() => { onUnmounted(() => {
clearTimeout(nextId); clearTimeout(nextId);
clearInterval(refreshId); clearInterval(refreshId);
}); });
function formatHours(minutes) { function formatHours(minutes) {
const hrs = (minutes / 60).toFixed(1); const hrs = (minutes / 60).toFixed(1);
return `${hrs}h`; return `${hrs}h`;
} }
</script> </script>
<template> <template>
<div class="steam-wrapper"> <div class="steam-wrapper">
<Header class="text-left"> <Header class="text-left">
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
Steam Steam
<span <span
class="inline-block w-2 h-2 rounded-full" class="inline-block w-2 h-2 rounded-full"
:class="steamStatus.online ? 'bg-green-500' : 'bg-gray-400'" :class="steamStatus.online ? 'bg-green-500' : 'bg-gray-400'"
:title="steamStatus.online ? 'Online' : 'Offline'" :title="steamStatus.online ? 'Online' : 'Offline'"
/> />
</span> </span>
</Header> </Header>
<div v-if="!loaded" class="p-2 text-sm">Loading...</div> <div v-if="!loaded" class="p-2 text-sm">Loading...</div>
<Transition name="fade" v-else-if="game"> <div v-else-if="game" class="game-container">
<div @click="nextGame" :key="game.appId" class="flex flex-col items-center"> <Transition name="fade">
<img <div
:src="game.headerImageUrl" @click="nextGame"
:alt="game.name" :key="game.appId"
class="game-img" class="flex flex-col items-center"
/> >
<p class="text-center"> <img
<strong>{{ game.name }}</strong> :src="game.headerImageUrl"
</p> :alt="game.name"
<p class="text-center text-tertiary text-xs"> class="game-img"
{{ formatHours(game.playtime2Weeks) }} last 2 weeks />
</p> <p class="text-center">
</div> <strong>{{ game.name }}</strong>
</Transition> </p>
<p class="text-center text-tertiary text-xs">
{{ formatHours(game.playtime2Weeks) }} last 2 weeks
</p>
</div>
</Transition>
</div>
<div v-else class="p-2 text-sm">No recent games.</div> <div v-else class="p-2 text-sm">No recent games.</div>
</div> </div>
</template> </template>
<style scoped> <style scoped>
.steam-wrapper { .steam-wrapper {
position: relative; position: relative;
width: 100%; height: 50mm;
height: 100%; display: flex;
flex-direction: column;
}
.game-container {
position: relative;
flex: 1;
min-height: 0;
overflow-y: scroll;
} }
.game-img { .game-img {
width: 90%; width: 90%;
} }
p { p {
width: 100%; width: 100%;
margin: 0 auto; margin: 0 auto;
} }
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity 0.5s ease; transition: opacity 0.5s ease;
} }
.fade-leave-active { .fade-leave-active {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
} }
.fade-enter-from, .fade-enter-from,
.fade-leave-to { .fade-leave-to {
opacity: 0; opacity: 0;
} }
</style> </style>