refactor(ui): DRY the settings-card CSS tokens + fix unstyled headers (#161)
- Promote .fc-section-h to a global token (app.css). It was copied identically into 4 cards, and TranslationCard used the class with NO local def — so its section headers rendered unstyled. Now fixed everywhere. - Promote .fc-good / .fc-weak status colours to globals; delete the local copies in the GPU/heads cards. (.fc-ok stays local — divergent: on-surface in HeadsCard vs success in QueuesTable. .fc-bad stays — different name.) - Delete 10 identical local .fc-muted redefinitions that crept back after the 2026-06-09 sweep; the global utility already covers them. - DbMaintenanceCard: opacity:0.6 muted text → the .fc-muted token (the exact anti-pattern that token's comment forbids). - HeadsCard: collapse byte-identical ratePct() into pct(). CSS-only + one template class swap; no logic change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsmJSQxnNxGgtM5Yz4GAqi
This commit is contained in:
@@ -131,11 +131,6 @@ function saveToggle (p, v) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
.fc-section-h {
|
||||
font-size: 13px; font-weight: 700; letter-spacing: 0.03em;
|
||||
text-transform: uppercase; color: rgb(var(--v-theme-on-surface));
|
||||
}
|
||||
.fc-proposer {
|
||||
border-top: 1px solid rgb(var(--v-theme-surface-light)); padding-top: 14px;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,6 @@ async function onCommit() {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
.fc-code {
|
||||
background: rgb(var(--v-theme-surface-light));
|
||||
border-radius: 4px; padding: 2px 8px;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
<p v-else class="text-caption mt-3" style="opacity: 0.6;">
|
||||
<p v-else class="text-caption mt-3 fc-muted">
|
||||
No table statistics yet.
|
||||
</p>
|
||||
</MaintenanceTile>
|
||||
|
||||
@@ -72,6 +72,5 @@ onUnmounted(() => { if (pollId) clearInterval(pollId) })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
.fc-bad { color: rgb(var(--v-theme-error)); }
|
||||
</style>
|
||||
|
||||
@@ -95,7 +95,6 @@ onUnmounted(() => { if (pollId) clearInterval(pollId) })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
.fc-cells { display: flex; gap: 28px; }
|
||||
.fc-cell__n {
|
||||
font-size: 20px; font-weight: 700; line-height: 1.1;
|
||||
@@ -105,6 +104,5 @@ onUnmounted(() => { if (pollId) clearInterval(pollId) })
|
||||
font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
|
||||
color: rgb(var(--v-theme-on-surface-variant));
|
||||
}
|
||||
.fc-good { color: rgb(var(--v-theme-success)); }
|
||||
.fc-bad { color: rgb(var(--v-theme-error)); }
|
||||
</style>
|
||||
|
||||
@@ -367,11 +367,6 @@ async function onReprocess() {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
.fc-section-h {
|
||||
font-size: 13px; font-weight: 700; letter-spacing: 0.03em;
|
||||
text-transform: uppercase; color: rgb(var(--v-theme-on-surface));
|
||||
}
|
||||
.fc-token {
|
||||
display: flex; align-items: center; gap: 4px;
|
||||
background: rgb(var(--v-theme-surface-light)); border-radius: 6px;
|
||||
@@ -390,6 +385,4 @@ async function onReprocess() {
|
||||
font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
|
||||
color: rgb(var(--v-theme-on-surface-variant));
|
||||
}
|
||||
.fc-good { color: rgb(var(--v-theme-success)); }
|
||||
.fc-weak { color: rgb(var(--v-theme-error)); }
|
||||
</style>
|
||||
|
||||
@@ -155,11 +155,6 @@ async function onRecover(it) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
.fc-section-h {
|
||||
font-size: 13px; font-weight: 700; letter-spacing: 0.03em;
|
||||
text-transform: uppercase; color: rgb(var(--v-theme-on-surface));
|
||||
}
|
||||
.fc-queue { display: flex; gap: 24px; }
|
||||
.fc-q__n {
|
||||
font-size: 20px; font-weight: 700; line-height: 1.1;
|
||||
@@ -169,8 +164,6 @@ async function onRecover(it) {
|
||||
font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
|
||||
color: rgb(var(--v-theme-on-surface-variant));
|
||||
}
|
||||
.fc-good { color: rgb(var(--v-theme-success)); }
|
||||
.fc-weak { color: rgb(var(--v-theme-error)); }
|
||||
.fc-defect {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
background: rgb(var(--v-theme-surface-light)); border-radius: 8px;
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
<td class="fc-r fc-mono">{{ c.n_auto_applied }}</td>
|
||||
<td class="fc-r fc-mono">{{ c.n_misfires }}</td>
|
||||
<td class="fc-r fc-mono" :class="rateClass(c.misfire_rate)">
|
||||
{{ ratePct(c.misfire_rate) }}
|
||||
{{ pct(c.misfire_rate) }}
|
||||
</td>
|
||||
<td class="fc-r fc-mono">{{ c.n_underfires }}</td>
|
||||
</tr>
|
||||
@@ -495,7 +495,6 @@ function sweepConcepts(run) {
|
||||
.sort((a, b) => b.applied - a.applied)
|
||||
}
|
||||
function sweepTotal(run) { return run?.n_applied ?? 0 }
|
||||
function ratePct(x) { return x == null ? '—' : `${Math.round(x * 100)}%` }
|
||||
function rateClass(x) {
|
||||
if (x == null) return ''
|
||||
if (x <= 0.03) return 'fc-good'
|
||||
@@ -526,12 +525,6 @@ function relTime(iso) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
|
||||
.fc-section-h {
|
||||
font-size: 13px; font-weight: 700; letter-spacing: 0.03em;
|
||||
text-transform: uppercase; color: rgb(var(--v-theme-on-surface));
|
||||
}
|
||||
.fc-auto {
|
||||
border-top: 1px solid rgb(var(--v-theme-surface-light)); padding-top: 16px;
|
||||
}
|
||||
@@ -588,7 +581,5 @@ function relTime(iso) {
|
||||
background: rgb(var(--v-theme-surface-light));
|
||||
padding: 1px 6px; border-radius: 999px;
|
||||
}
|
||||
.fc-good { color: rgb(var(--v-theme-success)); }
|
||||
.fc-ok { color: rgb(var(--v-theme-on-surface)); }
|
||||
.fc-weak { color: rgb(var(--v-theme-error)); }
|
||||
</style>
|
||||
|
||||
@@ -80,5 +80,4 @@ async function run() {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
</style>
|
||||
|
||||
@@ -40,6 +40,20 @@
|
||||
emits, so no specificity/reorder fight — no !important needed. */
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
|
||||
/* Section sub-heading in settings cards (DRY pass #161): was redefined
|
||||
identically in 4 cards, and TranslationCard used the class with NO local def
|
||||
so its section headers rendered unstyled. Now one global utility. */
|
||||
.fc-section-h {
|
||||
font-size: 13px; font-weight: 700; letter-spacing: 0.03em;
|
||||
text-transform: uppercase; color: rgb(var(--v-theme-on-surface));
|
||||
}
|
||||
|
||||
/* Status text colours (DRY pass #161): fc-good = success, fc-weak = error,
|
||||
consolidated from the GPU / heads cards. fc-ok is intentionally NOT global —
|
||||
it means on-surface in HeadsCard but success in QueuesTable. */
|
||||
.fc-good { color: rgb(var(--v-theme-success)); }
|
||||
.fc-weak { color: rgb(var(--v-theme-error)); }
|
||||
|
||||
/* Vuetify 4 dropped its global CSS reset (normalisation moved into each
|
||||
component). FC's layouts assumed the reset zeroed margins on text elements, so
|
||||
restore just that — the "minimal reset" from the v4 upgrade guide — inside
|
||||
|
||||
@@ -284,7 +284,6 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
|
||||
/* Full-height workspace under the sticky top nav. --fc-nav-h is the nav's REAL
|
||||
measured height (set by TopNav) — a hardcoded 64px here overflowed the
|
||||
|
||||
@@ -349,7 +349,6 @@ async function onDeleteTagConfirm() {
|
||||
.fc-tags__sentinel {
|
||||
display: flex; justify-content: center; padding: 32px 0; min-height: 60px;
|
||||
}
|
||||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||||
.fc-merge-preview {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
|
||||
|
||||
Reference in New Issue
Block a user