realtimecursor
Version:
Real-time collaboration system with cursor tracking and approval workflow
155 lines (135 loc) • 2.86 kB
CSS
/* RealtimeCursor CSS */
/* Cursor blinking animation */
@keyframes realtimecursor-blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
/* Typing indicator animation */
@keyframes realtimecursor-typing {
0%, 100% { opacity: 0.4; }
50% { opacity: 1; }
}
/* Dot animation */
@keyframes realtimecursor-bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-2px); }
}
/* Cursor styles */
.realtimecursor-cursor {
position: fixed;
z-index: 9999;
pointer-events: none;
transition: transform 75ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
will-change: transform;
}
.realtimecursor-pointer {
width: 12px;
height: 12px;
border-radius: 50%;
box-shadow: 0 0 5px rgba(0,0,0,0.3);
}
.realtimecursor-name {
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
margin-top: 4px;
white-space: nowrap;
color: #fff;
}
/* Text cursor styles */
.realtimecursor-text-cursor {
position: absolute;
z-index: 9998;
pointer-events: none;
}
.realtimecursor-caret {
width: 2px;
height: 20px;
animation: realtimecursor-blink 1s infinite;
}
.realtimecursor-flag {
position: absolute;
top: -18px;
left: -8px;
width: 18px;
height: 18px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: bold;
color: #fff;
}
/* Collaborators list styles */
.realtimecursor-collaborators {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.realtimecursor-collaborator {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 8px;
border-radius: 4px;
transition: background-color 0.2s ease;
}
.realtimecursor-collaborator.typing {
background-color: #f0f9ff;
}
.realtimecursor-avatar {
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 12px;
font-weight: bold;
}
/* Typing indicator */
.realtimecursor-typing-indicator {
display: flex;
align-items: center;
gap: 2px;
}
.realtimecursor-dot {
width: 4px;
height: 4px;
border-radius: 50%;
background-color: currentColor;
opacity: 0.7;
}
.realtimecursor-dot:nth-child(1) {
animation: realtimecursor-bounce 1s infinite 0.1s;
}
.realtimecursor-dot:nth-child(2) {
animation: realtimecursor-bounce 1s infinite 0.2s;
}
.realtimecursor-dot:nth-child(3) {
animation: realtimecursor-bounce 1s infinite 0.3s;
}
/* Textarea styles */
.realtimecursor-textarea {
width: 100%;
min-height: 200px;
padding: 16px;
font-family: monospace;
font-size: 16px;
line-height: 1.5;
border: 1px solid #e5e7eb;
border-radius: 8px;
outline: none;
resize: vertical;
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.realtimecursor-cursor,
.realtimecursor-caret,
.realtimecursor-dot {
transition: none;
animation: none;
}
}