feat(app): add base layout
Some checks failed
Build and Push Docker Image / build (push) Failing after 48s

This commit is contained in:
Lars Hampe 2024-09-30 23:21:05 +02:00
parent 643fe98c39
commit f0eca6885d
5 changed files with 214 additions and 13 deletions

33
apps/app/biome.json Normal file
View File

@ -0,0 +1,33 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.2/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": ["*.gen.ts"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noChildrenProp": "off"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
}

View File

@ -0,0 +1,56 @@
import { CircleUser } from 'lucide-react'
import {
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@boring.tools/ui'
import { SignOutButton, useUser } from '@clerk/clerk-react'
import type { ReactNode } from 'react'
import { Navigation } from './Navigation'
import { NavigationMobile } from './NavigationMobile'
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"></div>
<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>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>
<SignOutButton>
<button type="button">Sign out</button>
</SignOutButton>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</header>
<main className="flex flex-1 flex-col gap-4 p-4 lg:gap-6 lg:p-6">
{children}
</main>
</div>
</div>
)
}

View File

@ -0,0 +1,58 @@
import {
Button,
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@boring.tools/ui'
import { Link } from '@tanstack/react-router'
import { BellIcon, HomeIcon } from 'lucide-react'
export const Navigation = () => {
return (
<div className="hidden border-r bg-muted/40 md:block">
<div className="flex h-full max-h-screen flex-col gap-2">
<div className="flex h-14 items-center border-b px-4 lg:h-[60px] lg:px-6">
<Link to="/" className="flex items-center gap-2 font-semibold">
<span className="">boring.tools</span>
</Link>
<Button variant="outline" size="icon" className="ml-auto h-8 w-8">
<BellIcon className="h-4 w-4" />
<span className="sr-only">Toggle notifications</span>
</Button>
</div>
<div className="flex-1">
<nav className="grid items-start px-2 text-sm font-medium lg:px-4">
<Link
href="#"
className="flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary"
activeProps={{ className: 'bg-muted text-primary' }}
>
<HomeIcon className="h-4 w-4" />
Dashboard
</Link>
</nav>
</div>
<div className="mt-auto p-4">
<Card>
<CardHeader className="p-2 pt-0 md:p-4">
<CardTitle>More Infos</CardTitle>
<CardDescription>
If you want more informations about boring.tools, visit our
documenation!
</CardDescription>
</CardHeader>
<CardContent className="p-2 pt-0 md:p-4 md:pt-0">
<a href="https://boring.tools">
<Button size="sm" className="w-full">
Documentation
</Button>
</a>
</CardContent>
</Card>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,64 @@
import {
Button,
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
Sheet,
SheetContent,
SheetTrigger,
} from '@boring.tools/ui'
import { Link } from '@tanstack/react-router'
import { HomeIcon, MenuIcon } from 'lucide-react'
export const NavigationMobile = () => {
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="outline" size="icon" className="shrink-0 md:hidden">
<MenuIcon className="h-5 w-5" />
<span className="sr-only">Toggle navigation menu</span>
</Button>
</SheetTrigger>
<SheetContent side="left" className="flex flex-col">
<nav className="grid gap-2 text-lg font-medium">
<Link
to="/"
className="flex items-center gap-2 text-lg font-semibold"
>
<span className="sr-only">boring.tools</span>
</Link>
<Link
to="/"
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2 hover:text-foreground"
activeProps={{
className: 'bg-muted text-foreground',
}}
>
<HomeIcon className="h-5 w-5" />
Dashboard
</Link>
</nav>
<div className="mt-auto">
<Card>
<CardHeader className="p-2 pt-0 md:p-4">
<CardTitle>More Infos</CardTitle>
<CardDescription>
If you want more informations about boring.tools, visit our
documenation!
</CardDescription>
</CardHeader>
<CardContent className="p-2 pt-0 md:p-4 md:pt-0">
<a href="https://boring.tools">
<Button size="sm" className="w-full">
Documentation
</Button>
</a>
</CardContent>
</Card>
</div>
</SheetContent>
</Sheet>
)
}

View File

@ -2,6 +2,7 @@ import { ThemeToggle } from '@boring.tools/ui'
import { SignIn, SignedIn, SignedOut, UserButton } from '@clerk/clerk-react'
import { Link, Outlet, createRootRoute } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
import { Layout } from '../components/Layout'
export const Route = createRootRoute({
component: () => (
@ -12,21 +13,10 @@ export const Route = createRootRoute({
</div>
</SignedOut>
<SignedIn>
<>
<div className="p-2 flex gap-2">
<Link to="/" className="[&.active]:font-bold">
Home
</Link>{' '}
<Link to="/about" className="[&.active]:font-bold">
About
</Link>
<ThemeToggle />
<UserButton />
</div>
<hr />
<Layout>
<Outlet />
{!import.meta.env.PROD && <TanStackRouterDevtools />}
</>
</Layout>
</SignedIn>
</>
),