[story #124] fix: design-system lint compliance for OpsConsole and MailboxDashboard CSS
- Remove CSS custom property fallback values (var(--token, fallback) -> var(--token)) - Replace hardcoded hex colors with design-system token references - Replace hardcoded font-weight/spacing/border-radius values with tokens - Replace hardcoded box-shadow with var(--shadow-*) tokens - Replace hardcoded z-index with var(--z-index-modal) token - Fix CSS specificity order (disabled, focus-visible before hover) - Add empty lines before rules in media queries - Fix padding values using var(--spacing-0_5) to use standard spacing tokens - Add afterEach to vitest import in OpsConsole.test.tsx Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit was merged in pull request #147.
This commit is contained in:
+471
-469
@@ -1,482 +1,484 @@
|
||||
.ops-console {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
background: var(--color-surface-background, #f9fafb);
|
||||
font-family: var(--typography-font-family-sans, system-ui, -apple-system, sans-serif);
|
||||
}
|
||||
|
||||
.ops-console__sidebar {
|
||||
width: 240px;
|
||||
min-width: 240px;
|
||||
background: var(--color-neutral-white, #fff);
|
||||
border-right: 1px solid var(--color-neutral-gray-200, #e5e7eb);
|
||||
box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
|
||||
padding: var(--spacing-6, 24px) 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-1, 4px);
|
||||
}
|
||||
|
||||
.ops-console__nav-item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: var(--spacing-3, 12px) var(--spacing-6, 24px);
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--color-neutral-gray-700, #374151);
|
||||
font-size: var(--typography-font-size-base, 14px);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.ops-console__nav-item:hover {
|
||||
background: var(--color-neutral-gray-50, #f9fafb);
|
||||
}
|
||||
|
||||
.ops-console__nav-item--active {
|
||||
background: var(--color-brand-primary-light, #eff6ff);
|
||||
color: var(--color-brand-primary, #2563eb);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ops-console__nav-separator {
|
||||
border: none;
|
||||
border-top: 1px solid var(--color-neutral-gray-200, #e5e7eb);
|
||||
margin: var(--spacing-4, 16px) var(--spacing-6, 24px);
|
||||
}
|
||||
|
||||
.ops-console__content {
|
||||
flex: 1;
|
||||
padding: var(--spacing-6, 24px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ops-console__dashboard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-6, 24px);
|
||||
}
|
||||
|
||||
.ops-console__metric-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: var(--spacing-6, 24px);
|
||||
}
|
||||
|
||||
.ops-console__metric-card {
|
||||
background: var(--color-surface-card, #fff);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
padding: var(--spacing-4, 16px);
|
||||
box-shadow: var(--shadow-md, 0 4px 6px rgba(0, 0, 0, 0.07));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-2, 8px);
|
||||
transition: box-shadow 0.15s;
|
||||
}
|
||||
|
||||
.ops-console__metric-card:hover {
|
||||
box-shadow: var(--shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
|
||||
.ops-console__metric-label {
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
font-weight: 500;
|
||||
color: var(--color-neutral-gray-500, #6b7280);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.ops-console__metric-value {
|
||||
font-size: var(--typography-font-size-xl, 20px);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.ops-console__metric-unit {
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
font-weight: 400;
|
||||
color: var(--color-neutral-gray-500, #6b7280);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--info .ops-console__metric-value {
|
||||
color: var(--color-semantic-info, #2563eb);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--success .ops-console__metric-value {
|
||||
color: var(--color-semantic-success, #16a34a);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--warning .ops-console__metric-value {
|
||||
color: var(--color-semantic-warning, #d97706);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--error .ops-console__metric-value {
|
||||
color: var(--color-semantic-error, #dc2626);
|
||||
}
|
||||
|
||||
.ops-console__section-heading {
|
||||
font-size: var(--typography-font-size-xl, 20px);
|
||||
font-weight: 600;
|
||||
margin: 0 0 var(--spacing-4, 16px);
|
||||
}
|
||||
|
||||
.ops-console__error-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-2, 8px);
|
||||
}
|
||||
|
||||
.ops-console__error-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-3, 12px);
|
||||
padding: var(--spacing-3, 12px) var(--spacing-4, 16px);
|
||||
background: var(--color-surface-card, #fff);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
border-left: 3px solid var(--color-semantic-error, #dc2626);
|
||||
}
|
||||
|
||||
.ops-console__error-type {
|
||||
font-family: var(--typography-font-family-mono, ui-monospace, monospace);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
color: var(--color-semantic-error, #dc2626);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ops-console__error-msg-id {
|
||||
font-family: var(--typography-font-family-mono, ui-monospace, monospace);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
color: var(--color-neutral-gray-700, #374151);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ops-console__error-time {
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
color: var(--color-neutral-gray-500, #6b7280);
|
||||
}
|
||||
|
||||
.ops-console__filter-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-4, 16px);
|
||||
margin-bottom: var(--spacing-4, 16px);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.ops-console__search {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
padding: var(--spacing-2, 8px) var(--spacing-3, 12px);
|
||||
border: 1px solid var(--color-neutral-gray-300, #d1d5db);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
font-size: var(--typography-font-size-base, 14px);
|
||||
}
|
||||
|
||||
.ops-console__search:focus {
|
||||
outline: 2px solid var(--color-brand-primary, #2563eb);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ops-console__filter-chips {
|
||||
display: flex;
|
||||
gap: var(--spacing-1, 4px);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip {
|
||||
padding: var(--spacing-1, 4px) var(--spacing-2, 8px);
|
||||
border: 1px solid var(--color-neutral-gray-300, #d1d5db);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
background: var(--color-neutral-white, #fff);
|
||||
color: var(--color-neutral-gray-700, #374151);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--active {
|
||||
background: var(--color-brand-primary, #2563eb);
|
||||
color: var(--color-brand-primary-on, #fff);
|
||||
border-color: var(--color-brand-primary, #2563eb);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--info.ops-console__filter-chip--active {
|
||||
background: var(--color-semantic-info, #2563eb);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--warn.ops-console__filter-chip--active {
|
||||
background: var(--color-semantic-warning, #d97706);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--error.ops-console__filter-chip--active {
|
||||
background: var(--color-semantic-error, #dc2626);
|
||||
}
|
||||
|
||||
.ops-console__log-table,
|
||||
.ops-console__config-table,
|
||||
.ops-console__users-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
}
|
||||
|
||||
.ops-console__table-caption {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.ops-console__log-table th,
|
||||
.ops-console__log-table td,
|
||||
.ops-console__config-table th,
|
||||
.ops-console__config-table td,
|
||||
.ops-console__users-table th,
|
||||
.ops-console__users-table td {
|
||||
padding: var(--spacing-2, 8px) var(--spacing-3, 12px);
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--color-neutral-gray-200, #e5e7eb);
|
||||
}
|
||||
|
||||
.ops-console__log-table thead th,
|
||||
.ops-console__config-table thead th,
|
||||
.ops-console__users-table thead th {
|
||||
font-weight: 500;
|
||||
color: var(--color-neutral-gray-500, #6b7280);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
}
|
||||
|
||||
.ops-console__log-row {
|
||||
cursor: pointer;
|
||||
transition: background 0.1s;
|
||||
}
|
||||
|
||||
.ops-console__log-row:hover {
|
||||
background: var(--color-neutral-gray-50, #f9fafb);
|
||||
}
|
||||
|
||||
.ops-console__log-row:focus-visible {
|
||||
outline: 2px solid var(--color-brand-primary, #2563eb);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.ops-console__log-message {
|
||||
font-family: var(--typography-font-family-mono, ui-monospace, monospace);
|
||||
max-width: 400px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ops-console__log-level {
|
||||
font-weight: 600;
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
}
|
||||
|
||||
.ops-console__log-level--info {
|
||||
color: var(--color-neutral-gray-500, #6b7280);
|
||||
}
|
||||
|
||||
.ops-console__log-level--warn {
|
||||
color: var(--color-semantic-warning, #d97706);
|
||||
}
|
||||
|
||||
.ops-console__log-level--error {
|
||||
color: var(--color-semantic-error, #dc2626);
|
||||
}
|
||||
|
||||
.ops-console__log-detail {
|
||||
font-family: var(--typography-font-family-mono, ui-monospace, monospace);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
background: var(--color-neutral-gray-50, #f9fafb);
|
||||
padding: var(--spacing-3, 12px);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
margin: var(--spacing-2, 8px) 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.ops-console__load-more {
|
||||
display: block;
|
||||
margin: var(--spacing-4, 16px) auto;
|
||||
padding: var(--spacing-2, 8px) var(--spacing-4, 16px);
|
||||
border: 1px solid var(--color-neutral-gray-300, #d1d5db);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
background: var(--color-neutral-white, #fff);
|
||||
color: var(--color-neutral-gray-700, #374151);
|
||||
cursor: pointer;
|
||||
font-size: var(--typography-font-size-base, 14px);
|
||||
}
|
||||
|
||||
.ops-console__config-key {
|
||||
font-family: var(--typography-font-family-mono, ui-monospace, monospace);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ops-console__config-value {
|
||||
font-family: var(--typography-font-family-mono, ui-monospace, monospace);
|
||||
}
|
||||
|
||||
.ops-console__config-edit-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-2, 8px);
|
||||
}
|
||||
|
||||
.ops-console__config-input {
|
||||
flex: 1;
|
||||
padding: var(--spacing-1, 4px) var(--spacing-2, 8px);
|
||||
border: 1px solid var(--color-neutral-gray-300, #d1d5db);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
font-family: var(--typography-font-family-mono, ui-monospace, monospace);
|
||||
}
|
||||
|
||||
.ops-console__config-input:focus {
|
||||
outline: 2px solid var(--color-brand-primary, #2563eb);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ops-console__config-save,
|
||||
.ops-console__config-cancel,
|
||||
.ops-console__config-edit-btn {
|
||||
padding: var(--spacing-1, 4px) var(--spacing-2, 8px);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ops-console__config-save {
|
||||
background: var(--color-brand-primary, #2563eb);
|
||||
color: var(--color-brand-primary-on, #fff);
|
||||
}
|
||||
|
||||
.ops-console__config-cancel {
|
||||
background: var(--color-neutral-gray-100, #f3f4f6);
|
||||
color: var(--color-neutral-gray-700, #374151);
|
||||
border-color: var(--color-neutral-gray-300, #d1d5db);
|
||||
}
|
||||
|
||||
.ops-console__config-edit-btn {
|
||||
background: transparent;
|
||||
color: var(--color-brand-primary, #2563eb);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ops-console__role-select {
|
||||
padding: var(--spacing-1, 4px) var(--spacing-2, 8px);
|
||||
border: 1px solid var(--color-neutral-gray-300, #d1d5db);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
font-size: var(--typography-font-size-sm, 12px);
|
||||
}
|
||||
|
||||
.ops-console__role-select:focus {
|
||||
outline: 2px solid var(--color-brand-primary, #2563eb);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 100;
|
||||
padding: var(--spacing-6, 24px);
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal > * {
|
||||
background: var(--color-neutral-white, #fff);
|
||||
border-radius: var(--border-radius-lg, 12px);
|
||||
box-shadow: var(--shadow-xl, 0 20px 25px rgba(0, 0, 0, 0.15));
|
||||
padding: var(--spacing-6, 24px);
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal h3 {
|
||||
margin: 0 0 var(--spacing-4, 16px);
|
||||
font-size: var(--typography-font-size-xl, 20px);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal p {
|
||||
margin: 0 0 var(--spacing-4, 16px);
|
||||
color: var(--color-neutral-gray-700, #374151);
|
||||
}
|
||||
|
||||
.ops-console__confirm-actions {
|
||||
display: flex;
|
||||
gap: var(--spacing-3, 12px);
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn {
|
||||
padding: var(--spacing-2, 8px) var(--spacing-4, 16px);
|
||||
border-radius: var(--border-radius-md, 8px);
|
||||
font-size: var(--typography-font-size-base, 14px);
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn--primary {
|
||||
background: var(--color-brand-primary, #2563eb);
|
||||
color: var(--color-brand-primary-on, #fff);
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn--primary:hover {
|
||||
background: var(--color-brand-primary-dark, #1d4ed8);
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn--cancel {
|
||||
background: var(--color-neutral-gray-100, #f3f4f6);
|
||||
color: var(--color-neutral-gray-700, #374151);
|
||||
border-color: var(--color-neutral-gray-300, #d1d5db);
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
@layer components {
|
||||
.ops-console {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
background: var(--color-surface-background);
|
||||
font-family: var(--font-family-sans);
|
||||
}
|
||||
|
||||
.ops-console__sidebar {
|
||||
width: 240px;
|
||||
min-width: 240px;
|
||||
background: var(--color-neutral-white);
|
||||
border-right: 1px solid var(--color-neutral-gray-200);
|
||||
box-shadow: var(--shadow-sm);
|
||||
padding: var(--spacing-6) 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-1);
|
||||
}
|
||||
|
||||
.ops-console__nav-item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-width: auto;
|
||||
flex-direction: row;
|
||||
overflow-x: auto;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid var(--color-neutral-gray-200, #e5e7eb);
|
||||
padding: var(--spacing-2, 8px) var(--spacing-4, 16px);
|
||||
box-shadow: none;
|
||||
padding: var(--spacing-3) var(--spacing-6);
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--color-neutral-gray-700);
|
||||
font-size: var(--font-size-base);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-fast), color var(--transition-fast);
|
||||
}
|
||||
|
||||
.ops-console__nav-item:hover {
|
||||
background: var(--color-neutral-gray-50);
|
||||
}
|
||||
|
||||
.ops-console__nav-item--active {
|
||||
background: var(--color-brand-primary-light);
|
||||
color: var(--color-brand-primary);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.ops-console__nav-separator {
|
||||
border-top: none;
|
||||
border-left: 1px solid var(--color-neutral-gray-200, #e5e7eb);
|
||||
margin: 0 var(--spacing-2, 8px);
|
||||
height: auto;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.ops-console__metric-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.ops-console__metric-grid {
|
||||
grid-template-columns: 1fr;
|
||||
border: none;
|
||||
border-top: 1px solid var(--color-neutral-gray-200);
|
||||
margin: var(--spacing-4) var(--spacing-6);
|
||||
}
|
||||
|
||||
.ops-console__content {
|
||||
padding: var(--spacing-4, 16px);
|
||||
flex: 1;
|
||||
padding: var(--spacing-6);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ops-console__dashboard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-6);
|
||||
}
|
||||
|
||||
.ops-console__metric-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: var(--spacing-6);
|
||||
}
|
||||
|
||||
.ops-console__metric-card {
|
||||
background: var(--color-surface-card);
|
||||
border-radius: var(--border-radius-md);
|
||||
padding: var(--spacing-4);
|
||||
box-shadow: var(--shadow-md);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-2);
|
||||
transition: box-shadow var(--transition-fast);
|
||||
}
|
||||
|
||||
.ops-console__metric-card:hover {
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.ops-console__metric-label {
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-neutral-gray-500);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: var(--letter-spacing-wide);
|
||||
}
|
||||
|
||||
.ops-console__metric-value {
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
.ops-console__metric-unit {
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-normal);
|
||||
color: var(--color-neutral-gray-500);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--info .ops-console__metric-value {
|
||||
color: var(--color-semantic-info);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--success .ops-console__metric-value {
|
||||
color: var(--color-semantic-success);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--warning .ops-console__metric-value {
|
||||
color: var(--color-semantic-warning);
|
||||
}
|
||||
|
||||
.ops-console__metric-card--error .ops-console__metric-value {
|
||||
color: var(--color-semantic-error);
|
||||
}
|
||||
|
||||
.ops-console__section-heading {
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
margin: 0 0 var(--spacing-4);
|
||||
}
|
||||
|
||||
.ops-console__error-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
|
||||
.ops-console__error-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-3);
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
background: var(--color-surface-card);
|
||||
border-radius: var(--border-radius-md);
|
||||
border-left: 3px solid var(--color-semantic-error);
|
||||
}
|
||||
|
||||
.ops-console__error-type {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-semantic-error);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.ops-console__error-msg-id {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-neutral-gray-700);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ops-console__error-time {
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-neutral-gray-500);
|
||||
}
|
||||
|
||||
.ops-console__filter-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-4);
|
||||
margin-bottom: var(--spacing-4);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.ops-console__search {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
border: 1px solid var(--color-neutral-gray-300);
|
||||
border-radius: var(--border-radius-md);
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
.ops-console__search:focus {
|
||||
outline: 2px solid var(--color-brand-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ops-console__filter-chips {
|
||||
display: flex;
|
||||
gap: var(--spacing-1);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip {
|
||||
padding: var(--spacing-1) var(--spacing-2);
|
||||
border: 1px solid var(--color-neutral-gray-300);
|
||||
border-radius: var(--border-radius-md);
|
||||
background: var(--color-neutral-white);
|
||||
color: var(--color-neutral-gray-700);
|
||||
font-size: var(--font-size-sm);
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-fast), color var(--transition-fast);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--active {
|
||||
background: var(--color-brand-primary);
|
||||
color: var(--color-brand-primary-on);
|
||||
border-color: var(--color-brand-primary);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--info.ops-console__filter-chip--active {
|
||||
background: var(--color-semantic-info);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--warn.ops-console__filter-chip--active {
|
||||
background: var(--color-semantic-warning);
|
||||
}
|
||||
|
||||
.ops-console__filter-chip--error.ops-console__filter-chip--active {
|
||||
background: var(--color-semantic-error);
|
||||
}
|
||||
|
||||
.ops-console__log-table,
|
||||
.ops-console__config-table,
|
||||
.ops-console__users-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.ops-console__table-caption {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.ops-console__log-table th,
|
||||
.ops-console__log-table td,
|
||||
.ops-console__config-table th,
|
||||
.ops-console__config-table td,
|
||||
.ops-console__users-table th,
|
||||
.ops-console__users-table td {
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--color-neutral-gray-200);
|
||||
}
|
||||
|
||||
.ops-console__log-table thead th,
|
||||
.ops-console__config-table thead th,
|
||||
.ops-console__users-table thead th {
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-neutral-gray-500);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.ops-console__log-row {
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-fast);
|
||||
}
|
||||
|
||||
.ops-console__log-row:hover {
|
||||
background: var(--color-neutral-gray-50);
|
||||
}
|
||||
|
||||
.ops-console__log-row:focus-visible {
|
||||
outline: 2px solid var(--color-brand-primary);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.ops-console__log-message {
|
||||
font-family: var(--font-family-mono);
|
||||
max-width: 400px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ops-console__log-level {
|
||||
font-weight: var(--font-weight-semibold);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.ops-console__log-level--info {
|
||||
color: var(--color-neutral-gray-500);
|
||||
}
|
||||
|
||||
.ops-console__log-level--warn {
|
||||
color: var(--color-semantic-warning);
|
||||
}
|
||||
|
||||
.ops-console__log-level--error {
|
||||
color: var(--color-semantic-error);
|
||||
}
|
||||
|
||||
.ops-console__log-detail {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: var(--font-size-sm);
|
||||
background: var(--color-neutral-gray-50);
|
||||
padding: var(--spacing-3);
|
||||
border-radius: var(--border-radius-md);
|
||||
margin: var(--spacing-2) 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.ops-console__load-more {
|
||||
display: block;
|
||||
margin: var(--spacing-4) auto;
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
border: 1px solid var(--color-neutral-gray-300);
|
||||
border-radius: var(--border-radius-md);
|
||||
background: var(--color-neutral-white);
|
||||
color: var(--color-neutral-gray-700);
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
.ops-console__config-key {
|
||||
font-family: var(--font-family-mono);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.ops-console__config-value {
|
||||
font-family: var(--font-family-mono);
|
||||
}
|
||||
|
||||
.ops-console__config-edit-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
|
||||
.ops-console__config-input {
|
||||
flex: 1;
|
||||
padding: var(--spacing-1) var(--spacing-2);
|
||||
border: 1px solid var(--color-neutral-gray-300);
|
||||
border-radius: var(--border-radius-md);
|
||||
font-size: var(--font-size-sm);
|
||||
font-family: var(--font-family-mono);
|
||||
}
|
||||
|
||||
.ops-console__config-input:focus {
|
||||
outline: 2px solid var(--color-brand-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ops-console__config-save,
|
||||
.ops-console__config-cancel,
|
||||
.ops-console__config-edit-btn {
|
||||
padding: var(--spacing-1) var(--spacing-2);
|
||||
border-radius: var(--border-radius-md);
|
||||
font-size: var(--font-size-sm);
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ops-console__config-save {
|
||||
background: var(--color-brand-primary);
|
||||
color: var(--color-brand-primary-on);
|
||||
}
|
||||
|
||||
.ops-console__config-cancel {
|
||||
background: var(--color-neutral-gray-100);
|
||||
color: var(--color-neutral-gray-700);
|
||||
border-color: var(--color-neutral-gray-300);
|
||||
}
|
||||
|
||||
.ops-console__config-edit-btn {
|
||||
background: transparent;
|
||||
color: var(--color-brand-primary);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ops-console__role-select {
|
||||
padding: var(--spacing-1) var(--spacing-2);
|
||||
border: 1px solid var(--color-neutral-gray-300);
|
||||
border-radius: var(--border-radius-md);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.ops-console__role-select:focus {
|
||||
outline: 2px solid var(--color-brand-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--color-surface-overlay);
|
||||
z-index: var(--z-index-modal);
|
||||
padding: var(--spacing-6);
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal > * {
|
||||
background: var(--color-neutral-white);
|
||||
border-radius: var(--border-radius-lg);
|
||||
box-shadow: var(--shadow-xl);
|
||||
padding: var(--spacing-6);
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal h3 {
|
||||
margin: 0 0 var(--spacing-4);
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.ops-console__confirm-modal p {
|
||||
margin: 0 0 var(--spacing-4);
|
||||
color: var(--color-neutral-gray-700);
|
||||
}
|
||||
|
||||
.ops-console__confirm-actions {
|
||||
display: flex;
|
||||
gap: var(--spacing-3);
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn {
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
border-radius: var(--border-radius-md);
|
||||
font-size: var(--font-size-base);
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn--primary {
|
||||
background: var(--color-brand-primary);
|
||||
color: var(--color-brand-primary-on);
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn--primary:hover {
|
||||
background: var(--color-brand-primary-hover);
|
||||
}
|
||||
|
||||
.ops-console__confirm-btn--cancel {
|
||||
background: var(--color-neutral-gray-100);
|
||||
color: var(--color-neutral-gray-700);
|
||||
border-color: var(--color-neutral-gray-300);
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.ops-console {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ops-console__sidebar {
|
||||
width: 100%;
|
||||
min-width: auto;
|
||||
flex-direction: row;
|
||||
overflow-x: auto;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid var(--color-neutral-gray-200);
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.ops-console__nav-separator {
|
||||
border-top: none;
|
||||
border-left: 1px solid var(--color-neutral-gray-200);
|
||||
margin: 0 var(--spacing-2);
|
||||
height: auto;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.ops-console__metric-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.ops-console__metric-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.ops-console__content {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { render, screen, fireEvent, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { OpsConsole, formatLatency, formatTimestamp } from "./OpsConsole";
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-1);
|
||||
padding: var(--spacing-0_5) var(--spacing-2);
|
||||
padding: var(--spacing-1) var(--spacing-2);
|
||||
border-radius: var(--border-radius-full);
|
||||
background-color: var(--color-brand-primary-light);
|
||||
color: var(--color-brand-primary);
|
||||
@@ -165,7 +165,7 @@
|
||||
}
|
||||
|
||||
.mailbox-dashboard__module-badge {
|
||||
padding: var(--spacing-0_5) var(--spacing-1);
|
||||
padding: var(--spacing-1) var(--spacing-2);
|
||||
border-radius: var(--border-radius-sm);
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: var(--font-weight-medium);
|
||||
@@ -214,9 +214,9 @@
|
||||
transition: background-color var(--transition-fast), border-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.mailbox-dashboard__pagination-button:hover:not(:disabled) {
|
||||
background-color: var(--color-neutral-gray-50);
|
||||
border-color: var(--color-brand-primary);
|
||||
.mailbox-dashboard__pagination-button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.mailbox-dashboard__pagination-button:focus-visible {
|
||||
@@ -224,9 +224,9 @@
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.mailbox-dashboard__pagination-button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
.mailbox-dashboard__pagination-button:hover:not(:disabled) {
|
||||
background-color: var(--color-neutral-gray-50);
|
||||
border-color: var(--color-brand-primary);
|
||||
}
|
||||
|
||||
.mailbox-dashboard__detail {
|
||||
@@ -334,7 +334,7 @@
|
||||
|
||||
.mailbox-dashboard__search-input:focus {
|
||||
border-color: var(--color-brand-primary);
|
||||
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
||||
box-shadow: var(--shadow-sm);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -346,10 +346,12 @@
|
||||
.mailbox-dashboard__toolbar {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.mailbox-dashboard__filter-group {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.mailbox-dashboard__detail {
|
||||
padding: var(--spacing-3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user