add view transition for terminal open

This commit is contained in:
Peter Steinberger 2025-06-20 20:15:37 +02:00
parent 8b64f2088d
commit d8dae14bde
6 changed files with 132 additions and 3 deletions

View file

@ -171,6 +171,71 @@ export class VibeTunnelApp extends LitElement {
this.showCreateModal = false;
}
private async handleNavigateToSession(e: CustomEvent): Promise<void> {
const { sessionId } = e.detail;
// Check if View Transitions API is supported
if ('startViewTransition' in document && typeof document.startViewTransition === 'function') {
// Debug: Check what elements have view-transition-name before transition
console.log('Before transition - elements with view-transition-name:');
document.querySelectorAll('[style*="view-transition-name"]').forEach((el) => {
console.log('Element:', el, 'Style:', el.getAttribute('style'));
});
// Use View Transitions API for smooth animation
const transition = document.startViewTransition(async () => {
// Update state which will trigger a re-render
this.selectedSessionId = sessionId;
this.currentView = 'session';
this.updateUrl(sessionId);
// Wait for LitElement to complete its update
await this.updateComplete;
// Debug: Check what elements have view-transition-name after transition
console.log('After transition - elements with view-transition-name:');
document.querySelectorAll('[style*="view-transition-name"]').forEach((el) => {
console.log('Element:', el, 'Style:', el.getAttribute('style'));
});
});
// Log if transition is ready
transition.ready
.then(() => {
console.log('View transition ready');
})
.catch((err) => {
console.error('View transition failed:', err);
});
} else {
// Fallback for browsers without View Transitions support
this.selectedSessionId = sessionId;
this.currentView = 'session';
this.updateUrl(sessionId);
}
}
private handleNavigateToList(): void {
// Check if View Transitions API is supported
if ('startViewTransition' in document && typeof document.startViewTransition === 'function') {
// Use View Transitions API for smooth animation
document.startViewTransition(() => {
// Update state which will trigger a re-render
this.selectedSessionId = null;
this.currentView = 'list';
this.updateUrl();
// Force update to ensure DOM changes happen within the transition
return this.updateComplete;
});
} else {
// Fallback for browsers without View Transitions support
this.selectedSessionId = null;
this.currentView = 'list';
this.updateUrl();
}
}
private async handleKillAll() {
// Find all session cards and trigger their kill buttons
const sessionCards = this.querySelectorAll<SessionCard>('session-card');

View file

@ -40,7 +40,15 @@ export class SessionList extends LitElement {
private handleSessionSelect(e: CustomEvent) {
const session = e.detail as Session;
window.location.search = `?session=${session.id}`;
// Dispatch a custom event that the app can handle with view transitions
this.dispatchEvent(
new CustomEvent('navigate-to-session', {
detail: { sessionId: session.id },
bubbles: true,
composed: true,
})
);
}
private handleSessionKilled(e: CustomEvent) {

View file

@ -446,7 +446,13 @@ export class SessionView extends LitElement {
}
private handleBack() {
window.location.search = '';
// Dispatch a custom event that the app can handle with view transitions
this.dispatchEvent(
new CustomEvent('navigate-to-list', {
bubbles: true,
composed: true,
})
);
}
private handleSessionExit(e: Event) {

View file

@ -1195,6 +1195,7 @@ export class Terminal extends LitElement {
class="terminal-container w-full h-full overflow-hidden"
tabindex="0"
contenteditable="false"
style="view-transition-name: terminal-${this.sessionId}"
@paste=${this.handlePaste}
@click=${this.handleClick}
></div>

View file

@ -191,7 +191,10 @@ export class VibeTerminalBuffer extends LitElement {
line-height: ${lineHeight}px;
}
</style>
<div class="relative w-full h-full overflow-hidden bg-black">
<div
class="relative w-full h-full overflow-hidden bg-black"
style="view-transition-name: terminal-${this.sessionId}"
>
${this.error
? html`
<div class="absolute inset-0 flex items-center justify-center">

View file

@ -701,3 +701,49 @@ body {
color: #00ff88;
box-shadow: 0 0 10px rgba(0, 255, 136, 0.3);
}
/* View Transitions */
@supports (view-transition-name: none) {
::view-transition {
/* Set the transition duration to 0.1s as requested */
--transition-duration: 100ms;
}
::view-transition-group(*) {
animation-duration: var(--transition-duration);
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
::view-transition-old(*),
::view-transition-new(*) {
animation-duration: var(--transition-duration);
mix-blend-mode: normal;
}
/* Specific styling for terminal transitions */
::view-transition-old(terminal-*) {
animation: view-transition-fade-out var(--transition-duration) cubic-bezier(0.4, 0, 0.2, 1);
}
::view-transition-new(terminal-*) {
animation: view-transition-fade-in var(--transition-duration) cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes view-transition-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes view-transition-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}