refactor(frontend): the second sweep — scoped rules that no longer match their own template (#2962)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 7s
CI & Build / TypeScript typecheck (push) Successful in 10s
CI & Build / integration (push) Successful in 27s
CI & Build / Python tests (push) Successful in 1m4s
CI & Build / Build & push image (push) Successful in 34s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 7s
CI & Build / TypeScript typecheck (push) Successful in 10s
CI & Build / integration (push) Successful in 27s
CI & Build / Python tests (push) Successful in 1m4s
CI & Build / Build & push image (push) Successful in 34s
The first sweep asked "does this class token appear anywhere outside a
<style> block?". That is too generous for a `<style scoped>` rule, which can
only ever match its own template, the component's root element, or whatever
`:deep()` reaches — so a scoped rule whose name lives only in some OTHER file
is dead regardless. The server's map had this right and my local pass did
not; this closes the gap.
79 scoped classes are absent from their own file. 48 are names their own file
BUILDS — `status-${task.status}`, `pri-${p}`, `toast--${type}`,
`perm-${permission}`, `diff-${op}`, `is-${kind}` — and 12 more are Vue
transition classes. Those are the map's documented blind spot and they stay.
The remaining 19 match nothing:
- AppHeader (9, -39 lines): the whole connection-status indicator —
.status-indicator/.status-dot/.status-text and the five colour states,
plus @keyframes pulse-dot and status-pulse, which had no other user. Same
Phase 7 residue as the last commit. `.btn-icon.active` goes too: `active`
is never applied in this component (its nav uses router-link-active).
- SettingsView (6): .status-badge/.status-on/.status-off,
.perm-granted/.perm-denied, .location-row. This view renders no child
components at all, so nothing can inherit its scope.
- WorkspaceNoteEditor: .note-row:hover .btn-delete and .btn-suggest-tags —
those buttons are .btn-danger-outline/.btn-ghost now.
- ProjectListView .loading-msg; SnippetEditorView .field-row.three, whose
media-query companion keeps its live .field-row half.
Checked against child-component roots before deleting, since a child's root
element does inherit the parent's scope id — none of the 19 is one. Template
and script regions byte-identical; both style checks still pass with only
the six pre-existing reports.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -212,43 +212,6 @@ router.afterEach(() => {
|
||||
box-shadow: 0 0 16px color-mix(in srgb, var(--fs-accent) 30%, transparent);
|
||||
}
|
||||
|
||||
/* Status indicator */
|
||||
.status-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
cursor: default;
|
||||
padding: 0 0.25rem;
|
||||
}
|
||||
.status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.status-text {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: var(--fs-text-tertiary);
|
||||
}
|
||||
/* Status dots are indicator lights, not semantic-palette buttons —
|
||||
they want to read as vital (Moss/Warning/Error are too muted for
|
||||
a "ready" indicator). Hardcoded bright values; the rest of the
|
||||
system still uses the semantic tokens. */
|
||||
.status-green .status-dot { background: #4ade80; animation: status-pulse 2.5s ease-in-out infinite; }
|
||||
.status-yellow .status-dot { background: #facc15; animation: pulse-dot 2s infinite; }
|
||||
.status-orange .status-dot { background: #f97316; }
|
||||
.status-red .status-dot { background: #ef4444; }
|
||||
.status-gray .status-dot { background: var(--fs-text-tertiary); animation: pulse-dot 2s infinite; }
|
||||
@keyframes pulse-dot {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.3; }
|
||||
}
|
||||
@keyframes status-pulse {
|
||||
0%, 100% { box-shadow: 0 0 4px rgba(74, 222, 128, 0.4); }
|
||||
50% { box-shadow: 0 0 10px rgba(74, 222, 128, 0.6); }
|
||||
}
|
||||
|
||||
/* Icon buttons (?, theme, gear) */
|
||||
.btn-icon {
|
||||
background: none;
|
||||
@@ -263,8 +226,7 @@ router.afterEach(() => {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.btn-icon:hover,
|
||||
.btn-icon.active {
|
||||
.btn-icon:hover {
|
||||
background: var(--fs-surface-raised);
|
||||
color: var(--fs-text-primary);
|
||||
border-color: var(--fs-accent);
|
||||
@@ -382,7 +344,6 @@ router.afterEach(() => {
|
||||
.nav-center {
|
||||
display: none;
|
||||
}
|
||||
.status-indicator,
|
||||
.btn-icon,
|
||||
.user-info {
|
||||
display: none;
|
||||
|
||||
@@ -471,7 +471,6 @@ defineExpose({ reload: loadProjectNotes });
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
.rail-search-input {
|
||||
flex: 1;
|
||||
background: transparent;
|
||||
@@ -575,8 +574,6 @@ defineExpose({ reload: loadProjectNotes });
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.note-row:hover .btn-delete { opacity: 1; }
|
||||
|
||||
/* Editor UI */
|
||||
.panel-header {
|
||||
display: flex;
|
||||
@@ -624,8 +621,6 @@ defineExpose({ reload: loadProjectNotes });
|
||||
}
|
||||
.tag-row > :first-child { flex: 1; min-width: 0; }
|
||||
|
||||
.btn-suggest-tags { flex-shrink: 0; align-self: center; }
|
||||
|
||||
.tag-suggestions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -653,7 +648,6 @@ defineExpose({ reload: loadProjectNotes });
|
||||
color: var(--fs-accent);
|
||||
}
|
||||
|
||||
|
||||
.link-suggest-strip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user