feat(calendar): header continuity with week numbers + skeleton content in fly-rect
- Add ISO week numbers to the left of week rows in month view (8, 9, 10...) with spacer alignment on day-of-week headers - Inject label + skeleton placeholder lines into fly-rect during zoom animations: zoom-in shows source label (month name / "Week N" / day name) + pulsing bars zoom-out shows target context label + skeleton - Skeleton CSS uses pulse animation (0.8s alternate) for loading hint - Non-scoped style block for dynamically injected innerHTML elements - isoWeekNumber helper for ISO 8601 week calculation - Extended MonthRow type with weekNumber property Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ type MonthCell = {
|
||||
type MonthRow = {
|
||||
key: string;
|
||||
startKey: string;
|
||||
weekNumber: number;
|
||||
cells: MonthCell[];
|
||||
};
|
||||
|
||||
@@ -220,21 +221,24 @@ defineProps<{
|
||||
data-calendar-layer="month"
|
||||
:class="calendarView === 'month' || calendarView === 'agenda' ? 'calendar-depth-layer-active' : 'calendar-depth-layer-hidden'"
|
||||
>
|
||||
<div class="grid grid-cols-7 gap-1 text-center text-xs font-semibold text-base-content/60">
|
||||
<span>Sun</span>
|
||||
<span>Mon</span>
|
||||
<span>Tue</span>
|
||||
<span>Wed</span>
|
||||
<span>Thu</span>
|
||||
<span>Fri</span>
|
||||
<span>Sat</span>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="calendar-week-number" aria-hidden="true"></span>
|
||||
<div class="grid grid-cols-7 gap-1 text-center text-xs font-semibold text-base-content/60 flex-1">
|
||||
<span>Sun</span>
|
||||
<span>Mon</span>
|
||||
<span>Tue</span>
|
||||
<span>Wed</span>
|
||||
<span>Thu</span>
|
||||
<span>Fri</span>
|
||||
<span>Sat</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-1 flex-col gap-1">
|
||||
<div
|
||||
v-for="row in monthRows"
|
||||
:key="row.key"
|
||||
class="group relative flex-1 calendar-hover-targetable"
|
||||
class="group relative flex-1 flex items-stretch gap-1 calendar-hover-targetable"
|
||||
:class="[
|
||||
calendarHoveredWeekStartKey === row.startKey ? 'calendar-hover-target' : '',
|
||||
calendarZoomPrimeToken === calendarPrimeWeekToken(row.startKey) ? 'calendar-zoom-prime-active' : '',
|
||||
@@ -243,7 +247,8 @@ defineProps<{
|
||||
:data-calendar-week-start-key="row.startKey"
|
||||
@mouseenter="setCalendarHoveredWeekStartKey(row.startKey)"
|
||||
>
|
||||
<div class="grid grid-cols-7 gap-1 h-full">
|
||||
<span class="calendar-week-number">{{ row.weekNumber }}</span>
|
||||
<div class="grid grid-cols-7 gap-1 h-full flex-1">
|
||||
<button
|
||||
v-for="cell in row.cells"
|
||||
:key="cell.key"
|
||||
@@ -440,6 +445,18 @@ defineProps<{
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
.calendar-week-number {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
min-width: 24px;
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
color: color-mix(in oklab, var(--color-base-content) 40%, transparent);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.calendar-hover-targetable {
|
||||
transform-origin: center center;
|
||||
transition: transform 320ms ease, box-shadow 320ms ease, outline-color 320ms ease;
|
||||
@@ -563,3 +580,44 @@ defineProps<{
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
/* Non-scoped: fly-rect inner content is injected via innerHTML */
|
||||
.calendar-fly-rect .calendar-fly-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 12px 16px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.calendar-fly-rect .calendar-fly-label {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--color-base-content);
|
||||
margin: 0 0 12px 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.calendar-fly-rect .calendar-fly-skeleton {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.calendar-fly-rect .calendar-fly-skeleton-line {
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background: color-mix(in oklab, var(--color-base-content) 10%, transparent);
|
||||
animation: calendar-fly-skeleton-pulse 0.8s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes calendar-fly-skeleton-pulse {
|
||||
from { opacity: 0.3; }
|
||||
to { opacity: 0.7; }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user