60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { ReactNode } from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Menu } from "lucide-react";
|
|
import { useSidebarContext } from "@/components/layout/sidebar-context";
|
|
import { useIsMobile } from "@/hooks/use-mobile";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface PageHeaderProps {
|
|
title: string;
|
|
description?: string | ReactNode;
|
|
actions?: ReactNode;
|
|
rightContent?: ReactNode;
|
|
}
|
|
|
|
export function PageHeader({
|
|
title,
|
|
description,
|
|
actions,
|
|
rightContent,
|
|
}: PageHeaderProps) {
|
|
const { setOpen } = useSidebarContext();
|
|
const isMobile = useIsMobile();
|
|
|
|
return (
|
|
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
|
<div className="flex items-center gap-3">
|
|
{isMobile && (
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={() => setOpen(true)}
|
|
className="shrink-0"
|
|
>
|
|
<Menu className="w-5 h-5" />
|
|
</Button>
|
|
)}
|
|
<div>
|
|
<h1 className="text-lg md:text-2xl font-bold text-foreground">{title}</h1>
|
|
{description && (
|
|
<div className="text-xs md:text-base text-muted-foreground mt-1">{description}</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{(rightContent || actions) && (
|
|
<div className="flex items-center gap-2 flex-wrap">
|
|
{rightContent}
|
|
{actions && (
|
|
<div className={cn("flex gap-2", isMobile && "flex-wrap")}>
|
|
{actions}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|