Refactors the calendar grid to support smoother navigation transitions by using separate week containers. This change introduces a GridManager to handle grid rendering and interactions within these containers, enabling scroll synchronization and click event handling for each week view. Also, configures the calendar to start at midnight and span a full 24-hour day, providing a more comprehensive view.
293 lines
No EOL
6.2 KiB
CSS
293 lines
No EOL
6.2 KiB
CSS
/* styles/layout.css */
|
|
|
|
/* Main calendar container */
|
|
swp-calendar {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
background: var(--color-background);
|
|
position: relative;
|
|
}
|
|
|
|
/* Navigation bar layout */
|
|
swp-calendar-nav {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr auto auto;
|
|
align-items: center;
|
|
gap: 20px;
|
|
padding: 12px 16px;
|
|
background: var(--color-background);
|
|
border-bottom: 1px solid var(--color-border);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
/* Calendar container grid (following POC structure) */
|
|
swp-calendar-container {
|
|
flex: 1;
|
|
display: grid;
|
|
grid-template-columns: 60px 1fr;
|
|
grid-template-rows: 1fr;
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
|
|
/* Time axis (fixed, left side) */
|
|
swp-time-axis {
|
|
grid-column: 1;
|
|
grid-row: 1;
|
|
background: var(--color-surface);
|
|
border-right: 1px solid var(--color-border);
|
|
position: sticky;
|
|
left: 0;
|
|
z-index: 4;
|
|
padding-top: 80px; /* Match header height */
|
|
overflow-y: hidden; /* Hide scrollbar but allow programmatic scrolling */
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
/* Week container for sliding */
|
|
swp-week-container {
|
|
grid-column: 2;
|
|
display: grid;
|
|
grid-template-rows: auto 1fr;
|
|
position: relative;
|
|
width: 100%;
|
|
transition: transform 400ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
/* Week header (inside week container) */
|
|
swp-week-header {
|
|
display: grid;
|
|
grid-template-columns: repeat(7, 1fr);
|
|
background: var(--color-surface);
|
|
border-bottom: 1px solid var(--color-border);
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 3;
|
|
height: 80px; /* Fixed height */
|
|
}
|
|
|
|
/* Scrollable content */
|
|
swp-scrollable-content {
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
scroll-behavior: smooth;
|
|
position: relative;
|
|
flex: 1;
|
|
min-height: 0; /* Important for flex children to shrink */
|
|
max-height: calc(100vh - 80px - 80px); /* Subtract nav height and week-header height */
|
|
}
|
|
|
|
swp-week-container.slide-out-left {
|
|
transform: translateX(-100%);
|
|
}
|
|
|
|
swp-week-container.slide-out-right {
|
|
transform: translateX(100%);
|
|
}
|
|
|
|
swp-week-container.slide-in-left {
|
|
transform: translateX(-100%);
|
|
}
|
|
|
|
swp-week-container.slide-in-right {
|
|
transform: translateX(100%);
|
|
}
|
|
|
|
swp-hour-marker {
|
|
height: var(--hour-height);
|
|
padding: 8px;
|
|
font-size: 0.75rem;
|
|
color: var(--color-text-secondary);
|
|
display: flex;
|
|
align-items: flex-start;
|
|
position: relative;
|
|
|
|
/* Hour line extending into calendar */
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 100%;
|
|
width: 100vw;
|
|
height: 1px;
|
|
background: var(--color-grid-line);
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
|
|
/* Day header styling (inside week-header) */
|
|
|
|
swp-day-header {
|
|
padding: 12px;
|
|
text-align: center;
|
|
border-right: 1px solid var(--color-grid-line);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
swp-day-header:last-child {
|
|
border-right: none;
|
|
}
|
|
|
|
swp-day-name {
|
|
display: block;
|
|
font-weight: 500;
|
|
font-size: 0.875rem;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-day-date {
|
|
display: block;
|
|
font-size: 1.25rem;
|
|
font-weight: 600;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
swp-day-header[data-today="true"] swp-day-date {
|
|
color: var(--color-primary);
|
|
background: rgba(33, 150, 243, 0.1);
|
|
border-radius: 50%;
|
|
width: 36px;
|
|
height: 36px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 4px auto 0;
|
|
}
|
|
|
|
/* All-day events container */
|
|
swp-allday-container {
|
|
position: sticky;
|
|
top: 0;
|
|
background: var(--color-background);
|
|
border-bottom: 1px solid var(--color-border);
|
|
min-height: 0;
|
|
z-index: 2;
|
|
|
|
&:not(:empty) {
|
|
padding: 8px 0;
|
|
}
|
|
}
|
|
|
|
/* Time grid */
|
|
swp-time-grid {
|
|
position: relative;
|
|
height: calc(24 * var(--hour-height));
|
|
}
|
|
|
|
swp-time-grid::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: calc((var(--work-start-hour) - var(--day-start-hour)) * var(--hour-height));
|
|
height: calc((var(--work-end-hour) - var(--work-start-hour)) * var(--hour-height));
|
|
left: 0;
|
|
right: 0;
|
|
background: var(--color-work-hours);
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Grid lines */
|
|
swp-grid-lines {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
z-index: var(--z-grid);
|
|
background-image:
|
|
/* Hour lines (stronger) */
|
|
repeating-linear-gradient(
|
|
to bottom,
|
|
transparent,
|
|
transparent calc(var(--hour-height) - 1px),
|
|
var(--color-grid-line) calc(var(--hour-height) - 1px),
|
|
var(--color-grid-line) var(--hour-height)
|
|
),
|
|
/* Quarter hour lines (lighter) */
|
|
repeating-linear-gradient(
|
|
to bottom,
|
|
transparent,
|
|
transparent calc(var(--hour-height) / 4 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) / 4 - 1px),
|
|
var(--color-grid-line-light) calc(var(--hour-height) / 4)
|
|
);
|
|
}
|
|
|
|
/* Ensure grid lines are visible during transitions */
|
|
swp-week-container swp-grid-lines {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
|
|
/* Grid lines should remain visible even during animations */
|
|
swp-week-container.slide-out-left swp-grid-lines,
|
|
swp-week-container.slide-out-right swp-grid-lines,
|
|
swp-week-container.slide-in-left swp-grid-lines,
|
|
swp-week-container.slide-in-right swp-grid-lines {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
|
|
/* Day columns */
|
|
swp-day-columns {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: grid;
|
|
grid-template-columns: repeat(7, 1fr);
|
|
}
|
|
|
|
swp-day-column {
|
|
position: relative;
|
|
border-right: 1px solid var(--color-grid-line);
|
|
}
|
|
|
|
swp-day-column:last-child {
|
|
border-right: none;
|
|
}
|
|
|
|
swp-events-layer {
|
|
position: absolute;
|
|
inset: 0;
|
|
}
|
|
|
|
/* Current time indicator */
|
|
swp-current-time-indicator {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
height: 2px;
|
|
background: var(--color-current-time);
|
|
pointer-events: none;
|
|
z-index: var(--z-current-time);
|
|
|
|
/* Time label */
|
|
&::before {
|
|
content: attr(data-time);
|
|
position: absolute;
|
|
left: -55px;
|
|
top: -10px;
|
|
background: var(--color-current-time);
|
|
color: white;
|
|
padding: 2px 6px;
|
|
font-size: 0.75rem;
|
|
border-radius: 3px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* Animated dot */
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
right: -4px;
|
|
top: -4px;
|
|
width: 10px;
|
|
height: 10px;
|
|
background: var(--color-current-time);
|
|
border-radius: 50%;
|
|
box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.3);
|
|
}
|
|
|
|
/* Position based on current time */
|
|
top: calc(var(--current-minutes) * var(--minute-height));
|
|
} |