@nestjsvn/swagger-sse
Version:
OpenAPI documentation and interactive Swagger UI for NestJS Server-Sent Events endpoints
493 lines (427 loc) • 9.38 kB
CSS
/**
* Component-specific styles for SSE Plugin
* Styles for individual UI components
*/
/* Event Filter Component */
.sse-event-filter {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.sse-filter-row {
display: flex;
gap: 0.75rem;
align-items: flex-end;
flex-wrap: wrap;
}
.sse-search-input {
flex: 1;
min-width: 200px;
position: relative;
}
.sse-search-input input {
width: 100%;
padding: 0.5rem 2.5rem 0.5rem 0.75rem;
border: 1px solid var(--sse-border-color);
border-radius: var(--sse-border-radius);
background-color: var(--sse-bg-color);
color: var(--sse-text-color);
font-size: 0.875rem;
transition: all 0.2s ease;
}
.sse-search-input input:focus {
outline: none;
border-color: var(--sse-primary-color);
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
.sse-search-clear {
position: absolute;
right: 0.5rem;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: var(--sse-text-color);
cursor: pointer;
padding: 0.25rem;
opacity: 0.6;
transition: opacity 0.2s ease;
}
.sse-search-clear:hover {
opacity: 1;
}
.sse-type-filter select {
padding: 0.5rem;
border: 1px solid var(--sse-border-color);
border-radius: var(--sse-border-radius);
background-color: var(--sse-bg-color);
color: var(--sse-text-color);
font-size: 0.875rem;
min-width: 120px;
}
.sse-status-filter {
display: flex;
gap: 0.5rem;
}
.sse-status-chip {
padding: 0.25rem 0.5rem;
border: 1px solid var(--sse-border-color);
border-radius: 1rem;
background-color: var(--sse-bg-color);
color: var(--sse-text-color);
font-size: 0.75rem;
cursor: pointer;
transition: all 0.2s ease;
user-select: none;
}
.sse-status-chip:hover {
background-color: var(--sse-light-color);
}
.sse-status-chip.active {
background-color: var(--sse-primary-color);
color: white;
border-color: var(--sse-primary-color);
}
.sse-filter-stats {
font-size: 0.75rem;
color: var(--sse-text-color);
opacity: 0.7;
margin-top: 0.5rem;
}
/* Event List Component */
.sse-event-list {
position: relative;
height: 100%;
}
.sse-virtual-list {
height: 400px;
overflow-y: auto;
position: relative;
border: 1px solid var(--sse-border-color);
border-radius: var(--sse-border-radius);
}
.sse-virtual-list-inner {
position: relative;
}
.sse-virtual-item {
position: absolute;
left: 0;
right: 0;
transition: transform 0.1s ease;
}
.sse-event-batch-indicator {
position: sticky;
top: 0;
background-color: var(--sse-warning-color);
color: white;
padding: 0.5rem;
text-align: center;
font-size: 0.75rem;
font-weight: 500;
z-index: 10;
animation: slideDown 0.3s ease;
}
.sse-no-events {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 200px;
color: var(--sse-text-color);
opacity: 0.6;
text-align: center;
}
.sse-no-events-icon {
font-size: 3rem;
margin-bottom: 1rem;
opacity: 0.3;
}
.sse-event-item-detailed {
padding: 1rem;
border-bottom: 1px solid var(--sse-border-color);
transition: all 0.2s ease;
cursor: pointer;
position: relative;
}
.sse-event-item-detailed:hover {
background-color: var(--sse-light-color);
transform: translateX(2px);
}
.sse-event-item-detailed.selected {
background-color: rgba(0, 123, 255, 0.1);
border-left: 3px solid var(--sse-primary-color);
}
.sse-event-meta {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 0.75rem;
}
.sse-event-type-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.25rem 0.5rem;
background-color: var(--sse-primary-color);
color: white;
border-radius: var(--sse-border-radius);
font-size: 0.75rem;
font-weight: 500;
}
.sse-event-id {
font-family: var(--sse-mono-font);
font-size: 0.75rem;
color: var(--sse-text-color);
opacity: 0.6;
}
.sse-event-time-info {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 0.25rem;
font-size: 0.75rem;
color: var(--sse-text-color);
opacity: 0.7;
}
.sse-event-preview {
background-color: var(--sse-light-color);
padding: 0.75rem;
border-radius: var(--sse-border-radius);
font-family: var(--sse-mono-font);
font-size: 0.8125rem;
max-height: 100px;
overflow: hidden;
position: relative;
transition: max-height 0.3s ease;
}
.sse-event-preview.expanded {
max-height: none;
}
.sse-event-preview-fade {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 20px;
background: linear-gradient(transparent, var(--sse-light-color));
pointer-events: none;
}
.sse-event-preview.expanded .sse-event-preview-fade {
display: none;
}
.sse-event-actions {
display: flex;
gap: 0.5rem;
margin-top: 0.75rem;
opacity: 0;
transition: opacity 0.2s ease;
}
.sse-event-item-detailed:hover .sse-event-actions {
opacity: 1;
}
.sse-event-action-btn {
padding: 0.25rem 0.5rem;
border: 1px solid var(--sse-border-color);
border-radius: var(--sse-border-radius);
background-color: var(--sse-bg-color);
color: var(--sse-text-color);
font-size: 0.75rem;
cursor: pointer;
transition: all 0.2s ease;
}
.sse-event-action-btn:hover {
background-color: var(--sse-light-color);
transform: translateY(-1px);
}
/* Connection Status Component */
.sse-connection-status {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.75rem;
background-color: var(--sse-light-color);
border-radius: var(--sse-border-radius);
border: 1px solid var(--sse-border-color);
}
.sse-status-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
}
.sse-status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
position: relative;
transition: all 0.3s ease;
}
.sse-status-dot::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
opacity: 0.6;
transform: scale(1);
}
.sse-status-dot.connected {
background-color: var(--sse-success-color);
}
.sse-status-dot.connected::after {
background-color: var(--sse-success-color);
animation: ripple 2s infinite;
}
.sse-status-dot.connecting {
background-color: var(--sse-warning-color);
}
.sse-status-dot.connecting::after {
background-color: var(--sse-warning-color);
animation: pulse 1s infinite;
}
.sse-status-dot.disconnected {
background-color: var(--sse-danger-color);
opacity: 0.5;
}
.sse-status-dot.error {
background-color: var(--sse-danger-color);
}
.sse-status-dot.error::after {
background-color: var(--sse-danger-color);
animation: shake 0.5s infinite;
}
.sse-status-text {
font-weight: 500;
font-size: 0.875rem;
text-transform: capitalize;
}
.sse-connection-info {
display: flex;
gap: 1rem;
margin-left: auto;
font-size: 0.75rem;
color: var(--sse-text-color);
opacity: 0.8;
}
.sse-connection-stat {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.25rem;
}
.sse-connection-stat-value {
font-weight: 600;
color: var(--sse-primary-color);
font-size: 0.875rem;
}
.sse-connection-stat-label {
text-transform: uppercase;
letter-spacing: 0.05em;
opacity: 0.7;
}
.sse-reconnect-btn {
padding: 0.5rem 0.75rem;
background-color: var(--sse-primary-color);
color: white;
border: none;
border-radius: var(--sse-border-radius);
font-size: 0.75rem;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 0.25rem;
}
.sse-reconnect-btn:hover {
background-color: #0056b3;
transform: translateY(-1px);
}
.sse-reconnect-btn:disabled {
background-color: #6c757d;
cursor: not-allowed;
transform: none;
}
.sse-error-message {
margin-top: 0.5rem;
padding: 0.5rem;
background-color: rgba(220, 53, 69, 0.1);
border: 1px solid rgba(220, 53, 69, 0.2);
border-radius: var(--sse-border-radius);
color: var(--sse-danger-color);
font-size: 0.75rem;
font-family: var(--sse-mono-font);
}
/* Performance Indicators */
.sse-performance-indicator {
position: absolute;
top: 0.5rem;
right: 0.5rem;
padding: 0.25rem 0.5rem;
background-color: rgba(0, 0, 0, 0.8);
color: white;
border-radius: var(--sse-border-radius);
font-size: 0.75rem;
font-family: var(--sse-mono-font);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.sse-event-list:hover .sse-performance-indicator {
opacity: 1;
}
.sse-batch-processing {
background-color: var(--sse-warning-color);
color: white;
padding: 0.5rem;
text-align: center;
font-size: 0.75rem;
font-weight: 500;
animation: slideDown 0.3s ease;
}
/* Animations */
@keyframes ripple {
0% {
transform: scale(1);
opacity: 0.6;
}
100% {
transform: scale(2);
opacity: 0;
}
}
@keyframes slideDown {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Responsive adjustments */
@media (max-width: 768px) {
.sse-filter-row {
flex-direction: column;
align-items: stretch;
}
.sse-search-input {
min-width: auto;
}
.sse-connection-status {
flex-direction: column;
gap: 0.75rem;
}
.sse-connection-info {
margin-left: 0;
justify-content: space-around;
}
.sse-event-meta {
flex-direction: column;
gap: 0.5rem;
}
.sse-event-time-info {
align-items: flex-start;
}
}