Skip to content

Commit 20cd63e

Browse files
jeevanpillayclaude
andauthored
fix: improve sidebar skeleton to match actual implementation (#103)
- Update skeleton structure to match ServerSidebarImplementation layout - Add proper logo placeholder with correct dimensions - Match ActiveMenuItem and ThreadItem styling in skeleton - Improve user dropdown skeleton to show avatar and username placeholders - Use consistent overflow and width classes across all elements - Add two-line thread item skeletons for more realistic appearance This fixes the visual inconsistency during hard reloads by ensuring the skeleton closely matches the actual rendered sidebar components. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude <[email protected]>
1 parent b9b693b commit 20cd63e

File tree

1 file changed

+82
-53
lines changed

1 file changed

+82
-53
lines changed

src/components/chat/sidebar/SidebarSkeleton.tsx

Lines changed: 82 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ import { Plus } from "lucide-react"
1616
// Skeleton loader for the sidebar - provides instant visual feedback
1717
export function SidebarSkeleton() {
1818
return (
19-
<Sidebar variant="inset" className="w-64">
19+
<Sidebar variant="inset" className="w-64 max-w-64">
2020
<SidebarHeader className="p-4">
2121
<div className="flex items-center gap-3">
22-
{/* Logo skeleton */}
23-
<div className="w-6 h-6 bg-muted animate-pulse rounded" />
22+
{/* Logo skeleton - match the actual logo dimensions */}
23+
<div className="w-6 h-6 flex items-center justify-center">
24+
<div className="w-full h-4 bg-muted animate-pulse rounded" />
25+
</div>
2426
</div>
2527
</SidebarHeader>
2628

@@ -29,66 +31,93 @@ export function SidebarSkeleton() {
2931
<SidebarGroupContent>
3032
<SidebarMenu>
3133
<SidebarMenuItem>
32-
{/* New Chat button - static, can render immediately */}
33-
<SidebarMenuButton size="default" className="h-10 w-full">
34-
<Plus className="w-4 h-4" />
35-
<span>New Chat</span>
34+
{/* New Chat button skeleton - match ActiveMenuItem styling */}
35+
<SidebarMenuButton
36+
size="default"
37+
className="w-full max-w-full min-w-0 overflow-hidden"
38+
>
39+
<div className="w-full max-w-full min-w-0 flex items-center overflow-hidden">
40+
<Plus className="w-4 h-4" />
41+
<span>New Chat</span>
42+
</div>
3643
</SidebarMenuButton>
3744
</SidebarMenuItem>
3845
</SidebarMenu>
3946
</SidebarGroupContent>
4047
</SidebarGroup>
4148

42-
<ScrollArea className="h-[calc(100vh-280px)]">
43-
{/* Loading skeleton for threads */}
44-
<SidebarGroup>
45-
<SidebarGroupLabel className="text-xs font-medium text-muted-foreground">
46-
<div className="w-12 h-3 bg-muted animate-pulse rounded" />
47-
</SidebarGroupLabel>
48-
<SidebarGroupContent>
49-
<SidebarMenu className="space-y-0.5">
50-
{/* Skeleton thread items */}
51-
{Array.from(
52-
{ length: 5 },
53-
() =>
54-
`skeleton-thread-${Math.random().toString(36).substr(2, 9)}`,
55-
).map((id) => (
56-
<SidebarMenuItem key={id}>
57-
<SidebarMenuButton className="w-full h-auto p-2.5 text-left">
58-
<div className="w-full h-4 bg-muted animate-pulse rounded" />
59-
</SidebarMenuButton>
60-
</SidebarMenuItem>
61-
))}
62-
</SidebarMenu>
63-
</SidebarGroupContent>
64-
</SidebarGroup>
49+
{/* Threads list container - match the actual implementation */}
50+
<div className="w-full min-w-0">
51+
<ScrollArea className="flex-1">
52+
{/* Loading skeleton for threads */}
53+
<SidebarGroup>
54+
<SidebarGroupLabel className="text-xs font-medium text-muted-foreground">
55+
<div className="w-12 h-3 bg-muted animate-pulse rounded" />
56+
</SidebarGroupLabel>
57+
<SidebarGroupContent>
58+
<SidebarMenu className="space-y-0.5">
59+
{/* Skeleton thread items - match ThreadItem styling */}
60+
{Array.from(
61+
{ length: 4 },
62+
() =>
63+
`skeleton-thread-${Math.random().toString(36).substr(2, 9)}`,
64+
).map((id) => (
65+
<SidebarMenuItem key={id}>
66+
<SidebarMenuButton className="w-full max-w-full min-w-0 overflow-hidden h-auto py-2 px-2.5 text-left">
67+
<div className="w-full max-w-full min-w-0 flex items-start gap-1.5 overflow-hidden">
68+
<div className="flex-1 min-w-0 space-y-1">
69+
<div className="w-3/4 h-3.5 bg-muted animate-pulse rounded" />
70+
<div className="w-full h-3 bg-muted/60 animate-pulse rounded" />
71+
</div>
72+
</div>
73+
</SidebarMenuButton>
74+
</SidebarMenuItem>
75+
))}
76+
</SidebarMenu>
77+
</SidebarGroupContent>
78+
</SidebarGroup>
6579

66-
<SidebarGroup>
67-
<SidebarGroupLabel className="text-xs font-medium text-muted-foreground">
68-
<div className="w-16 h-3 bg-muted animate-pulse rounded" />
69-
</SidebarGroupLabel>
70-
<SidebarGroupContent>
71-
<SidebarMenu className="space-y-0.5">
72-
{Array.from(
73-
{ length: 3 },
74-
() =>
75-
`skeleton-older-${Math.random().toString(36).substr(2, 9)}`,
76-
).map((id) => (
77-
<SidebarMenuItem key={id}>
78-
<SidebarMenuButton className="w-full h-auto p-2.5 text-left">
79-
<div className="w-full h-4 bg-muted animate-pulse rounded" />
80-
</SidebarMenuButton>
81-
</SidebarMenuItem>
82-
))}
83-
</SidebarMenu>
84-
</SidebarGroupContent>
85-
</SidebarGroup>
86-
</ScrollArea>
80+
<SidebarGroup>
81+
<SidebarGroupLabel className="text-xs font-medium text-muted-foreground">
82+
<div className="w-16 h-3 bg-muted animate-pulse rounded" />
83+
</SidebarGroupLabel>
84+
<SidebarGroupContent>
85+
<SidebarMenu className="space-y-0.5">
86+
{Array.from(
87+
{ length: 3 },
88+
() =>
89+
`skeleton-older-${Math.random().toString(36).substr(2, 9)}`,
90+
).map((id) => (
91+
<SidebarMenuItem key={id}>
92+
<SidebarMenuButton className="w-full max-w-full min-w-0 overflow-hidden h-auto py-2 px-2.5 text-left">
93+
<div className="w-full max-w-full min-w-0 flex items-start gap-1.5 overflow-hidden">
94+
<div className="flex-1 min-w-0 space-y-1">
95+
<div className="w-2/3 h-3.5 bg-muted animate-pulse rounded" />
96+
<div className="w-5/6 h-3 bg-muted/60 animate-pulse rounded" />
97+
</div>
98+
</div>
99+
</SidebarMenuButton>
100+
</SidebarMenuItem>
101+
))}
102+
</SidebarMenu>
103+
</SidebarGroupContent>
104+
</SidebarGroup>
105+
</ScrollArea>
106+
</div>
87107
</SidebarContent>
88108

89109
<SidebarFooter>
90-
{/* User dropdown skeleton */}
91-
<div className="w-full h-10 bg-muted animate-pulse rounded" />
110+
{/* User dropdown skeleton - match UserDropdown button styling */}
111+
<div className="w-full h-10 px-2 flex items-center justify-between bg-muted/50 animate-pulse rounded-md">
112+
<div className="flex items-center gap-2">
113+
{/* Avatar skeleton */}
114+
<div className="w-8 h-8 bg-muted animate-pulse rounded-full" />
115+
{/* Username skeleton */}
116+
<div className="w-20 h-4 bg-muted animate-pulse rounded" />
117+
</div>
118+
{/* Chevron icon skeleton */}
119+
<div className="w-4 h-4 bg-muted animate-pulse rounded" />
120+
</div>
92121
</SidebarFooter>
93122
</Sidebar>
94123
)

0 commit comments

Comments
 (0)