Enhance Sidebar component with improved animations and transitions

Updated the Sidebar component to include smoother transitions for width, padding, and background color changes. Adjusted layout styles for better responsiveness and visual appeal, ensuring a more cohesive user experience when toggling the sidebar. Refactored navigation button styles for consistency and added transition effects to icon and label visibility based on the collapsed state.
This commit is contained in:
Xin Wang
2026-06-05 14:49:09 +08:00
parent 571c67526f
commit 7dd37936b4

View File

@@ -55,11 +55,11 @@ export function Sidebar({
return (
<aside
className={[
"flex shrink-0 flex-col border-r border-sidebar-border bg-sidebar transition-all",
"flex shrink-0 flex-col overflow-hidden border-r border-sidebar-border bg-sidebar transition-[width] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[width]",
collapsed ? "w-[76px]" : "w-[252px]",
].join(" ")}
>
<div className="flex h-[81px] items-center gap-3 border-b border-sidebar-border px-5">
<div className="flex h-[81px] items-center gap-3 border-b border-sidebar-border px-5 transition-[padding] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]">
<div
className="relative flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl text-on-primary shadow-sm"
style={{
@@ -71,14 +71,17 @@ export function Sidebar({
<Video size={22} style={{ color: "var(--primary-foreground)" }} />
</div>
{!collapsed && (
<div>
<div className="font-display text-base text-foreground">
AI
</div>
<div className="caption-label text-muted-soft"></div>
<div
className={[
"min-w-0 overflow-hidden transition-all duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]",
collapsed ? "w-0 opacity-0 -translate-x-2" : "w-[140px] opacity-100 translate-x-0",
].join(" ")}
>
<div className="truncate font-display text-base text-foreground">
AI
</div>
)}
<div className="truncate caption-label text-muted-soft"></div>
</div>
</div>
<nav className="flex-1 space-y-1 px-3 py-5">
@@ -102,7 +105,12 @@ export function Sidebar({
{!collapsed && <span className="font-medium"></span>}
</div>
<div className={["mt-1 space-y-1", collapsed ? "pl-0" : "pl-5"].join(" ")}>
<div
className={[
"mt-1 space-y-1 transition-[padding] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]",
collapsed ? "pl-0" : "pl-5",
].join(" ")}
>
{assistantSubItems.map((item) => (
<NavButton
key={item.key}
@@ -134,11 +142,14 @@ export function Sidebar({
<div className="border-t border-sidebar-border p-3">
<button
onClick={onToggle}
className="flex h-10 w-full items-center justify-center rounded-full border border-hairline-strong text-muted-foreground transition-colors hover:bg-surface-strong hover:text-foreground"
className="flex h-10 w-full items-center justify-center rounded-full border border-hairline-strong text-muted-foreground transition-[background-color,color,border-color,transform] duration-200 hover:bg-surface-strong hover:text-foreground active:scale-95"
>
<ChevronLeft
size={18}
className={collapsed ? "rotate-180 transition" : "transition"}
className={[
"transition-transform duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]",
collapsed ? "rotate-180" : "rotate-0",
].join(" ")}
/>
</button>
</div>
@@ -166,7 +177,7 @@ function NavButton({
onClick={onClick}
title={collapsed ? label : undefined}
className={[
"mt-1 flex w-full items-center gap-3 rounded-full px-3 text-sm transition-colors",
"group mt-1 flex w-full items-center gap-3 overflow-hidden rounded-full px-3 text-sm transition-[background-color,color,transform] duration-200 hover:translate-x-0.5 active:scale-[0.98]",
small ? "h-10" : "h-11",
active
? "bg-sidebar-accent text-sidebar-accent-foreground font-medium"
@@ -174,8 +185,18 @@ function NavButton({
collapsed ? "justify-center" : "",
].join(" ")}
>
<Icon size={small ? 16 : 18} />
{!collapsed && <span>{label}</span>}
<Icon
size={small ? 16 : 18}
className="shrink-0 transition-transform duration-200 group-hover:scale-105"
/>
<span
className={[
"min-w-0 truncate transition-all duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]",
collapsed ? "w-0 opacity-0 -translate-x-2" : "w-[150px] opacity-100 translate-x-0",
].join(" ")}
>
{label}
</span>
</button>
);
}