feat(FN-1105): move background task indicator styling to CSS classes

- Replace inline styles in BackgroundTasksIndicator with semantic class names for pill, popover, and session rows
- Add dedicated styles for attention state, hover behavior, and muted text/border theme tokens
- Style session content, icons, and dismiss controls in styles.css to centralize indicator presentation
This commit is contained in:
gsxdsm
2026-04-08 00:19:12 -07:00
parent 7eed8ed68a
commit b386db12bd
2 changed files with 137 additions and 58 deletions

View File

@@ -50,25 +50,10 @@ export function BackgroundTasksIndicator({
const hasAttention = needsInput > 0;
return (
<div ref={containerRef} className="background-tasks-indicator" style={{ position: "relative" }}>
<div ref={containerRef} className="background-tasks-indicator">
<button
className="background-tasks-indicator__pill"
className={`background-tasks-indicator__pill${hasAttention ? " background-tasks-indicator__pill--attention" : ""}`}
onClick={() => setPopoverOpen((prev) => !prev)}
style={{
display: "inline-flex",
alignItems: "center",
gap: "6px",
padding: "2px 10px",
borderRadius: "12px",
border: "1px solid var(--border-color)",
background: hasAttention ? "var(--triage)" : "var(--surface-secondary)",
color: hasAttention ? "#fff" : "var(--text-primary)",
cursor: "pointer",
fontSize: "12px",
fontWeight: 500,
lineHeight: "20px",
whiteSpace: "nowrap",
}}
title={`${total} background AI task${total !== 1 ? "s" : ""}${needsInput > 0 ? ` (${needsInput} need${needsInput !== 1 ? "" : "s"} input)` : ""}`}
>
{generating > 0 && (
@@ -79,26 +64,11 @@ export function BackgroundTasksIndicator({
</button>
{popoverOpen && (
<div
className="background-tasks-indicator__popover"
style={{
position: "absolute",
bottom: "calc(100% + 8px)",
left: 0,
minWidth: "280px",
maxWidth: "360px",
background: "var(--surface-primary)",
border: "1px solid var(--border-color)",
borderRadius: "8px",
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
zIndex: 1000,
overflow: "hidden",
}}
>
<div style={{ padding: "8px 12px", borderBottom: "1px solid var(--border-color)", fontSize: "12px", fontWeight: 600, color: "var(--text-secondary)" }}>
<div className="background-tasks-indicator__popover">
<div className="background-tasks-indicator__popover-header">
Background Tasks
</div>
<div style={{ maxHeight: "240px", overflowY: "auto" }}>
<div className="background-tasks-indicator__sessions">
{sessions.map((session) => {
const Icon = TYPE_ICONS[session.type];
const isGenerating = session.status === "generating";
@@ -107,46 +77,46 @@ export function BackgroundTasksIndicator({
return (
<div
key={session.id}
style={{
display: "flex",
alignItems: "center",
gap: "8px",
padding: "8px 12px",
borderBottom: "1px solid var(--border-color)",
cursor: "pointer",
}}
className="background-tasks-indicator__session"
onClick={() => {
onOpenSession(session);
setPopoverOpen(false);
}}
>
<Icon size={14} style={{ flexShrink: 0, color: "var(--text-secondary)" }} />
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: "13px", fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
<Icon size={14} className="background-tasks-indicator__session-icon" />
<div className="background-tasks-indicator__session-content">
<div className="background-tasks-indicator__session-title">
{session.title}
</div>
<div style={{ fontSize: "11px", color: "var(--text-secondary)" }}>
<div className="background-tasks-indicator__session-meta">
{TYPE_LABELS[session.type]}
{isGenerating && " — generating..."}
{isAwaiting && " — needs input"}
</div>
</div>
{isGenerating && <Loader2 size={14} style={{ flexShrink: 0, animation: "spin 1s linear infinite", color: "var(--color-success)" }} />}
{isAwaiting && <HelpCircle size={14} style={{ flexShrink: 0, color: "var(--triage)" }} />}
{isGenerating && (
<Loader2
size={14}
className="background-tasks-indicator__session-icon"
style={{
animation: "spin 1s linear infinite",
color: "var(--color-success)",
}}
/>
)}
{isAwaiting && (
<HelpCircle
size={14}
className="background-tasks-indicator__session-icon"
style={{ color: "var(--triage)" }}
/>
)}
<button
className="background-tasks-indicator__dismiss"
onClick={(e) => {
e.stopPropagation();
onDismissSession(session.id);
}}
style={{
flexShrink: 0,
background: "none",
border: "none",
cursor: "pointer",
padding: "2px",
color: "var(--text-secondary)",
borderRadius: "4px",
}}
title="Dismiss"
>
<X size={12} />

View File

@@ -17696,6 +17696,115 @@ html .column.drag-over * {
color: var(--color-success);
}
/* === Background Tasks Indicator === */
.background-tasks-indicator {
position: relative;
}
.background-tasks-indicator__pill {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 2px 10px;
border-radius: 12px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text-muted);
cursor: pointer;
font-size: 12px;
font-weight: 500;
line-height: 20px;
white-space: nowrap;
transition: background var(--transition-fast);
}
.background-tasks-indicator__pill:hover:not(.background-tasks-indicator__pill--attention) {
background: color-mix(in srgb, var(--surface) 85%, var(--text-muted));
}
.background-tasks-indicator__pill--attention {
background: var(--triage);
color: #fff;
border-color: var(--triage);
}
.background-tasks-indicator__pill--attention:hover {
background: color-mix(in srgb, var(--triage) 85%, #000);
}
.background-tasks-indicator__popover {
position: absolute;
bottom: calc(100% + 8px);
left: 0;
min-width: 280px;
max-width: 360px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 1000;
overflow: hidden;
}
.background-tasks-indicator__popover-header {
padding: 8px 12px;
border-bottom: 1px solid var(--border);
font-size: 12px;
font-weight: 600;
color: var(--text-muted);
}
.background-tasks-indicator__sessions {
max-height: 240px;
overflow-y: auto;
}
.background-tasks-indicator__session {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-bottom: 1px solid var(--border);
cursor: pointer;
}
.background-tasks-indicator__session:last-child {
border-bottom: none;
}
.background-tasks-indicator__session-icon {
flex-shrink: 0;
color: var(--text-muted);
}
.background-tasks-indicator__session-content {
flex: 1;
min-width: 0;
}
.background-tasks-indicator__session-title {
font-size: 13px;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.background-tasks-indicator__session-meta {
font-size: 11px;
color: var(--text-muted);
}
.background-tasks-indicator__dismiss {
flex-shrink: 0;
background: none;
border: none;
cursor: pointer;
padding: 2px;
color: var(--text-muted);
border-radius: 4px;
}
/* === DirectoryPicker === */
.directory-picker {
display: flex;