Skip to content

Commit e641190

Browse files
committed
updates and improvements
1 parent 40dc52b commit e641190

19 files changed

+190
-179
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Fragment } from 'react'
2+
import {
3+
Breadcrumb,
4+
BreadcrumbItem,
5+
BreadcrumbLink,
6+
BreadcrumbList,
7+
BreadcrumbPage,
8+
BreadcrumbSeparator,
9+
} from "@/components/ui/breadcrumb"
10+
import { type BreadcrumbItem as BreadcrumbItemType } from '@/types'
11+
import { Separator } from "@/components/ui/separator"
12+
import { SidebarTrigger } from "@/components/ui/sidebar"
13+
14+
export function AppHeader({ breadcrumbs = [] }: { breadcrumbs?: BreadcrumbItemType[] }) {
15+
return (
16+
<header className="flex h-16 shrink-0 items-center w-full justify-between gap-2 border-b px-4">
17+
<div className="flex items-center gap-2">
18+
<SidebarTrigger className="-ml-1" />
19+
{breadcrumbs.length > 0 && (
20+
<>
21+
<Separator orientation="vertical" className="mr-2 h-4" />
22+
<Breadcrumb>
23+
<BreadcrumbList>
24+
{breadcrumbs.map((item, index) => {
25+
const isLast = index === breadcrumbs.length - 1;
26+
27+
return (
28+
<Fragment key={index}>
29+
<BreadcrumbItem>
30+
{isLast ? (
31+
<BreadcrumbPage>{item.title}</BreadcrumbPage>
32+
) : (
33+
<BreadcrumbLink href={item.href}>
34+
{item.title}
35+
</BreadcrumbLink>
36+
)}
37+
</BreadcrumbItem>
38+
{!isLast && (
39+
<BreadcrumbSeparator />
40+
)}
41+
</Fragment>
42+
);
43+
})}
44+
</BreadcrumbList>
45+
</Breadcrumb>
46+
</>
47+
)}
48+
</div>
49+
</header>
50+
)
51+
}

