From 7168a97afa642b6bc992f38b8da962650365936b Mon Sep 17 00:00:00 2001 From: DiheChen Date: Thu, 5 Nov 2026 12:46:00 +0800 Subject: [PATCH] fix: slide the side panel tabs in their own direction --- web/src/app/app.tsx | 4 +++- web/src/app/style.css | 9 +++++---- web/src/app/view-transition.ts | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/web/src/app/app.tsx b/web/src/app/app.tsx index ca59b52..d3fd81d 100644 --- a/web/src/app/app.tsx +++ b/web/src/app/app.tsx @@ -218,8 +218,10 @@ export function App() { // 加入房间前不显示面板:底部的切换按钮此时不可用,而聊天视图的关闭按钮在 RoomGate 内,打开的聊天面板会无法关闭。 const shownPanel = joined && panel !== page ? panel : null const switchPanel = (next: Panel | null) => { + // 侧栏 tab 里播放历史排在播放列表右边,切回播放列表时内容要从左边进来。 + const direction = shownPanel === 'history' && next === 'queue' ? 'backward' : 'forward' if (shownPanel && next && next !== shownPanel && next !== page) - withViewTransition(() => navigationStore.setPanel(next)) + withViewTransition(() => navigationStore.setPanel(next), direction) else navigationStore.setPanel(next) } diff --git a/web/src/app/style.css b/web/src/app/style.css index 7aed1fb..2f1a149 100644 --- a/web/src/app/style.css +++ b/web/src/app/style.css @@ -76,7 +76,8 @@ from { opacity: 0; } to { opacity: 1; } } -:root { --detail-panel-width: 480px; } +:root { --detail-panel-width: 480px; --view-direction: 1; } +:root[data-view-direction='backward'] { --view-direction: -1; } .detail-panel { width: var(--detail-panel-width); flex-shrink: 0; position: relative; min-height: 0; display: flex; flex-direction: column; border: 0; border-radius: 12px; background: var(--color-panel); overflow: hidden; animation: detail-panel-open 240ms cubic-bezier(.2, .8, .2, 1) both; } .detail-panel-content { view-transition-name: detail-panel-content; width: var(--detail-panel-width); flex: 1; min-height: 0; display: flex; flex-direction: column; } .detail-panel-closing { pointer-events: none; animation-name: detail-panel-close; } @@ -99,15 +100,15 @@ ::view-transition-new(detail-panel-content) { animation: view-push-in 300ms cubic-bezier(.2, .8, .2, 1) both; } @keyframes view-recede { from { transform: translateX(0); } - to { transform: translateX(-14%); } + to { transform: translateX(calc(var(--view-direction) * -14%)); } } @keyframes view-push-in { - from { transform: translateX(100%); } + from { transform: translateX(calc(var(--view-direction) * 100%)); } to { transform: translateX(0); } } .detail-panel-swap { animation: detail-panel-swap-in 180ms cubic-bezier(.2, .8, .2, 1) both; } @keyframes detail-panel-swap-in { - from { opacity: 0; transform: translateX(10px); } + from { opacity: 0; transform: translateX(calc(var(--view-direction) * 10px)); } to { opacity: 1; transform: translateX(0); } } :root[data-performance='low'] .header-menu[open] .main-nav { animation: fade-in 160ms ease both; } diff --git a/web/src/app/view-transition.ts b/web/src/app/view-transition.ts index dfff078..89061c1 100644 --- a/web/src/app/view-transition.ts +++ b/web/src/app/view-transition.ts @@ -5,7 +5,8 @@ export function canPushViews(): boolean { return 'startViewTransition' in document && performanceStore.smoothMotion() } -export function withViewTransition(update: () => void): void { +export function withViewTransition(update: () => void, direction: 'forward' | 'backward'): void { + document.documentElement.dataset.viewDirection = direction if (!canPushViews()) { update() return