feat(web/ui): refactor component inline styles into utility classes
Pass 2 of the web UI spacing/typography/visual-rhythm rework. - Add layout, spacing, typography, visual, card, and component utilities - Add form-section, form-row, form-help, text-error, alert-success - Unify .form-group and .form-field; add .status-badge family - Alias legacy button classes to .btn primitives - Refactor ToolTypeListSidebar and ConfigProfileListSidebar to use .sidebar and var(--sidebar-width) instead of hardcoded 280px - Refactor ToolTypeEditorPanel, ConfigProfileEditorPanel, git-mount-editor, and manifest-editor to use utility classes Quality gates: npm run typecheck, npm run lint, npm run build pass. Inline style blocks in target components reduced from 198 to 11.
This commit is contained in:
+181
-24
@@ -428,21 +428,71 @@
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
.form-field,
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
gap: var(--space-2);
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.form-field:last-child,
|
||||
.form-group:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-field input,
|
||||
.form-field textarea,
|
||||
.form-field select {
|
||||
padding: 0.55rem 0.7rem;
|
||||
.form-field select,
|
||||
.form-group input,
|
||||
.form-group textarea,
|
||||
.form-group select {
|
||||
padding: var(--space-2) var(--space-3);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
border-radius: var(--radius-md);
|
||||
font: inherit;
|
||||
background: var(--panel);
|
||||
color: var(--ink);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.form-row .form-field,
|
||||
.form-row .form-group {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
padding: var(--space-4);
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.form-section > h4:first-child,
|
||||
.form-section > h3:first-child {
|
||||
margin-top: 0;
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.form-help {
|
||||
display: block;
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--muted);
|
||||
margin-top: var(--space-1);
|
||||
line-height: var(--line-height-normal);
|
||||
}
|
||||
|
||||
.text-error {
|
||||
color: var(--danger);
|
||||
font-size: var(--font-size-sm);
|
||||
line-height: var(--line-height-normal);
|
||||
}
|
||||
|
||||
.dialog-actions {
|
||||
@@ -494,19 +544,6 @@
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
padding: 0.55rem 0.7rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #b91c1c;
|
||||
padding: 0.75rem;
|
||||
@@ -1205,7 +1242,11 @@ a .icon:last-child {
|
||||
}
|
||||
}
|
||||
/* ─── Primitive Buttons ─── */
|
||||
.btn {
|
||||
.btn,
|
||||
.primary-button,
|
||||
.secondary-button,
|
||||
.ghost-button,
|
||||
.button-secondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -1224,29 +1265,41 @@ a .icon:last-child {
|
||||
transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
|
||||
}
|
||||
|
||||
.btn:focus-visible {
|
||||
.btn:focus-visible,
|
||||
.primary-button:focus-visible,
|
||||
.secondary-button:focus-visible,
|
||||
.ghost-button:focus-visible,
|
||||
.button-secondary:focus-visible {
|
||||
outline: 2px solid var(--brand);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
.btn-primary,
|
||||
.primary-button {
|
||||
background: var(--brand);
|
||||
color: var(--primary-fg);
|
||||
border-color: var(--brand);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
.btn-primary:hover,
|
||||
.primary-button:hover {
|
||||
background: var(--brand-strong);
|
||||
border-color: var(--brand-strong);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
.btn-secondary,
|
||||
.secondary-button,
|
||||
.ghost-button,
|
||||
.button-secondary {
|
||||
background: var(--panel);
|
||||
color: var(--ink);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
.btn-secondary:hover,
|
||||
.secondary-button:hover,
|
||||
.ghost-button:hover,
|
||||
.button-secondary:hover {
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
@@ -1411,6 +1464,12 @@ a .icon:last-child {
|
||||
color: var(--info);
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
background: var(--success-light);
|
||||
border-color: color-mix(in srgb, var(--success) 30%, transparent);
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
/* ─── Loading State ─── */
|
||||
.loading-state {
|
||||
display: flex;
|
||||
@@ -1454,6 +1513,104 @@ a .icon:last-child {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
/* ─── Status Badges ─── */
|
||||
.status-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
padding: var(--space-1) var(--space-2);
|
||||
border-radius: var(--radius-full);
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: 600;
|
||||
text-transform: capitalize;
|
||||
line-height: var(--line-height-tight);
|
||||
background: var(--bg);
|
||||
color: var(--muted);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.status-badge::before {
|
||||
content: "";
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.status-badge--running,
|
||||
.status-badge--success {
|
||||
background: var(--success-light);
|
||||
color: var(--success);
|
||||
border-color: color-mix(in srgb, var(--success) 30%, transparent);
|
||||
}
|
||||
|
||||
.status-badge--error,
|
||||
.status-badge--failed {
|
||||
background: var(--danger-light);
|
||||
color: var(--danger);
|
||||
border-color: color-mix(in srgb, var(--danger) 30%, transparent);
|
||||
}
|
||||
|
||||
.status-badge--warning {
|
||||
background: var(--warning-light);
|
||||
color: var(--warning);
|
||||
border-color: color-mix(in srgb, var(--warning) 30%, transparent);
|
||||
}
|
||||
|
||||
.status-badge--info,
|
||||
.status-badge--pending,
|
||||
.status-badge--idle {
|
||||
background: var(--info-light);
|
||||
color: var(--info);
|
||||
border-color: color-mix(in srgb, var(--info) 30%, transparent);
|
||||
}
|
||||
|
||||
/* Legacy instance-chip alias */
|
||||
.instance-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
padding: var(--space-1) var(--space-2);
|
||||
border-radius: var(--radius-full);
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: 600;
|
||||
text-transform: capitalize;
|
||||
line-height: var(--line-height-tight);
|
||||
background: var(--bg);
|
||||
color: var(--muted);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.instance-chip::before {
|
||||
content: "";
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.instance-chip.running {
|
||||
background: var(--success-light);
|
||||
color: var(--success);
|
||||
border-color: color-mix(in srgb, var(--success) 30%, transparent);
|
||||
}
|
||||
|
||||
.instance-chip.starting,
|
||||
.instance-chip.building,
|
||||
.instance-chip.probing {
|
||||
background: var(--warning-light);
|
||||
color: var(--warning);
|
||||
border-color: color-mix(in srgb, var(--warning) 30%, transparent);
|
||||
}
|
||||
|
||||
.instance-chip.error,
|
||||
.instance-chip.unhealthy,
|
||||
.instance-chip.stopped {
|
||||
background: var(--danger-light);
|
||||
color: var(--danger);
|
||||
border-color: color-mix(in srgb, var(--danger) 30%, transparent);
|
||||
}
|
||||
|
||||
/* ─── Focus States ─── */
|
||||
.nav-item:focus-visible,
|
||||
.mobile-nav-item:focus-visible,
|
||||
|
||||
Reference in New Issue
Block a user