page-shell.tsx 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import Link from "next/link";
  2. import type { ReactNode } from "react";
  3. interface PageShellProps {
  4. title: string;
  5. /** Optional subtitle under the title */
  6. description?: string;
  7. children: ReactNode;
  8. /** Optional return control shown top-left above the title */
  9. backHref?: string;
  10. backLabel?: string;
  11. }
  12. /**
  13. * Consistent page header (title + description) used by every route.
  14. */
  15. export function PageShell({
  16. title,
  17. description,
  18. children,
  19. backHref,
  20. backLabel = "Back",
  21. }: PageShellProps) {
  22. return (
  23. <div className="mx-auto w-full max-w-6xl">
  24. <div className="mb-6 sm:mb-8">
  25. {backHref ? (
  26. <Link
  27. href={backHref}
  28. className="mb-3 inline-flex min-h-10 items-center gap-1.5 py-1 text-sm text-muted-foreground transition-colors hover:text-foreground sm:mb-4"
  29. >
  30. <span aria-hidden className="text-base leading-none">
  31. </span>
  32. {backLabel}
  33. </Link>
  34. ) : null}
  35. <h1 className="font-display text-xl font-semibold tracking-tight sm:text-2xl">
  36. {title}
  37. </h1>
  38. {description ? (
  39. <p className="mt-1.5 text-sm leading-relaxed text-muted-foreground">
  40. {description}
  41. </p>
  42. ) : null}
  43. </div>
  44. {children}
  45. </div>
  46. );
  47. }