Implements a fuzzy search filter system using Fuse.js to enhance event searching. This system allows users to quickly find events by typing partial matches of event titles or descriptions, providing visual feedback by dimming non-matching events. The filter persists during navigation and includes escape key support for quick clearing. It also includes performance optimizations like requestAnimationFrame debouncing.
207 lines
No EOL
4.2 KiB
CSS
207 lines
No EOL
4.2 KiB
CSS
/* styles/components/events.css */
|
|
|
|
/* Event base styles */
|
|
swp-event {
|
|
position: absolute;
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
cursor: pointer;
|
|
transition: box-shadow 150ms ease, transform 150ms ease;
|
|
z-index: 10;
|
|
left: 2px;
|
|
right: 2px;
|
|
color: var(--color-text);
|
|
font-size: 12px;
|
|
padding: 2px 4px;
|
|
|
|
/* Event types */
|
|
&[data-type="meeting"] {
|
|
background: var(--color-event-meeting);
|
|
border-left: 4px solid var(--color-event-meeting-border);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
&[data-type="meal"] {
|
|
background: var(--color-event-meal);
|
|
border-left: 4px solid var(--color-event-meal-border);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
&[data-type="work"] {
|
|
background: var(--color-event-work);
|
|
border-left: 4px solid var(--color-event-work-border);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
&[data-type="milestone"] {
|
|
background: var(--color-event-milestone);
|
|
border-left: 4px solid var(--color-event-milestone-border);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
&[data-type="personal"] {
|
|
background: var(--color-event-personal);
|
|
border-left: 4px solid var(--color-event-personal-border);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
&[data-type="deadline"] {
|
|
background: var(--color-event-milestone);
|
|
border-left: 4px solid var(--color-event-milestone-border);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
}
|
|
|
|
swp-event:hover {
|
|
box-shadow: var(--shadow-md);
|
|
transform: translateX(2px);
|
|
z-index: 20;
|
|
}
|
|
|
|
swp-event-time {
|
|
display: block;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
swp-event-title {
|
|
display: block;
|
|
font-size: 0.875rem;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
/* Resize handles */
|
|
swp-resize-handle {
|
|
position: absolute;
|
|
left: 8px;
|
|
right: 8px;
|
|
height: 4px;
|
|
opacity: 0;
|
|
transition: opacity var(--transition-fast);
|
|
|
|
/* The two lines */
|
|
&::before,
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
height: 1px;
|
|
background: rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
&::before {
|
|
top: 0;
|
|
}
|
|
|
|
&::after {
|
|
bottom: 0;
|
|
}
|
|
|
|
/* Hit area */
|
|
swp-handle-hitarea {
|
|
position: absolute;
|
|
left: -8px;
|
|
right: -8px;
|
|
top: -6px;
|
|
bottom: -6px;
|
|
cursor: ns-resize;
|
|
}
|
|
|
|
&[data-position="top"] {
|
|
top: 4px;
|
|
}
|
|
|
|
&[data-position="bottom"] {
|
|
bottom: 4px;
|
|
}
|
|
}
|
|
|
|
/* Multi-day events */
|
|
swp-multi-day-event {
|
|
position: relative;
|
|
height: 28px;
|
|
margin: 2px 4px;
|
|
padding: 0 8px;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all var(--transition-fast);
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
|
|
/* Event type colors */
|
|
&[data-type="milestone"] {
|
|
background: var(--color-event-milestone);
|
|
color: var(--color-event-milestone-border);
|
|
}
|
|
|
|
/* Continuation indicators */
|
|
&[data-continues-before="true"] {
|
|
border-top-left-radius: 0;
|
|
border-bottom-left-radius: 0;
|
|
margin-left: 0;
|
|
padding-left: 20px;
|
|
|
|
&::before {
|
|
content: '◀';
|
|
position: absolute;
|
|
left: 4px;
|
|
opacity: 0.6;
|
|
font-size: 0.75rem;
|
|
}
|
|
}
|
|
|
|
&[data-continues-after="true"] {
|
|
border-top-right-radius: 0;
|
|
border-bottom-right-radius: 0;
|
|
margin-right: 0;
|
|
padding-right: 20px;
|
|
|
|
&::after {
|
|
content: '▶';
|
|
position: absolute;
|
|
right: 4px;
|
|
opacity: 0.6;
|
|
font-size: 0.75rem;
|
|
}
|
|
}
|
|
|
|
&:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
}
|
|
|
|
/* Event creation preview */
|
|
swp-event-preview {
|
|
position: absolute;
|
|
left: 8px;
|
|
right: 8px;
|
|
background: rgba(33, 150, 243, 0.1);
|
|
border: 2px dashed var(--color-primary);
|
|
border-radius: 4px;
|
|
pointer-events: none;
|
|
|
|
/* Position via CSS variables */
|
|
top: calc(var(--preview-start) * var(--minute-height));
|
|
height: calc(var(--preview-duration) * var(--minute-height));
|
|
}
|
|
|
|
/* Event filtering styles */
|
|
/* When filter is active, all events are dimmed by default */
|
|
swp-events-layer[data-filter-active="true"] swp-event {
|
|
opacity: 0.2;
|
|
transition: opacity 200ms ease;
|
|
}
|
|
|
|
/* Events that match the filter stay normal */
|
|
swp-events-layer[data-filter-active="true"] swp-event[data-matches="true"] {
|
|
opacity: 1;
|
|
} |