resources/js/components/app-sidebar.tsx

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Link } from "@inertiajs/react"
33
import { NavMain } from "@/components/nav-main"
44
import { NavFooter } from "@/components/nav-footer"
55
import { NavUser } from "@/components/nav-user"
6-
import { type NavItemType } from '@/types'
6+
import { type NavItem } from '@/types'
77
import {
88
Sidebar,
99
SidebarContent,
@@ -12,18 +12,21 @@ import {
1212
SidebarMenu,
1313
SidebarMenuButton,
1414
SidebarMenuItem,
15+
SidebarProvider,
16+
SidebarInset,
1517
} from "@/components/ui/sidebar"
1618
import ApplicationLogo from "./application-logo"
19+
import { useState } from "react"
1720

18-
const mainNavItems: NavItemType[] = [
21+
const mainNavItems: NavItem[] = [
1922
{
2023
title: "Dashboard",
2124
url: "/dashboard",
2225
icon: LayoutDashboard,
2326
},
2427
]
2528

26-
const footerNavItems: NavItemType[] = [
29+
const footerNavItems: NavItem[] = [
2730
{
2831
title: "Repository",
2932
url: "https://github.com/laravel/react-starter-kit",
@@ -36,35 +39,57 @@ const footerNavItems: NavItemType[] = [
3639
},
3740
]
3841

39-
export function AppSidebar() {
42+
export function AppSidebar({ children }: { children: React.ReactNode }) {
43+
const [isOpen, setIsOpen] = useState(() =>
44+
typeof window !== 'undefined' ?
45+
localStorage.getItem('sidebar') !== 'false' :
46+
true
47+
);
48+
49+
const handleSidebarChange = (open: boolean) => {
50+
setIsOpen(open);
51+
if (typeof window !== 'undefined') {
52+
localStorage.setItem('sidebar', String(open));
53+
}
54+
};
55+
4056
return (
41-
<Sidebar collapsible="icon">
42-
<SidebarHeader>
43-
<SidebarMenu>
44-
<SidebarMenuItem>
45-
<SidebarMenuButton size="lg" asChild>
46-
<Link href="/dashboard" className="flex items-center gap-3" prefetch>
47-
<div className="flex aspect-square size-8 items-center justify-center rounded-md bg-sidebar-primary text-sidebar-primary-foreground">
48-
<ApplicationLogo className="size-5 text-white fill-current" />
49-
</div>
50-
<div className="grid flex-1 text-left text-sm leading-tight">
51-
<span className="truncate font-semibold">Laravel</span>
52-
<span className="truncate text-xs">Starter Kit</span>
53-
</div>
54-
</Link>
55-
</SidebarMenuButton>
56-
</SidebarMenuItem>
57-
</SidebarMenu>
58-
</SidebarHeader>
57+
<SidebarProvider
58+
defaultOpen={isOpen}
59+
open={isOpen}
60+
onOpenChange={handleSidebarChange}
61+
>
62+
<Sidebar collapsible="icon">
63+
<SidebarHeader>
64+
<SidebarMenu>
65+
<SidebarMenuItem>
66+
<SidebarMenuButton size="lg" asChild>
67+
<Link href="/dashboard" className="flex items-center gap-3" prefetch>
68+
<div className="flex aspect-square size-8 items-center justify-center rounded-md bg-sidebar-primary text-sidebar-primary-foreground">
69+
<ApplicationLogo className="size-5 text-white fill-current" />
70+
</div>
71+
<div className="grid flex-1 text-left text-sm leading-tight">
72+
<span className="truncate font-semibold">Laravel</span>
73+
<span className="truncate text-xs">Starter Kit</span>
74+
</div>
75+
</Link>
76+
</SidebarMenuButton>
77+
</SidebarMenuItem>
78+
</SidebarMenu>
79+
</SidebarHeader>
5980

60-
<SidebarContent>
61-
<NavMain items={mainNavItems} />
62-
</SidebarContent>
81+
<SidebarContent>
82+
<NavMain items={mainNavItems} />
83+
</SidebarContent>
6384

64-
<SidebarFooter>
65-
<NavFooter items={footerNavItems} className="mt-auto" />
66-
<NavUser />
67-
</SidebarFooter>
68-
</Sidebar>
85+
<SidebarFooter>
86+
<NavFooter items={footerNavItems} className="mt-auto" />
87+
<NavUser />
88+
</SidebarFooter>
89+
</Sidebar>
90+
<SidebarInset>
91+
{children}
92+
</SidebarInset>
93+
</SidebarProvider>
6994
)
7095
}

resources/js/components/nav-footer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ExternalLink } from "lucide-react"
2-
import { type NavItemType } from '@/types'
2+
import { type NavItem } from '@/types'
33
import {
44
SidebarGroup,
55
SidebarGroupContent,
@@ -14,7 +14,7 @@ export function NavFooter({
1414
className,
1515
...props
1616
}: React.ComponentPropsWithoutRef<typeof SidebarGroup> & {
17-
items: NavItemType[]
17+
items: NavItem[]
1818
}) {
1919
return (
2020
<SidebarGroup

resources/js/components/nav-main.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type NavItemType } from '@/types'
1+
import { type NavItem } from '@/types'
22
import { Link, usePage } from "@inertiajs/react"
33
import {
44
SidebarGroup,
@@ -8,7 +8,7 @@ import {
88
} from "@/components/ui/sidebar"
99

1010
export function NavMain({ items = [] }: {
11-
items: NavItemType[]
11+
items: NavItem[]
1212
}) {
1313
const page = usePage();
1414
return (

resources/js/components/nav-user.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type UserType } from '@/types'
1+
import { type User } from '@/types'
22
import { ChevronsUpDown, LogOut, Settings } from "lucide-react"
33
import { Link, usePage } from '@inertiajs/react'
44
import {
@@ -21,16 +21,11 @@ import {
2121
SidebarMenuItem,
2222
} from "@/components/ui/sidebar"
2323

24-
interface User {
25-
name: string
26-
email: string
27-
avatar?: string
28-
}
29-
3024
interface PageProps {
3125
auth: {
32-
user: UserType
26+
user: User
3327
}
28+
[key: string]: any;
3429
}
3530

3631
function getInitials(fullName: string): string {
@@ -40,7 +35,7 @@ function getInitials(fullName: string): string {
4035
return `${names[0].charAt(0)}${names[names.length - 1].charAt(0)}`.toUpperCase()
4136
}
4237

43-
function UserInfo({ user }: { user: UserType }) {
38+
function UserInfo({ user }: { user: User }) {
4439
return (
4540
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
4641
<Avatar className="h-8 w-8 rounded-md">
@@ -56,7 +51,7 @@ function UserInfo({ user }: { user: UserType }) {
5651
}
5752

5853
export function NavUser() {
59-
const { auth } = usePage().props
54+
const { auth } = usePage<PageProps>().props
6055

6156
return (
6257
<SidebarMenu>
Lines changed: 8 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,19 @@
1-
import { Fragment, useState } from 'react'
1+
import { Fragment } from 'react'
22
import { AppSidebar } from "@/components/app-sidebar"
3-
import {
4-
Breadcrumb,
5-
BreadcrumbItem,
6-
BreadcrumbLink,
7-
BreadcrumbList,
8-
BreadcrumbPage,
9-
BreadcrumbSeparator,
10-
} from "@/components/ui/breadcrumb"
11-
import { type BreadcrumbItemType } from '@/types'
12-
import { Separator } from "@/components/ui/separator"
13-
import {
14-
SidebarInset,
15-
SidebarProvider,
16-
SidebarTrigger,
17-
} from "@/components/ui/sidebar"
3+
import { AppHeader } from "@/components/app-header"
4+
import { type BreadcrumbItem } from '@/types'
185

196
export default function App({
207
children,
218
breadcrumbs = [],
229
}: {
2310
children: React.ReactNode
24-
breadcrumbs?: BreadcrumbItemType[]
11+
breadcrumbs?: BreadcrumbItem[]
2512
}) {
26-
27-
const [isOpen, setIsOpen] = useState(() =>
28-
typeof window !== 'undefined' ?
29-
localStorage.getItem('sidebar') !== 'false' :
30-
true
31-
);
32-
33-
const handleSidebarChange = (open: boolean) => {
34-
setIsOpen(open);
35-
if (typeof window !== 'undefined') {
36-
localStorage.setItem('sidebar', String(open));
37-
}
38-
};
39-
4013
return (
41-
<SidebarProvider
42-
defaultOpen={isOpen}
43-
open={isOpen}
44-
onOpenChange={handleSidebarChange}
45-
>
46-
<AppSidebar />
47-
<SidebarInset>
48-
<header className="flex h-16 shrink-0 items-center w-full justify-between gap-2 border-b px-4">
49-
<div className="flex items-center gap-2">
50-
<SidebarTrigger className="-ml-1" />
51-
{breadcrumbs.length > 0 && (
52-
<>
53-
<Separator orientation="vertical" className="mr-2 h-4" />
54-
<Breadcrumb>
55-
<BreadcrumbList>
56-
{breadcrumbs.map((item, index) => {
57-
const isLast = index === breadcrumbs.length - 1;
58-
59-
return (
60-
<Fragment key={index}>
61-
<BreadcrumbItem>
62-
{isLast ? (
63-
<BreadcrumbPage>{item.title}</BreadcrumbPage>
64-
) : (
65-
<BreadcrumbLink href={item.href}>
66-
{item.title}
67-
</BreadcrumbLink>
68-
)}
69-
</BreadcrumbItem>
70-
{!isLast && (
71-
<BreadcrumbSeparator />
72-
)}
73-
</Fragment>
74-
);
75-
})}
76-
</BreadcrumbList>
77-
</Breadcrumb>
78-
</>
79-
)}
80-
</div>
81-
</header>
82-
{children}
83-
</SidebarInset>
84-
</SidebarProvider>
14+
<AppSidebar>
15+
<AppHeader breadcrumbs={breadcrumbs} />
16+
{children}
17+
</AppSidebar>
8518
)
8619
}

resources/js/layouts/auth/auth-card-layout.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ export default function AuthCardLayout({
1818
title?: string
1919
description?: string
2020
}) {
21-
const name = usePage().props.name;
22-
const quote = usePage().props.quote;
2321

2422
return (
2523
<div className="flex min-h-svh flex-col items-center justify-center gap-6 bg-muted p-6 md:p-10">
26-
<div className="flex w-full max-w-sm flex-col gap-6">
24+
<div className="flex w-full max-w-md flex-col gap-6">
2725
<a href="#" className="flex items-center gap-2 self-center font-medium">
2826
<div className="flex h-10 w-10 items-center justify-center">
2927
<ApplicationLogo className="size-10 fill-current text-black" />
@@ -32,13 +30,13 @@ export default function AuthCardLayout({
3230

3331
<div className="flex flex-col gap-6">
3432
<Card>
35-
<CardHeader className="text-center">
33+
<CardHeader className="text-center p-10 pb-0">
3634
<CardTitle className="text-xl">{title}</CardTitle>
3735
<CardDescription>
3836
{description}
3937
</CardDescription>
4038
</CardHeader>
41-
<CardContent>
39+
<CardContent className="p-10">
4240
{children}
4341
</CardContent>
4442
</Card>

resources/js/layouts/auth/auth-simple-layout.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ export default function AuthSimpleLayout({
1313
title,
1414
description
1515
}: AuthLayoutProps) {
16-
const name = usePage().props.name;
17-
const quote = usePage().props.quote;
1816

1917
return (
2018
<div className="flex min-h-svh flex-col items-center justify-center gap-6 bg-background p-6 md:p-10">
@@ -25,10 +23,10 @@ export default function AuthSimpleLayout({
2523
href={route("home")}
2624
className="flex flex-col items-center gap-2 font-medium"
2725
>
28-
<div className="flex h-10 w-10 items-center justify-center rounded-md">
29-
<ApplicationLogo className="size-10 fill-current text-black dark:text-white" />
30-
</div>
31-
<span className="sr-only">{title}</span>
26+
<div className="flex h-10 w-10 items-center justify-center rounded-md">
27+
<ApplicationLogo className="size-10 fill-current text-black dark:text-white" />
28+
</div>
29+
<span className="sr-only">{title}</span>
3230
</Link>
3331
<h1 className="text-xl font-bold">{title}</h1>
3432
<p className="text-center text-sm">{description}</p>

0 commit comments

Comments
 (0)