ui: add animations to properties panel toggle

- Move toggle icon next to three-dots menu in a shared flex container
- Toggle icon fades in/out with opacity transition instead of hard mount/unmount
- Properties panel slides in/out with width + opacity transition (200ms ease-in-out)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dotta
2026-03-03 15:06:42 -06:00
parent c11d2d3eda
commit 31f02a80d8
2 changed files with 28 additions and 20 deletions

View File

@@ -6,19 +6,24 @@ import { ScrollArea } from "@/components/ui/scroll-area";
export function PropertiesPanel() {
const { panelContent, panelVisible, setPanelVisible } = usePanel();
if (!panelContent || !panelVisible) return null;
if (!panelContent) return null;
return (
<aside className="hidden md:flex w-80 border-l border-border bg-card flex-col shrink-0">
<div className="flex items-center justify-between px-4 py-2 border-b border-border">
<span className="text-sm font-medium">Properties</span>
<Button variant="ghost" size="icon-xs" onClick={() => setPanelVisible(false)}>
<X className="h-4 w-4" />
</Button>
<aside
className="hidden md:flex border-l border-border bg-card flex-col shrink-0 overflow-hidden transition-[width,opacity] duration-200 ease-in-out"
style={{ width: panelVisible ? 320 : 0, opacity: panelVisible ? 1 : 0 }}
>
<div className="w-80 flex-1 flex flex-col min-w-[320px]">
<div className="flex items-center justify-between px-4 py-2 border-b border-border">
<span className="text-sm font-medium">Properties</span>
<Button variant="ghost" size="icon-xs" onClick={() => setPanelVisible(false)}>
<X className="h-4 w-4" />
</Button>
</div>
<ScrollArea className="flex-1">
<div className="p-4">{panelContent}</div>
</ScrollArea>
</div>
<ScrollArea className="flex-1">
<div className="p-4">{panelContent}</div>
</ScrollArea>
</aside>
);
}

View File

@@ -613,24 +613,26 @@ export function IssueDetail() {
<SlidersHorizontal className="h-4 w-4" />
</Button>
{!panelVisible && (
<div className="hidden md:flex items-center md:ml-auto shrink-0">
<Button
variant="ghost"
size="icon-xs"
className="hidden md:inline-flex ml-auto shrink-0"
className={cn(
"shrink-0 transition-opacity duration-200",
panelVisible ? "opacity-0 pointer-events-none w-0 overflow-hidden" : "opacity-100",
)}
onClick={() => setPanelVisible(true)}
title="Show properties"
>
<SlidersHorizontal className="h-4 w-4" />
</Button>
)}
<Popover open={moreOpen} onOpenChange={setMoreOpen}>
<PopoverTrigger asChild>
<Button variant="ghost" size="icon-xs" className="md:ml-auto shrink-0">
<MoreHorizontal className="h-4 w-4" />
</Button>
</PopoverTrigger>
<Popover open={moreOpen} onOpenChange={setMoreOpen}>
<PopoverTrigger asChild>
<Button variant="ghost" size="icon-xs" className="shrink-0">
<MoreHorizontal className="h-4 w-4" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-44 p-1" align="end">
<button
className="flex items-center gap-2 w-full px-2 py-1.5 text-xs rounded hover:bg-accent/50 text-destructive"
@@ -646,7 +648,8 @@ export function IssueDetail() {
Hide this Issue
</button>
</PopoverContent>
</Popover>
</Popover>
</div>
</div>
<InlineEditor