feat(app): use new sidebar navigation
All checks were successful
Build and Push Docker Image / tests (push) Successful in 38s
Build and Push Docker Image / build (push) Successful in 2m26s

This commit is contained in:
Lars Hampe 2024-10-20 09:43:29 +02:00
parent 094775a3a0
commit 99c3452a5f
6 changed files with 245 additions and 70 deletions

View File

@ -1,58 +1,43 @@
import {
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@boring.tools/ui'
import { SignOutButton, useUser } from '@clerk/clerk-react'
import { Link } from '@tanstack/react-router'
import { SidebarInset, SidebarTrigger } from '@boring.tools/ui'
import type { ReactNode } from 'react'
import { Navigation } from './Navigation'
import { NavigationMobile } from './NavigationMobile'
import { Sidebar } from './Sidebar'
export const description =
'A products dashboard with a sidebar navigation and a main content area. The dashboard has a header with a search input and a user menu. The sidebar has a logo, navigation links, and a card with a call to action. The main content area shows an empty state with a call to action.'
export const Layout = ({ children }: { children: ReactNode | ReactNode[] }) => {
const { user } = useUser()
return (
<div className="grid min-h-screen w-full md:grid-cols-[220px_1fr] lg:grid-cols-[280px_1fr]">
<Navigation />
<div className="flex flex-col">
<header className="flex h-14 items-center gap-4 border-b bg-muted/40 px-4 lg:h-[60px] lg:px-6">
<NavigationMobile />
<div className="w-full flex-1" />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="icon"
className="overflow-hidden rounded-full"
>
<img src={user?.imageUrl} alt={user?.fullName ?? 'Avatar'} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Settings</DropdownMenuLabel>
<DropdownMenuItem asChild>
<Link to="/user">Profile</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<SignOutButton>
<button type="button">Sign out</button>
</SignOutButton>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<>
{/* <Navigation /> */}
<Sidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
{/* <Separator orientation="vertical" className="mr-2 h-4" /> */}
{/* <Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb> */}
</div>
</header>
<main className="flex flex-1 flex-col gap-4 p-4 lg:gap-6 lg:p-6">
{children}
</main>
</div>
</div>
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
<div className="flex flex-col">
<main className="flex flex-1 flex-col gap-4 p-4 lg:gap-6 lg:p-6">
{children}
</main>
</div>
</div>
</SidebarInset>
</>
)
}

View File

@ -0,0 +1,91 @@
import { FileStackIcon } from 'lucide-react'
import {
Collapsible,
Sidebar as SidebarComp,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from '@boring.tools/ui'
import { Link } from '@tanstack/react-router'
import { SidebarUser } from './SidebarUser'
const items = [
{
title: 'Changelog',
url: '/changelog',
icon: FileStackIcon,
isActive: true,
},
]
export function Sidebar() {
return (
<SidebarComp>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
<Link to="/">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
BT
</div>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">boring.tools</span>
</div>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarMenu>
{items.map((item) => (
<Collapsible key={item.title} asChild defaultOpen={item.isActive}>
<SidebarMenuItem>
<SidebarMenuButton asChild tooltip={item.title}>
<Link to={item.url}>
<item.icon />
<span>{item.title}</span>
</Link>
</SidebarMenuButton>
{/* {item.items?.length ? (
<>
<CollapsibleTrigger asChild>
<SidebarMenuAction className="data-[state=open]:rotate-90">
<ChevronRightIcon />
<span className="sr-only">Toggle</span>
</SidebarMenuAction>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.items?.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton asChild>
<Link to={subItem.url}>
<span>{subItem.title}</span>
</Link>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</CollapsibleContent>
</>
) : null} */}
</SidebarMenuItem>
</Collapsible>
))}
</SidebarMenu>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<SidebarUser />
</SidebarFooter>
</SidebarComp>
)
}

View File

@ -0,0 +1,96 @@
import { ChevronsUpDown } from 'lucide-react'
import {
Avatar,
AvatarFallback,
AvatarImage,
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from '@boring.tools/ui'
import { SignOutButton, useUser } from '@clerk/clerk-react'
import { Link } from '@tanstack/react-router'
export function SidebarUser() {
const { isMobile } = useSidebar()
const { user } = useUser()
return (
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage
src={user?.imageUrl}
alt={user?.fullName ?? 'Avatar'}
/>
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">{user?.fullName}</span>
<span className="truncate text-xs">
{user?.primaryEmailAddress?.emailAddress}
</span>
</div>
<ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
side={isMobile ? 'bottom' : 'right'}
align="end"
sideOffset={4}
>
<DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage
src={user?.imageUrl}
alt={user?.fullName ?? 'Avatar'}
/>
<AvatarFallback className="rounded-lg">
{user?.firstName?.substring(0, 1)}
{user?.lastName?.substring(0, 1)}
</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">
{user?.fullName}
</span>
<span className="truncate text-xs">
{user?.primaryEmailAddress?.emailAddress}
</span>
</div>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<Link to="/user">Profile</Link>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
<SignOutButton>
<button type="button">Sign out</button>
</SignOutButton>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
)
}

View File

@ -1,4 +1,8 @@
import { ThemeProvider, TooltipProvider } from '@boring.tools/ui'
import {
SidebarProvider,
ThemeProvider,
TooltipProvider,
} from '@boring.tools/ui'
import { ClerkProvider } from '@clerk/clerk-react'
import { RouterProvider, createRouter } from '@tanstack/react-router'
import { StrictMode } from 'react'
@ -34,22 +38,24 @@ if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)
root.render(
<StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
<ThemeProvider defaultTheme="dark" storageKey="ui-theme">
<TooltipProvider delayDuration={350}>
<QueryClientProvider client={queryClient}>
{import.meta.env.PROD && (
<script
defer
src="https://umami.hashdot.co/script.js"
data-website-id="446678cc-e2d8-4b6f-8e8f-389cd7f6db28"
/>
)}
<RouterProvider router={router} />
</QueryClientProvider>
</TooltipProvider>
</ThemeProvider>
</ClerkProvider>
<SidebarProvider>
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
<ThemeProvider defaultTheme="dark" storageKey="ui-theme">
<TooltipProvider delayDuration={350}>
<QueryClientProvider client={queryClient}>
{import.meta.env.PROD && (
<script
defer
src="https://umami.hashdot.co/script.js"
data-website-id="446678cc-e2d8-4b6f-8e8f-389cd7f6db28"
/>
)}
<RouterProvider router={router} />
</QueryClientProvider>
</TooltipProvider>
</ThemeProvider>
</ClerkProvider>
</SidebarProvider>
</StrictMode>,
)
}

View File

@ -1,8 +1,5 @@
import { VersionUpdateInput } from '@boring.tools/schema'
import {
Alert,
AlertDescription,
AlertTitle,
Button,
Calendar,
Form,
@ -44,7 +41,7 @@ import {
} from '../hooks/useChangelog'
import '@mdxeditor/editor/style.css'
import { format } from 'date-fns'
import { CalendarIcon, TriangleAlertIcon } from 'lucide-react'
import { CalendarIcon } from 'lucide-react'
import { useEffect, useRef } from 'react'
import { ChangelogVersionDelete } from '../components/Changelog/VersionDelete'
import { VersionStatus } from '../components/Changelog/VersionStatus'

View File

@ -1 +1 @@
{"root":["./src/main.tsx","./src/routeTree.gen.ts","./src/vite-env.d.ts","./src/components/Layout.tsx","./src/components/Navigation.tsx","./src/components/NavigationMobile.tsx","./src/components/Changelog/Delete.tsx","./src/components/Changelog/VersionStatus.tsx","./src/hooks/useChangelog.ts","./src/routes/__root.tsx","./src/routes/changelog.$id.edit.lazy.tsx","./src/routes/changelog.$id.index.lazy.tsx","./src/routes/changelog.$id.lazy.tsx","./src/routes/changelog.$id.version.$versionId.tsx","./src/routes/changelog.$id.versionCreate.lazy.tsx","./src/routes/changelog.create.lazy.tsx","./src/routes/changelog.index.lazy.tsx","./src/routes/index.lazy.tsx","./src/routes/user/index.lazy.tsx","./src/utils/navigation-routes.ts","./src/utils/queryFetch.ts"],"version":"5.6.2"}
{"root":["./src/main.tsx","./src/routeTree.gen.ts","./src/vite-env.d.ts","./src/components/Layout.tsx","./src/components/Navigation.tsx","./src/components/NavigationMobile.tsx","./src/components/Sidebar.tsx","./src/components/SidebarUser.tsx","./src/components/Changelog/Delete.tsx","./src/components/Changelog/VersionDelete.tsx","./src/components/Changelog/VersionStatus.tsx","./src/hooks/useChangelog.ts","./src/routes/__root.tsx","./src/routes/changelog.$id.edit.lazy.tsx","./src/routes/changelog.$id.index.lazy.tsx","./src/routes/changelog.$id.lazy.tsx","./src/routes/changelog.$id.version.$versionId.tsx","./src/routes/changelog.$id.versionCreate.lazy.tsx","./src/routes/changelog.create.lazy.tsx","./src/routes/changelog.index.lazy.tsx","./src/routes/index.lazy.tsx","./src/routes/user/index.lazy.tsx","./src/utils/navigation-routes.ts","./src/utils/queryFetch.ts"],"version":"5.6.2"}