feat: pulse Soul sidebar icon when soul mode is active (#606)

This commit is contained in:
ben
2026-02-17 23:17:49 -08:00
committed by GitHub
parent 8dc4265e08
commit 2824919962
4 changed files with 55 additions and 3 deletions

View File

@@ -133,3 +133,42 @@ select:disabled {
@utility animate-progress-shimmer {
animation: progress-shimmer 2s infinite linear;
}
@keyframes soul-nav-pulse {
0%,
100% {
transform: scale(1);
color: #ef4444;
filter: drop-shadow(0 0 0 rgba(239, 68, 68, 0));
}
35% {
transform: scale(1.08);
color: #f87171;
filter: drop-shadow(0 0 8px rgba(239, 68, 68, 0.45));
}
70% {
transform: scale(1.15);
color: #ef4444;
filter: drop-shadow(0 0 14px rgba(239, 68, 68, 0.75));
}
}
.soul-nav-icon-active {
color: #ef4444;
animation: soul-nav-pulse 1.8s cubic-bezier(0.32, 0, 0.3, 1) infinite;
transform-origin: center;
will-change: transform, filter;
}
[data-theme="dark"] .soul-nav-icon-active {
color: #fb7185;
}
@media (prefers-reduced-motion: reduce) {
.soul-nav-icon-active {
animation: none;
filter: none;
}
}

View File

@@ -515,6 +515,13 @@ export default function DashboardView(props: DashboardViewProps) {
});
});
const soulModeEnabled = createMemo(() => {
const status = props.soulStatusByWorkspaceId[props.activeWorkspaceId];
return Boolean(status?.enabled ?? props.activeSoulStatus?.enabled);
});
const soulNavIconClass = () => (soulModeEnabled() ? "soul-nav-icon-active" : "");
const navItem = (t: DashboardTab, label: any, icon: any) => {
const active = () => props.tab === t || (t === "mcp" && props.tab === "plugins");
return (
@@ -1537,7 +1544,7 @@ export default function DashboardView(props: DashboardViewProps) {
}`}
onClick={() => props.setTab("soul")}
>
<HeartPulse size={18} />
<HeartPulse size={18} class={soulNavIconClass()} />
Soul
</button>
<button
@@ -1585,7 +1592,7 @@ export default function DashboardView(props: DashboardViewProps) {
<aside class="w-56 hidden md:flex flex-col bg-dls-sidebar border-l border-dls-border p-4">
<div class="space-y-1 pt-2">
{navItem("scheduled", "Automations", <History size={18} />)}
{navItem("soul", "Soul", <HeartPulse size={18} />)}
{navItem("soul", "Soul", <HeartPulse size={18} class={soulNavIconClass()} />)}
{navItem("skills", "Skills", <Zap size={18} />)}
{navItem("mcp", "Extensions", <Box size={18} />)}
{navItem("identities", "Messaging", <MessageCircle size={18} />)}

View File

@@ -1807,6 +1807,12 @@ export default function SessionView(props: SessionViewProps) {
})();
};
const soulModeEnabled = createMemo(() =>
Boolean(props.soulStatusByWorkspaceId[props.activeWorkspaceId]?.enabled)
);
const soulNavIconClass = () => (soulModeEnabled() ? "soul-nav-icon-active" : "");
const openProviderAuth = () => {
void props.openProviderAuthModal().catch((error) => {
const message = error instanceof Error ? error.message : "Connect failed";
@@ -2659,7 +2665,7 @@ export default function SessionView(props: SessionViewProps) {
}`}
onClick={() => openSoul()}
>
<HeartPulse size={18} />
<HeartPulse size={18} class={soulNavIconClass()} />
Soul
</button>
<button

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB