feat(toolbar): add smooth transition animation for AppSwitcher compact toggle

Replace conditional rendering with always-rendered span driven by CSS
max-width + opacity animation. Add time-lock in useAutoCompact to prevent
ResizeObserver flicker during expand animation.
This commit is contained in:
Jason
2026-02-21 20:54:03 +08:00
parent 5763b9094b
commit 6b4ba64bbd
2 changed files with 21 additions and 8 deletions
+15 -8
View File
@@ -1,6 +1,7 @@
import type { AppId } from "@/lib/api";
import type { VisibleApps } from "@/types";
import { ProviderIcon } from "@/components/ProviderIcon";
import { cn } from "@/lib/utils";
interface AppSwitcherProps {
activeApp: AppId;
@@ -52,22 +53,28 @@ export function AppSwitcher({
key={app}
type="button"
onClick={() => handleSwitch(app)}
className={`group inline-flex items-center gap-2 px-3 h-8 rounded-md text-sm font-medium transition-all duration-200 ${
className={cn(
"group inline-flex items-center px-3 h-8 rounded-md text-sm font-medium transition-all duration-200",
activeApp === app
? "bg-background text-foreground shadow-sm"
: "text-muted-foreground hover:text-foreground hover:bg-background/50"
}`}
: "text-muted-foreground hover:text-foreground hover:bg-background/50",
)}
>
<ProviderIcon
icon={appIconName[app]}
name={appDisplayName[app]}
size={iconSize}
/>
{!compact && (
<span className="transition-all duration-200 whitespace-nowrap">
{appDisplayName[app]}
</span>
)}
<span
className={cn(
"transition-all duration-200 whitespace-nowrap overflow-hidden",
compact
? "max-w-0 opacity-0 ml-0"
: "max-w-[80px] opacity-100 ml-2",
)}
>
{appDisplayName[app]}
</span>
</button>
))}
</div>