remove slide effect

This commit is contained in:
2026-08-27 21:33:58 +02:00
parent a26f31a150
commit f447a9a163
5 changed files with 101 additions and 84 deletions
+21 -75
View File
@@ -1,5 +1,5 @@
<script setup>
import { ref, onMounted, onBeforeUnmount, computed, nextTick, watch } from 'vue';
import { onMounted, onBeforeUnmount, computed, nextTick, watch } from 'vue';
import { useFeeds } from '@/composables/useFeeds';
const {
@@ -43,22 +43,6 @@ let touchStartY = null
const SWIPE_THRESHOLD_X = 50 // min horizontal travel (px) to count as a swipe
const SWIPE_RESTRAINT_Y = 75 // max vertical travel (px) before it's treated as a scroll, not a swipe
// Drives which slide-in/slide-out transition ('slide-next' / 'slide-prev') the
// article view uses — set right before the index actually changes, by both
// the nav buttons and the swipe handler below, so the two triggers animate
// identically.
const slideDirection = ref('next')
function navigateToNextArticle() {
slideDirection.value = 'next'
nextArticle()
}
function navigateToPrevArticle() {
slideDirection.value = 'prev'
prevArticle()
}
function onArticleTouchStart(event) {
// Ignore multi-touch (pinch-zoom) and swipes starting inside a
// horizontally-scrollable code block (.article-feature__content :deep(pre))
@@ -83,9 +67,9 @@ function onArticleTouchEnd(event) {
if (Math.abs(deltaX) < SWIPE_THRESHOLD_X || Math.abs(deltaY) > SWIPE_RESTRAINT_Y) return
if (deltaX < 0) {
navigateToNextArticle()
nextArticle()
} else {
navigateToPrevArticle()
prevArticle()
}
}
@@ -189,20 +173,22 @@ onMounted(async () => {
</svg>
<p class="empty-state__label">All caught up</p>
</div>
<template v-else>
<Transition :name="`slide-${slideDirection}`">
<article class="article-feature" :key="currentIndex">
<p class="article-feature__source">{{ feeds[currentIndex].feedTitle }}</p>
<h2 @click="loadReadable(feeds[currentIndex], currentIndex)" class="article-feature__title">{{ feeds[currentIndex].title }}</h2>
<h3 class="article-feature__meta">{{ feeds[currentIndex].timestamp }}</h3>
<p class="feed-original-link">
<a :href="feeds[currentIndex].url" target="_blank" rel="noopener noreferrer">Read original article &#8599;</a>
<button type="button" class="feed-share-btn" :title="shareLabel" @click="shareUrl(feeds[currentIndex].url)">{{ shareLabel }}</button>
</p>
<p class="article-feature__content" :class="{ 'article-feature__content--readable': feeds[currentIndex].readable }" v-html="feeds[currentIndex].content"></p>
</article>
</Transition>
</template>
<!-- Deliberately no enter/leave transition here: Vue's <Transition>
component forces a synchronous whole-document reflow
(document.body.offsetHeight, in @vue/runtime-dom's forceReflow) on
every enter/leave, regardless of the app's own CSS — confirmed (via
a DevTools performance trace) to be what was corrupting the header's
native <select>/<button> rendering during article paging. -->
<article v-else class="article-feature" :key="currentIndex">
<p class="article-feature__source">{{ feeds[currentIndex].feedTitle }}</p>
<h2 @click="loadReadable(feeds[currentIndex], currentIndex)" class="article-feature__title">{{ feeds[currentIndex].title }}</h2>
<h3 class="article-feature__meta">{{ feeds[currentIndex].timestamp }}</h3>
<p class="feed-original-link">
<a :href="feeds[currentIndex].url" target="_blank" rel="noopener noreferrer">Read original article &#8599;</a>
<button type="button" class="feed-share-btn" :title="shareLabel" @click="shareUrl(feeds[currentIndex].url)">{{ shareLabel }}</button>
</p>
<p class="article-feature__content" :class="{ 'article-feature__content--readable': feeds[currentIndex].readable }" v-html="feeds[currentIndex].content"></p>
</article>
<div class="article-nav">
<button
@@ -210,14 +196,14 @@ onMounted(async () => {
class="article-nav__btn"
:disabled="currentIndex === 0"
aria-label="Previous article"
@click="navigateToPrevArticle"
@click="prevArticle"
>&uarr;</button>
<button
type="button"
class="article-nav__btn"
:disabled="feeds.length === 0 || currentIndex === feeds.length - 1"
aria-label="Next article"
@click="navigateToNextArticle"
@click="nextArticle"
>&darr;</button>
</div>
</div>
@@ -381,46 +367,6 @@ onMounted(async () => {
max-width: 720px;
}
/* Slide-in/out when paging between articles (swipe or nav buttons). The
outgoing article is pulled out of flex flow during its leave transition so
the incoming one can take its place immediately, instead of the two
stacking and doubling the page height for the transition's duration. */
.slide-next-enter-active,
.slide-next-leave-active,
.slide-prev-enter-active,
.slide-prev-leave-active {
transition: transform 0.28s ease, opacity 0.28s ease;
}
.slide-next-leave-active,
.slide-prev-leave-active {
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
}
.slide-next-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-next-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.slide-prev-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-prev-leave-to {
transform: translateX(100%);
opacity: 0;
}
.article-feature__source {
margin: 0 0 0.5em;
padding: 0 1rem;