fix: CSS class slide animation, mobile dot, flex task indicators

This commit is contained in:
mARTin 2026-03-04 08:54:37 +01:00
parent b3503d9e4d
commit 9fa646fa55
2 changed files with 36 additions and 62 deletions

View File

@ -719,6 +719,9 @@ h3 {
resize: none; resize: none;
min-height: 1.5em; min-height: 1.5em;
padding-top: 2px; /* Align with icons */ padding-top: 2px; /* Align with icons */
display: flex;
align-items: flex-start;
gap: 4px;
} }
/* Task Actions Visibility - Unified for Weekly and Time Grid */ /* Task Actions Visibility - Unified for Weekly and Time Grid */
@ -2736,46 +2739,23 @@ h3 {
background: #333; background: #333;
} }
/* --- VIEW TRANSITION ANIMATION (Day/Week Navigation Slide) --- */ /* --- SLIDE ANIMATION (Day/Week Navigation) --- */
/* Class-based animation that works on ALL browsers (no View Transitions API needed) */
@keyframes slideOutToLeft { @keyframes navSlideInFromRight {
from { transform: translateX(0); } from { transform: translateX(40%); opacity: 0.3; }
to { transform: translateX(-100%); } to { transform: translateX(0); opacity: 1; }
} }
@keyframes slideInFromRight { @keyframes navSlideInFromLeft {
from { transform: translateX(100%); } from { transform: translateX(-40%); opacity: 0.3; }
to { transform: translateX(0); } to { transform: translateX(0); opacity: 1; }
}
@keyframes slideOutToRight {
from { transform: translateX(0); }
to { transform: translateX(100%); }
}
@keyframes slideInFromLeft {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
} }
/* Week Grid Transition Group */ .slide-animate-next {
::view-transition-group(week-grid) { animation: navSlideInFromRight 0.35s cubic-bezier(0.25, 1, 0.5, 1) both;
animation-duration: 0.9s;
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
} }
.slide-animate-prev {
/* Slide Next (Left) — content exits left, new enters from right */ animation: navSlideInFromLeft 0.35s cubic-bezier(0.25, 1, 0.5, 1) both;
[data-slide-direction="next"]::view-transition-old(week-grid) {
animation-name: slideOutToLeft;
}
[data-slide-direction="next"]::view-transition-new(week-grid) {
animation-name: slideInFromRight;
}
/* Slide Prev (Right) — content exits right, new enters from left */
[data-slide-direction="prev"]::view-transition-old(week-grid) {
animation-name: slideOutToRight;
}
[data-slide-direction="prev"]::view-transition-new(week-grid) {
animation-name: slideInFromLeft;
} }
/* Smooth View Transitions */ /* Smooth View Transitions */

View File

@ -2087,27 +2087,30 @@ export default function WeeklyView() {
[tasks, cellDuration], [tasks, cellDuration],
); );
// Navigation handlers with proper slide animation // Navigation handlers with CSS class-based slide animation (works in all browsers)
// Simplified: Immediate state update with slide-in animation to prevent blank flash const gridRef = useRef<HTMLElement>(null);
const navigate = ( const navigate = (
newDate: Date, newDate: Date,
direction: "left" | "right", direction: "left" | "right",
type: "day" | "week", type: "day" | "week",
) => { ) => {
if (typeof document !== "undefined" && "startViewTransition" in document) { const grid = gridRef.current;
const doc = document as any; if (grid) {
doc.documentElement.dataset.slideDirection = // Remove any existing animation class
direction === "left" ? "next" : "prev"; grid.classList.remove("slide-animate-next", "slide-animate-prev");
doc.documentElement.dataset.navType = "week"; // Always use full-grid slide for both day and week // Trigger reflow to restart animation if same direction
void grid.offsetWidth;
doc.startViewTransition(() => { // Add new animation class
setCurrentWeekStart(newDate); grid.classList.add(direction === "left" ? "slide-animate-next" : "slide-animate-prev");
// setSlideDirection state is not strictly needed for global transition but keeping it clean // Clean up after animation
setSlideDirection(direction === "left" ? "next" : "prev"); const cleanup = () => {
}); grid.classList.remove("slide-animate-next", "slide-animate-prev");
} else { grid.removeEventListener("animationend", cleanup);
setCurrentWeekStart(newDate); };
grid.addEventListener("animationend", cleanup, { once: true });
} }
setCurrentWeekStart(newDate);
setSlideDirection(direction === "left" ? "next" : "prev");
}; };
const goToPrevWeek = () => const goToPrevWeek = () =>
@ -3720,8 +3723,8 @@ export default function WeeklyView() {
<button className="p-1.5 rounded text-gray-500 active:bg-white active:shadow-sm" onClick={goToPrevDay} title="Previous Day"> <button className="p-1.5 rounded text-gray-500 active:bg-white active:shadow-sm" onClick={goToPrevDay} title="Previous Day">
<ChevronLeft size={16} /> <ChevronLeft size={16} />
</button> </button>
<button className="px-3 py-1 text-xs font-bold text-gray-600 dark:text-gray-300 rounded active:bg-white active:shadow-sm" onClick={goToToday}> <button className="w-7 h-7 flex items-center justify-center text-gray-600 dark:text-gray-300 rounded active:bg-white active:shadow-sm" onClick={goToToday} title="Today">
Today <span style={{ fontSize: "8px" }}></span>
</button> </button>
<button className="p-1.5 rounded text-gray-500 active:bg-white active:shadow-sm" onClick={goToNextDay} title="Next Day"> <button className="p-1.5 rounded text-gray-500 active:bg-white active:shadow-sm" onClick={goToNextDay} title="Next Day">
<ChevronLeft size={16} className="rotate-180" /> <ChevronLeft size={16} className="rotate-180" />
@ -4311,14 +4314,10 @@ export default function WeeklyView() {
{/* Day Columns */} {/* Day Columns */}
<main <main
ref={gridRef}
className={`weekly-days-grid cols-${viewDays}`} className={`weekly-days-grid cols-${viewDays}`}
data-slide-direction={slideDirection} data-slide-direction={slideDirection}
data-nav-type={viewDays > 1 ? "week" : "day"} data-nav-type={viewDays > 1 ? "week" : "day"}
style={
{
viewTransitionName: viewDays > 1 ? "week-grid" : "none",
} as React.CSSProperties
}
> >
{getVisibleDays().map((date, colIndex) => { {getVisibleDays().map((date, colIndex) => {
const todayMidnight = new Date(); const todayMidnight = new Date();
@ -4330,11 +4329,6 @@ export default function WeeklyView() {
<div <div
key={date.toISOString()} key={date.toISOString()}
className={`weekly-day-column ${date.getDay() === 6 ? "is-sat" : ""} ${date.getDay() === 0 ? "is-sun" : ""} ${isToday ? "is-today" : ""} ${isPast ? "is-past" : ""}`} className={`weekly-day-column ${date.getDay() === 6 ? "is-sat" : ""} ${date.getDay() === 0 ? "is-sun" : ""} ${isToday ? "is-today" : ""} ${isPast ? "is-past" : ""}`}
style={
{
viewTransitionName: `day-${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`,
} as any
}
> >
{/* Day Header */} {/* Day Header */}
<header className="weekly-day-header" ref={colIndex === 0 ? dayHeaderRef : undefined}> <header className="weekly-day-header" ref={colIndex === 0 ? dayHeaderRef : undefined}>