Enables event resizing via drag handles

Adds a resize handle manager to handle mouse hover
effects on calendar events and display a resize indicator.

This allows users to visually identify and initiate
event resizing by hovering near the bottom edge of an event.
This commit is contained in:
Janus C. H. Knudsen 2025-10-06 23:38:01 +02:00
parent 7d7a8d9208
commit a9819a8bf1
4 changed files with 130 additions and 61 deletions

View file

@ -70,6 +70,35 @@ swp-day-columns swp-event:hover {
z-index: 20;
}
/* Resize handle indicator - created by JavaScript */
swp-resize-indicator {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 15px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="4"><rect x="0" y="0" width="16" height="1" fill="%23666"/><rect x="0" y="3" width="16" height="1" fill="%23666"/></svg>');
background-position: center center;
background-repeat: no-repeat;
pointer-events: none;
z-index: 10;
opacity: 0;
animation: fadeIn 0.8s ease forwards;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
swp-day-columns swp-event[data-resize-hover="true"] {
cursor: ns-resize;
}
swp-day-columns swp-event-time {
display: block;
font-size: 0.875rem;
@ -83,64 +112,6 @@ swp-day-columns swp-event-title {
line-height: 1.3;
}
/* External resize handles */
swp-resize-handle {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 24px;
height: 4px;
opacity: 0;
transition: opacity var(--transition-fast);
cursor: ns-resize;
z-index: 30;
background: var(--color-primary);
border-radius: 3px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
/* Subtle grip pattern */
&::before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 12px;
height: 1px;
background: rgba(255, 255, 255, 0.6);
border-radius: 0.5px;
box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.3);
}
}
/* Top resize handle - positioned OUTSIDE event */
swp-resize-handle[data-position="top"] {
top: -6px;
}
/* Bottom resize handle - positioned OUTSIDE event */
swp-resize-handle[data-position="bottom"] {
bottom: -6px;
}
/* Resize handles controlled by JavaScript - no general hover */
swp-handle-hitarea {
position: absolute;
left: -8px;
right: -8px;
top: -6px;
bottom: -6px;
cursor: ns-resize;
}
swp-handle-hitarea[data-position="top"] {
top: 4px;
}
swp-handle-hitarea[data-position="bottom"] {
bottom: 4px;
}
/* Multi-day events */
swp-multi-day-event {
position: relative;