From d8b3a0337596e021d0595f1fd6395f178f517293 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Mon, 27 Jul 2026 12:41:04 -0700
Subject: [PATCH] fix(skills): place the status glyph left of the skill name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Review feedback on the row header: the badge belongs immediately right of the
name so it reads as part of it, and the run's status circle/check belongs to
the left of the name rather than sharing the badge's slot on the far right.
Name, glyph and badge are now one left-aligned group; the location count and
chevron stay right-aligned. `available` still has no leading glyph — an empty
reserved box only indents the name past a gap with nothing in it.
---
.../src/components/skills/SkillUpdateRow.tsx | 68 +++++++++++--------
1 file changed, 40 insertions(+), 28 deletions(-)
diff --git a/src/renderer/src/components/skills/SkillUpdateRow.tsx b/src/renderer/src/components/skills/SkillUpdateRow.tsx
index 84d7c76af67..6b5a77382e0 100644
--- a/src/renderer/src/components/skills/SkillUpdateRow.tsx
+++ b/src/renderer/src/components/skills/SkillUpdateRow.tsx
@@ -1,4 +1,4 @@
-import { CheckCircle2, ChevronDown, Circle, XCircle } from 'lucide-react'
+import { AlertTriangle, CheckCircle2, ChevronDown, Circle, XCircle } from 'lucide-react'
import type { SkillFreshnessGroupModel } from './skill-freshness-grouping'
import { translate } from '@/i18n/i18n'
import { Badge } from '@/components/ui/badge'
@@ -10,14 +10,10 @@ import { skippedReason } from './skill-freshness-skipped-reason'
export type SkillRowState = 'available' | 'blocked' | 'pending' | 'done' | 'failed'
/**
- * The single status slot, sitting between the name and the location count.
- *
- * Why one slot rather than a leading icon column: a leading icon has nothing to
- * show in the resting state, and reserving the box for it just indents every
- * name past an empty gap. Swapping badge for icon in place keeps the name
- * flush-left and the row's right edge fixed in every state.
+ * Leading status glyph. Absent for `available` on purpose: an empty reserved box
+ * would just indent the name past a gap with nothing in it.
*/
-function StateSlot({ state }: { state: SkillRowState }): React.JSX.Element {
+function StateIcon({ state }: { state: SkillRowState }): React.JSX.Element | null {
switch (state) {
case 'done':
return
@@ -26,31 +22,44 @@ function StateSlot({ state }: { state: SkillRowState }): React.JSX.Element {
case 'pending':
return
case 'blocked':
- return (
-
- {translate('auto.components.skills.SkillFreshnessRow.statusCantUpdate', 'Skipped')}
-
- )
+ return
case 'available':
- return (
-
- {translate(
- 'auto.components.skills.SkillFreshnessRow.statusUpdateAvailable',
- 'Update available'
- )}
-
- )
+ return null
}
}
+/** Sits immediately right of the name, so the label reads as part of it. */
+function StateBadge({ state }: { state: SkillRowState }): React.JSX.Element | null {
+ if (state === 'blocked') {
+ return (
+
+ {translate('auto.components.skills.SkillFreshnessRow.statusCantUpdate', 'Skipped')}
+
+ )
+ }
+ if (state === 'available') {
+ return (
+
+ {translate(
+ 'auto.components.skills.SkillFreshnessRow.statusUpdateAvailable',
+ 'Update available'
+ )}
+
+ )
+ }
+ // Why: once a run owns the row the leading glyph carries the state. A stale
+ // "Update available" beside a green check would contradict it.
+ return null
+}
+
/**
* One skill in the update dialog, used unchanged in every state.
*
* The header keeps identical geometry from "update available" through running to
- * the result — only the status slot's contents change — so pressing Update
+ * the result — the row keeps its place and its right edge — so pressing Update
* doesn't replace the dialog's layout with a different one. Locations live
* behind a per-skill disclosure instead of being dumped inline, because a skill
* with several plugin-cache copies otherwise buries the actions.
@@ -76,10 +85,13 @@ export function SkillUpdateRow({
state === 'pending' ? 'opacity-60' : ''
}`}
>
-
- {group.name}
+
+
+
+ {group.name}
+
+
-
{locationCount === 1
? translate('auto.components.skills.SkillUpdateRow.oneLocation', '1 location')