fix: CSS class slide animation, mobile dot, flex task indicators
This commit is contained in:
parent
b3503d9e4d
commit
9fa646fa55
@ -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 */
|
||||||
|
|||||||
@ -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}>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user