Skip to content

Commit 2694900

Browse files
authored
Merge pull request #108 from hisabi-app/claude/add-user-nav-sidebar-01HCZih5g77j3r3UZY9hs8ZY
Add user navigation menu to sidebar
2 parents 803abf3 + 17eb969 commit 2694900

5 files changed

Lines changed: 105 additions & 15 deletions

File tree

resources/css/app.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,18 @@
127127
@layer base {
128128
* {
129129
@apply border-border outline-ring/50;
130+
scroll-behavior: auto !important;
131+
scroll-snap-type: none !important;
132+
}
133+
html {
134+
scroll-behavior: auto !important;
135+
overscroll-behavior: none !important;
130136
}
131137
body {
132138
@apply bg-background text-foreground;
139+
scroll-behavior: auto !important;
140+
overscroll-behavior: none !important;
141+
overscroll-behavior-y: none !important;
133142
}
134143
}
135144

resources/js/Layouts/Authenticated.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { SidebarProvider, SidebarInset, SidebarTrigger } from '@/components/ui/s
44
import { AppSidebar } from '@/components/app-sidebar';
55
import RightSidebar from '@/components/RightSidebar';
66

7-
export default function Authenticated({ header, children }: { auth?: any; header?: React.ReactNode; children: React.ReactNode }) {
7+
export default function Authenticated({ auth, header, children }: { auth?: any; header?: React.ReactNode; children: React.ReactNode }) {
88
return (
99
<SidebarProvider>
10-
<AppSidebar />
10+
<AppSidebar auth={auth} />
1111
<SidebarInset>
1212
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4 sticky top-0 bg-background z-10 md:rounded-t-xl">
1313
<SidebarTrigger className="-ml-1" />

resources/js/components/app-sidebar.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { Link } from '@inertiajs/react';
22
import {
33
Receipt,
44
StorefrontIcon,
5-
SignOutIcon,
65
CirclesThreeIcon,
76
ChartDonutIcon
87
} from "@phosphor-icons/react"
@@ -19,6 +18,7 @@ import {
1918
SidebarMenuItem,
2019
} from "@/components/ui/sidebar"
2120
import ApplicationLogo from "@/components/Global/ApplicationLogo"
21+
import { UserNav } from "@/components/user-nav"
2222

2323
// Navigation items
2424
const items = [
@@ -44,7 +44,16 @@ const items = [
4444
},
4545
]
4646

47-
export function AppSidebar() {
47+
interface AppSidebarProps {
48+
auth?: {
49+
user: {
50+
name: string;
51+
email: string;
52+
};
53+
};
54+
}
55+
56+
export function AppSidebar({ auth }: AppSidebarProps) {
4857
return (
4958
<Sidebar collapsible="offcanvas" variant="inset">
5059
<SidebarHeader>
@@ -77,16 +86,7 @@ export function AppSidebar() {
7786
</SidebarGroup>
7887
</SidebarContent>
7988
<SidebarFooter>
80-
<SidebarMenu>
81-
<SidebarMenuItem>
82-
<SidebarMenuButton asChild>
83-
<Link href={route('logout')} method="post" as="button">
84-
<SignOutIcon />
85-
<span>Log Out</span>
86-
</Link>
87-
</SidebarMenuButton>
88-
</SidebarMenuItem>
89-
</SidebarMenu>
89+
{auth?.user && <UserNav user={auth.user} />}
9090
</SidebarFooter>
9191
</Sidebar>
9292
)

resources/js/components/ui/sidebar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) {
348348
<div
349349
data-slot="sidebar-footer"
350350
data-sidebar="footer"
351-
className={cn("flex flex-col gap-2 p-2", className)}
351+
className={cn("flex flex-col gap-2 p-2 mt-auto", className)}
352352
{...props}
353353
/>
354354
)
@@ -377,6 +377,7 @@ function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
377377
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
378378
className
379379
)}
380+
style={{ scrollBehavior: 'auto' }}
380381
{...props}
381382
/>
382383
)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { Link } from '@inertiajs/react';
2+
import { SignOut, CaretUpDown } from "@phosphor-icons/react";
3+
import {
4+
DropdownMenu,
5+
DropdownMenuContent,
6+
DropdownMenuItem,
7+
DropdownMenuTrigger,
8+
} from "@/components/ui/dropdown-menu";
9+
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
10+
import { SidebarMenu, SidebarMenuItem, useSidebar } from "@/components/ui/sidebar";
11+
import { cn } from "@/lib/utils";
12+
13+
interface UserNavProps {
14+
user: {
15+
name: string;
16+
email: string;
17+
};
18+
}
19+
20+
function getInitials(name: string): string {
21+
const names = name.trim().split(' ');
22+
if (names.length >= 2) {
23+
return (names[0][0] + names[names.length - 1][0]).toUpperCase();
24+
}
25+
return name.substring(0, 2).toUpperCase();
26+
}
27+
28+
export function UserNav({ user }: UserNavProps) {
29+
const { state } = useSidebar();
30+
const initials = getInitials(user.name);
31+
32+
return (
33+
<SidebarMenu>
34+
<SidebarMenuItem>
35+
<DropdownMenu>
36+
<DropdownMenuTrigger asChild>
37+
<button
38+
className={cn(
39+
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding]",
40+
"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2",
41+
"active:bg-sidebar-accent active:text-sidebar-accent-foreground",
42+
"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
43+
"h-12 group-data-[collapsible=icon]:p-0",
44+
"group-data-[collapsible=icon]:size-8"
45+
)}
46+
>
47+
<Avatar className="size-8 rounded-lg">
48+
<AvatarFallback className="rounded-lg">
49+
{initials}
50+
</AvatarFallback>
51+
</Avatar>
52+
<div className="grid flex-1 text-left text-sm leading-tight">
53+
<span className="truncate font-semibold">{user.name}</span>
54+
<span className="truncate text-xs">{user.email}</span>
55+
</div>
56+
<CaretUpDown className="ml-auto size-4" />
57+
</button>
58+
</DropdownMenuTrigger>
59+
<DropdownMenuContent
60+
className="w-56"
61+
align="end"
62+
side={state === "collapsed" ? "right" : "top"}
63+
>
64+
<DropdownMenuItem asChild>
65+
<Link
66+
href={route('logout')}
67+
method="post"
68+
as="button"
69+
className="cursor-pointer w-full"
70+
>
71+
<SignOut className="mr-2 size-4" />
72+
<span>Log out</span>
73+
</Link>
74+
</DropdownMenuItem>
75+
</DropdownMenuContent>
76+
</DropdownMenu>
77+
</SidebarMenuItem>
78+
</SidebarMenu>
79+
);
80+
}

0 commit comments

Comments
 (0)