Improves grid layout and navigation
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.
This commit is contained in:
parent
f06c02121c
commit
b443649ced
12 changed files with 719 additions and 302 deletions
|
|
@ -15,8 +15,8 @@
|
|||
--snap-interval: 15;
|
||||
|
||||
/* Time boundaries */
|
||||
--day-start-hour: 7;
|
||||
--day-end-hour: 19;
|
||||
--day-start-hour: 0;
|
||||
--day-end-hour: 24;
|
||||
--work-start-hour: 8;
|
||||
--work-end-hour: 17;
|
||||
|
||||
|
|
@ -94,9 +94,26 @@ swp-day-columns,
|
|||
swp-day-column,
|
||||
swp-events-layer,
|
||||
swp-event,
|
||||
swp-allday-container,
|
||||
swp-loading-overlay,
|
||||
swp-event-popup {
|
||||
swp-week-container,
|
||||
swp-grid-lines,
|
||||
swp-nav-group,
|
||||
swp-nav-button,
|
||||
swp-search-container,
|
||||
swp-search-icon,
|
||||
swp-search-clear,
|
||||
swp-view-selector,
|
||||
swp-view-button,
|
||||
swp-week-info,
|
||||
swp-week-number,
|
||||
swp-date-range,
|
||||
swp-day-header,
|
||||
swp-day-name,
|
||||
swp-day-date,
|
||||
swp-hour-marker,
|
||||
swp-event-time,
|
||||
swp-event-title,
|
||||
swp-spinner {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
/* styles/components/navigation.css */
|
||||
|
||||
/* Navigation bar */
|
||||
swp-calendar-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
padding: 12px 16px;
|
||||
background: var(--color-background);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
/* Navigation groups */
|
||||
swp-nav-group {
|
||||
display: flex;
|
||||
|
|
@ -181,4 +170,23 @@ swp-calendar[data-searching="true"] {
|
|||
box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Week info display */
|
||||
swp-week-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
swp-week-number {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-date-range {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
|
@ -6,12 +6,11 @@ swp-event {
|
|||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: move;
|
||||
transition: box-shadow var(--transition-fast), transform var(--transition-fast);
|
||||
z-index: var(--z-event);
|
||||
|
||||
/* CSS-based positioning */
|
||||
top: calc(var(--start-minutes) * var(--minute-height));
|
||||
height: calc(var(--duration-minutes) * var(--minute-height));
|
||||
transition: box-shadow 150ms ease, transform 150ms ease;
|
||||
z-index: 10;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
padding: 8px;
|
||||
|
||||
/* Event types */
|
||||
&[data-type="meeting"] {
|
||||
|
|
@ -34,110 +33,26 @@ swp-event {
|
|||
border-left: 4px solid var(--color-event-milestone-border);
|
||||
}
|
||||
|
||||
/* Hover state */
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
transform: scale(1.02);
|
||||
z-index: var(--z-event-hover);
|
||||
|
||||
swp-resize-handle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Active/selected state */
|
||||
&[data-selected="true"] {
|
||||
box-shadow: 0 0 0 2px var(--color-primary);
|
||||
z-index: var(--z-event-hover);
|
||||
}
|
||||
|
||||
/* Dragging state */
|
||||
&[data-dragging="true"] {
|
||||
opacity: 0.5;
|
||||
cursor: grabbing;
|
||||
z-index: var(--z-drag-ghost);
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: -2px;
|
||||
border: 2px solid var(--color-primary);
|
||||
border-radius: 6px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resizing state */
|
||||
&[data-resizing="true"] {
|
||||
opacity: 0.8;
|
||||
|
||||
swp-resize-handle {
|
||||
opacity: 1;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
background: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sync status indicators */
|
||||
&[data-sync-status="pending"] {
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: var(--color-warning);
|
||||
border-radius: 50%;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-sync-status="error"] {
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: var(--color-danger);
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Event header */
|
||||
swp-event-header {
|
||||
padding: 8px 12px 4px;
|
||||
|
||||
swp-event-time {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
opacity: 0.8;
|
||||
}
|
||||
swp-event:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
transform: scale(1.02);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
/* Event body */
|
||||
swp-event-body {
|
||||
padding: 0 12px 8px;
|
||||
|
||||
swp-event-title {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.3;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
/* Multi-line ellipsis */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
swp-event-time {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
swp-event-title {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Resize handles */
|
||||
|
|
|
|||
|
|
@ -9,24 +9,89 @@ swp-calendar {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
/* Calendar container grid */
|
||||
/* 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: auto 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Time axis (left side) */
|
||||
/* Time axis (fixed, left side) */
|
||||
swp-time-axis {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
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;
|
||||
z-index: 2;
|
||||
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 {
|
||||
|
|
@ -51,66 +116,46 @@ swp-hour-marker {
|
|||
}
|
||||
}
|
||||
|
||||
/* Week header */
|
||||
swp-week-header {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--week-days, 7), 1fr);
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 3;
|
||||
}
|
||||
/* Day header styling (inside week-header) */
|
||||
|
||||
swp-day-header {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
border-right: 1px solid var(--color-grid-line);
|
||||
|
||||
&: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;
|
||||
}
|
||||
|
||||
/* Today indicator */
|
||||
&[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;
|
||||
}
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Scrollable content */
|
||||
swp-scrollable-content {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scroll-behavior: smooth;
|
||||
position: relative;
|
||||
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 */
|
||||
|
|
@ -130,19 +175,18 @@ swp-allday-container {
|
|||
/* Time grid */
|
||||
swp-time-grid {
|
||||
position: relative;
|
||||
height: calc(var(--total-hours, 12) * var(--hour-height));
|
||||
|
||||
/* Work hours background */
|
||||
&::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;
|
||||
}
|
||||
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 */
|
||||
|
|
@ -150,26 +194,39 @@ swp-grid-lines {
|
|||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
|
||||
/* 15-minute intervals */
|
||||
background-image: 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)
|
||||
);
|
||||
|
||||
/* Show stronger lines when dragging */
|
||||
&[data-dragging="true"] {
|
||||
background-image: repeating-linear-gradient(
|
||||
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),
|
||||
rgba(33, 150, 243, 0.2) calc(var(--hour-height) / 4 - 1px),
|
||||
rgba(33, 150, 243, 0.2) calc(var(--hour-height) / 4)
|
||||
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 */
|
||||
|
|
@ -177,42 +234,21 @@ swp-day-columns {
|
|||
position: absolute;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--week-days, 7), 1fr);
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
}
|
||||
|
||||
swp-day-column {
|
||||
position: relative;
|
||||
border-right: 1px solid var(--color-grid-line);
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* Hover effect for empty slots */
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
/* Events layer */
|
||||
swp-day-column:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
swp-events-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
|
||||
/* Layout modes */
|
||||
&[data-layout="overlap"] {
|
||||
swp-event {
|
||||
width: calc(100% - 16px);
|
||||
left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-layout="side-by-side"] {
|
||||
swp-event {
|
||||
width: calc(var(--event-width, 100%) - 16px);
|
||||
left: calc(8px + var(--event-offset, 0px));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Current time indicator */
|
||||
|
|
|
|||
|
|
@ -130,23 +130,27 @@ swp-loading-overlay {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: var(--z-loading);
|
||||
backdrop-filter: blur(2px);
|
||||
|
||||
&[hidden] {
|
||||
display: none;
|
||||
}
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
swp-loading-overlay[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
swp-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid var(--color-surface);
|
||||
border-top-color: var(--color-primary);
|
||||
border: 3px solid #f3f3f3;
|
||||
border-top: 3px solid var(--color-primary);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Snap indicator */
|
||||
swp-snap-indicator {
|
||||
position: absolute;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue