feat: refine animation strategy (day shift vs week slide)

- Implemented mixed View Transition strategy:
  - Week Navigation: Full container slide.
  - Day Navigation: Per-column 'Magic Move' shift.
- Updated navigate function to track navType.
- Updated styling to apply view-transition-name dynamically.
This commit is contained in:
mARTin 2026-02-01 14:53:45 +01:00
parent 3aad7b5371
commit a4c4670662
2 changed files with 19 additions and 9 deletions

View File

@ -1570,10 +1570,13 @@ h3 {
/* --- VIEW TRANSITION ANIMATION (TeuxDeux-like) --- */ /* --- VIEW TRANSITION ANIMATION (TeuxDeux-like) --- */
.teuxdeux-days-grid { /* Only apply Container transitions (Full Slide) when navType is 'week' */
[data-nav-type="week"] .teuxdeux-days-grid {
view-transition-name: week-grid; view-transition-name: week-grid;
} }
/* When navType="day", NO name on container, so columns animate individually via inline view-transition-name */
@keyframes slideOutToLeft { @keyframes slideOutToLeft {
to { to {
transform: translateX(-100%); transform: translateX(-100%);

View File

@ -202,11 +202,14 @@ export default function TeuxDeuxView() {
// Navigation handlers with proper slide animation // Navigation handlers with proper slide animation
// Simplified: Immediate state update with slide-in animation to prevent blank flash // Simplified: Immediate state update with slide-in animation to prevent blank flash
const navigate = (newDate: Date, direction: 'left' | 'right') => { const navigate = (newDate: Date, direction: 'left' | 'right', type: 'day' | 'week') => {
// Use View Transition API for smooth 'TeuxDeux' slide (simultaneous old/new) // Use View Transition API for smooth 'TeuxDeux' slide (simultaneous old/new)
if (typeof document !== 'undefined' && 'startViewTransition' in document) { if (typeof document !== 'undefined' && 'startViewTransition' in document) {
document.documentElement.dataset.transitionDirection = direction === 'left' ? 'next' : 'prev'; const doc = document as any;
(document as any).startViewTransition(() => { doc.documentElement.dataset.transitionDirection = direction === 'left' ? 'next' : 'prev';
doc.documentElement.dataset.navType = type;
doc.startViewTransition(() => {
setCurrentWeekStart(newDate); setCurrentWeekStart(newDate);
setSlideDirection(null); setSlideDirection(null);
}); });
@ -215,10 +218,10 @@ export default function TeuxDeuxView() {
} }
}; };
const goToPrevWeek = () => navigate(new Date(currentWeekStart.getTime() - 7 * 24 * 60 * 60 * 1000), 'right'); const goToPrevWeek = () => navigate(new Date(currentWeekStart.getTime() - 7 * 24 * 60 * 60 * 1000), 'right', 'week');
const goToNextWeek = () => navigate(new Date(currentWeekStart.getTime() + 7 * 24 * 60 * 60 * 1000), 'left'); const goToNextWeek = () => navigate(new Date(currentWeekStart.getTime() + 7 * 24 * 60 * 60 * 1000), 'left', 'week');
const goToPrevDay = () => navigate(new Date(currentWeekStart.getTime() - 24 * 60 * 60 * 1000), 'right'); const goToPrevDay = () => navigate(new Date(currentWeekStart.getTime() - 24 * 60 * 60 * 1000), 'right', 'day');
const goToNextDay = () => navigate(new Date(currentWeekStart.getTime() + 24 * 60 * 60 * 1000), 'left'); const goToNextDay = () => navigate(new Date(currentWeekStart.getTime() + 24 * 60 * 60 * 1000), 'left', 'day');
const goToToday = () => setCurrentWeekStart(getStartOfWeek(new Date())); const goToToday = () => setCurrentWeekStart(getStartOfWeek(new Date()));
// Task CRUD operations // Task CRUD operations
@ -511,7 +514,11 @@ export default function TeuxDeuxView() {
{/* Day Columns */} {/* Day Columns */}
<main className={`teuxdeux-days-grid cols-${viewDays} ${slideDirection ? `slide-${slideDirection}` : ''}`}> <main className={`teuxdeux-days-grid cols-${viewDays} ${slideDirection ? `slide-${slideDirection}` : ''}`}>
{getVisibleDays().map((date) => ( {getVisibleDays().map((date) => (
<div key={date.toISOString()} className="teuxdeux-day-column"> <div
key={date.toISOString()}
className="teuxdeux-day-column"
style={{ viewTransitionName: `day-${date.getFullYear()}-${date.getMonth()}-${date.getDate()}` } as any}
>
{/* Day Header */} {/* Day Header */}
<header className="teuxdeux-day-header"> <header className="teuxdeux-day-header">
<div className="teuxdeux-day-date">{formatDateHeader(date)}</div> <div className="teuxdeux-day-date">{formatDateHeader(date)}</div>