Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
"singleQuote": true,
"singleAttributePerLine": false,
"htmlWhitespaceSensitivity": "css",
"printWidth": 150,
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-tailwindcss"],
"tailwindFunctions": ["clsx", "cn"],
"printWidth": 80,
"plugins": [
"prettier-plugin-organize-imports",
"prettier-plugin-tailwindcss"
],
"tailwindFunctions": [
"clsx",
"cn"
],
"tailwindStylesheet": "resources/css/app.css",
"tabWidth": 4,
"overrides": [
Expand Down
4 changes: 3 additions & 1 deletion resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

@theme {
--font-sans:
'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
'Instrument Sans', ui-sans-serif, system-ui, sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';

--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
Expand Down
8 changes: 6 additions & 2 deletions resources/js/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import { initializeTheme } from './hooks/use-appearance';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
title: (title) => title ? `${title} - ${appName}` : appName,
resolve: (name) => resolvePageComponent(`./pages/${name}.tsx`, import.meta.glob('./pages/**/*.tsx')),
title: (title) => (title ? `${title} - ${appName}` : appName),
resolve: (name) =>
resolvePageComponent(
`./pages/${name}.tsx`,
import.meta.glob('./pages/**/*.tsx'),
),
setup({ el, App, props }) {
const root = createRoot(el);

Expand Down
11 changes: 9 additions & 2 deletions resources/js/components/app-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ interface AppContentProps extends React.ComponentProps<'main'> {
variant?: 'header' | 'sidebar';
}

export function AppContent({ variant = 'header', children, ...props }: AppContentProps) {
export function AppContent({
variant = 'header',
children,
...props
}: AppContentProps) {
if (variant === 'sidebar') {
return <SidebarInset {...props}>{children}</SidebarInset>;
}

return (
<main className="mx-auto flex h-full w-full max-w-7xl flex-1 flex-col gap-4 rounded-xl" {...props}>
<main
className="mx-auto flex h-full w-full max-w-7xl flex-1 flex-col gap-4 rounded-xl"
{...props}
>
{children}
</main>
);
Expand Down
137 changes: 114 additions & 23 deletions resources/js/components/app-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@ import { Breadcrumbs } from '@/components/breadcrumbs';
import { Icon } from '@/components/icon';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { NavigationMenu, NavigationMenuItem, NavigationMenuList, navigationMenuTriggerStyle } from '@/components/ui/navigation-menu';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuList,
navigationMenuTriggerStyle,
} from '@/components/ui/navigation-menu';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { UserMenuContent } from '@/components/user-menu-content';
import { useInitials } from '@/hooks/use-initials';
import { cn } from '@/lib/utils';
Expand Down Expand Up @@ -37,7 +57,8 @@ const rightNavItems: NavItem[] = [
},
];

const activeItemStyles = 'text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100';
const activeItemStyles =
'text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100';

interface AppHeaderProps {
breadcrumbs?: BreadcrumbItem[];
Expand All @@ -55,21 +76,39 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
<div className="lg:hidden">
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="mr-2 h-[34px] w-[34px]">
<Button
variant="ghost"
size="icon"
className="mr-2 h-[34px] w-[34px]"
>
<Menu className="h-5 w-5" />
</Button>
</SheetTrigger>
<SheetContent side="left" className="flex h-full w-64 flex-col items-stretch justify-between bg-sidebar">
<SheetTitle className="sr-only">Navigation Menu</SheetTitle>
<SheetContent
side="left"
className="flex h-full w-64 flex-col items-stretch justify-between bg-sidebar"
>
<SheetTitle className="sr-only">
Navigation Menu
</SheetTitle>
<SheetHeader className="flex justify-start text-left">
<AppLogoIcon className="h-6 w-6 fill-current text-black dark:text-white" />
</SheetHeader>
<div className="flex h-full flex-1 flex-col space-y-4 p-4">
<div className="flex h-full flex-col justify-between text-sm">
<div className="flex flex-col space-y-4">
{mainNavItems.map((item) => (
<Link key={item.title} href={item.href} className="flex items-center space-x-2 font-medium">
{item.icon && <Icon iconNode={item.icon} className="h-5 w-5" />}
<Link
key={item.title}
href={item.href}
className="flex items-center space-x-2 font-medium"
>
{item.icon && (
<Icon
iconNode={item.icon}
className="h-5 w-5"
/>
)}
<span>{item.title}</span>
</Link>
))}
Expand All @@ -79,12 +118,22 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
{rightNavItems.map((item) => (
<a
key={item.title}
href={typeof item.href === 'string' ? item.href : item.href.url}
href={
typeof item.href ===
'string'
? item.href
: item.href.url
}
target="_blank"
rel="noopener noreferrer"
className="flex items-center space-x-2 font-medium"
>
{item.icon && <Icon iconNode={item.icon} className="h-5 w-5" />}
{item.icon && (
<Icon
iconNode={item.icon}
className="h-5 w-5"
/>
)}
<span>{item.title}</span>
</a>
))}
Expand All @@ -95,7 +144,11 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
</Sheet>
</div>

<Link href={dashboard()} prefetch className="flex items-center space-x-2">
<Link
href={dashboard()}
prefetch
className="flex items-center space-x-2"
>
<AppLogo />
</Link>

Expand All @@ -104,16 +157,29 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
<NavigationMenu className="flex h-full items-stretch">
<NavigationMenuList className="flex h-full items-stretch space-x-2">
{mainNavItems.map((item, index) => (
<NavigationMenuItem key={index} className="relative flex h-full items-center">
<NavigationMenuItem
key={index}
className="relative flex h-full items-center"
>
<Link
href={item.href}
className={cn(
navigationMenuTriggerStyle(),
page.url === (typeof item.href === 'string' ? item.href : item.href.url) && activeItemStyles,
page.url ===
(typeof item.href ===
'string'
? item.href
: item.href.url) &&
activeItemStyles,
'h-9 cursor-pointer px-3',
)}
>
{item.icon && <Icon iconNode={item.icon} className="mr-2 h-4 w-4" />}
{item.icon && (
<Icon
iconNode={item.icon}
className="mr-2 h-4 w-4"
/>
)}
{item.title}
</Link>
{page.url === item.href && (
Expand All @@ -127,22 +193,41 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {

<div className="ml-auto flex items-center space-x-2">
<div className="relative flex items-center space-x-1">
<Button variant="ghost" size="icon" className="group h-9 w-9 cursor-pointer">
<Button
variant="ghost"
size="icon"
className="group h-9 w-9 cursor-pointer"
>
<Search className="!size-5 opacity-80 group-hover:opacity-100" />
</Button>
<div className="hidden lg:flex">
{rightNavItems.map((item) => (
<TooltipProvider key={item.title} delayDuration={0}>
<TooltipProvider
key={item.title}
delayDuration={0}
>
<Tooltip>
<TooltipTrigger>
<a
href={typeof item.href === 'string' ? item.href : item.href.url}
href={
typeof item.href ===
'string'
? item.href
: item.href.url
}
target="_blank"
rel="noopener noreferrer"
className="group ml-1 inline-flex h-9 w-9 items-center justify-center rounded-md bg-transparent p-0 text-sm font-medium text-accent-foreground ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50"
>
<span className="sr-only">{item.title}</span>
{item.icon && <Icon iconNode={item.icon} className="size-5 opacity-80 group-hover:opacity-100" />}
<span className="sr-only">
{item.title}
</span>
{item.icon && (
<Icon
iconNode={item.icon}
className="size-5 opacity-80 group-hover:opacity-100"
/>
)}
</a>
</TooltipTrigger>
<TooltipContent>
Expand All @@ -155,9 +240,15 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
</div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="size-10 rounded-full p-1">
<Button
variant="ghost"
className="size-10 rounded-full p-1"
>
<Avatar className="size-8 overflow-hidden rounded-full">
<AvatarImage src={auth.user.avatar} alt={auth.user.name} />
<AvatarImage
src={auth.user.avatar}
alt={auth.user.name}
/>
<AvatarFallback className="rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white">
{getInitials(auth.user.name)}
</AvatarFallback>
Expand Down
4 changes: 3 additions & 1 deletion resources/js/components/app-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export default function AppLogo() {
<AppLogoIcon className="size-5 fill-current text-white dark:text-black" />
</div>
<div className="ml-1 grid flex-1 text-left text-sm">
<span className="mb-0.5 truncate leading-tight font-semibold">Laravel Starter Kit</span>
<span className="mb-0.5 truncate leading-tight font-semibold">
Laravel Starter Kit
</span>
</div>
</>
);
Expand Down
4 changes: 3 additions & 1 deletion resources/js/components/app-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export function AppShell({ children, variant = 'header' }: AppShellProps) {
const isOpen = usePage<SharedData>().props.sidebarOpen;

if (variant === 'header') {
return <div className="flex min-h-screen w-full flex-col">{children}</div>;
return (
<div className="flex min-h-screen w-full flex-col">{children}</div>
);
}

return <SidebarProvider defaultOpen={isOpen}>{children}</SidebarProvider>;
Expand Down
6 changes: 5 additions & 1 deletion resources/js/components/app-sidebar-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { Breadcrumbs } from '@/components/breadcrumbs';
import { SidebarTrigger } from '@/components/ui/sidebar';
import { type BreadcrumbItem as BreadcrumbItemType } from '@/types';

export function AppSidebarHeader({ breadcrumbs = [] }: { breadcrumbs?: BreadcrumbItemType[] }) {
export function AppSidebarHeader({
breadcrumbs = [],
}: {
breadcrumbs?: BreadcrumbItemType[];
}) {
return (
<header className="flex h-16 shrink-0 items-center gap-2 border-b border-sidebar-border/50 px-6 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12 md:px-4">
<div className="flex items-center gap-2">
Expand Down
10 changes: 9 additions & 1 deletion resources/js/components/app-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { NavFooter } from '@/components/nav-footer';
import { NavMain } from '@/components/nav-main';
import { NavUser } from '@/components/nav-user';
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar';
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from '@/components/ui/sidebar';
import { dashboard } from '@/routes';
import { type NavItem } from '@/types';
import { Link } from '@inertiajs/react';
Expand Down
Loading