356 lines
8.7 KiB
Markdown
356 lines
8.7 KiB
Markdown
# Page Template Guide
|
|
|
|
A consistent, reusable page layout system for all pages in the application.
|
|
|
|
## Features
|
|
|
|
- ✅ **Consistent Layout**: Left rail + sidebar + main content area
|
|
- ✅ **Responsive Design**: Works on all screen sizes
|
|
- ✅ **Sidebar Navigation**: Built-in support for left sidebar with active states
|
|
- ✅ **Hero Section**: Optional hero banner with icon, title, description, and actions
|
|
- ✅ **Utility Components**: Pre-built sections, cards, grids, and empty states
|
|
- ✅ **Type-safe**: Full TypeScript support
|
|
|
|
---
|
|
|
|
## Basic Usage
|
|
|
|
```tsx
|
|
import { PageTemplate } from "@/components/layout/page-template";
|
|
import { Home } from "lucide-react";
|
|
|
|
export default function MyPage() {
|
|
return (
|
|
<PageTemplate
|
|
hero={{
|
|
icon: Home,
|
|
title: "My Page Title",
|
|
description: "A brief description of what this page does",
|
|
}}
|
|
>
|
|
<div>Your page content here</div>
|
|
</PageTemplate>
|
|
);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## With Sidebar Navigation
|
|
|
|
```tsx
|
|
import { PageTemplate } from "@/components/layout/page-template";
|
|
import { Home, Settings, Users } from "lucide-react";
|
|
|
|
export default function MyPage() {
|
|
return (
|
|
<PageTemplate
|
|
sidebar={{
|
|
title: "My Section",
|
|
description: "Navigate through options",
|
|
items: [
|
|
{ title: "Home", icon: Home, href: "/home", isActive: true },
|
|
{ title: "Settings", icon: Settings, href: "/settings" },
|
|
{ title: "Users", icon: Users, href: "/users", badge: "3" },
|
|
],
|
|
footer: <p className="text-xs">Footer content</p>,
|
|
}}
|
|
hero={{
|
|
icon: Home,
|
|
title: "My Page",
|
|
description: "Page description",
|
|
actions: [
|
|
{
|
|
label: "Create New",
|
|
onClick: () => console.log("Create"),
|
|
icon: Plus,
|
|
},
|
|
],
|
|
}}
|
|
>
|
|
<div>Your content</div>
|
|
</PageTemplate>
|
|
);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Using Utility Components
|
|
|
|
### PageSection
|
|
|
|
Organized content sections with optional titles and actions:
|
|
|
|
```tsx
|
|
import { PageSection } from "@/components/layout/page-template";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
<PageSection
|
|
title="Recent Activity"
|
|
description="Your latest updates"
|
|
headerAction={<Button size="sm">View All</Button>}
|
|
>
|
|
<div>Section content</div>
|
|
</PageSection>
|
|
```
|
|
|
|
### PageCard
|
|
|
|
Styled cards with consistent padding and hover effects:
|
|
|
|
```tsx
|
|
import { PageCard } from "@/components/layout/page-template";
|
|
|
|
<PageCard padding="lg" hover>
|
|
<h3>Card Title</h3>
|
|
<p>Card content</p>
|
|
</PageCard>
|
|
```
|
|
|
|
### PageGrid
|
|
|
|
Responsive grid layouts:
|
|
|
|
```tsx
|
|
import { PageGrid } from "@/components/layout/page-template";
|
|
|
|
<PageGrid cols={3}>
|
|
<div>Item 1</div>
|
|
<div>Item 2</div>
|
|
<div>Item 3</div>
|
|
</PageGrid>
|
|
```
|
|
|
|
### PageEmptyState
|
|
|
|
Empty states with icon, title, description, and action:
|
|
|
|
```tsx
|
|
import { PageEmptyState } from "@/components/layout/page-template";
|
|
import { Inbox } from "lucide-react";
|
|
|
|
<PageEmptyState
|
|
icon={Inbox}
|
|
title="No messages yet"
|
|
description="Start a conversation to see messages here"
|
|
action={{
|
|
label: "New Message",
|
|
onClick: () => console.log("Create message"),
|
|
icon: Plus,
|
|
}}
|
|
/>
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Example
|
|
|
|
Here's a full example combining all components:
|
|
|
|
```tsx
|
|
"use client";
|
|
|
|
import { useParams } from "next/navigation";
|
|
import { Home, Settings, Users, Plus, Mail } from "lucide-react";
|
|
import {
|
|
PageTemplate,
|
|
PageSection,
|
|
PageCard,
|
|
PageGrid,
|
|
PageEmptyState,
|
|
} from "@/components/layout/page-template";
|
|
|
|
export default function DashboardPage() {
|
|
const params = useParams();
|
|
const workspace = params.workspace as string;
|
|
const projectId = params.projectId as string;
|
|
|
|
return (
|
|
<PageTemplate
|
|
sidebar={{
|
|
title: "Dashboard",
|
|
description: "Overview and insights",
|
|
items: [
|
|
{
|
|
title: "Overview",
|
|
icon: Home,
|
|
href: `/${workspace}/project/${projectId}/overview`,
|
|
isActive: true,
|
|
},
|
|
{
|
|
title: "Settings",
|
|
icon: Settings,
|
|
href: `/${workspace}/project/${projectId}/settings`,
|
|
},
|
|
{
|
|
title: "Users",
|
|
icon: Users,
|
|
href: `/${workspace}/project/${projectId}/users`,
|
|
badge: "12",
|
|
},
|
|
],
|
|
footer: (
|
|
<p className="text-xs text-muted-foreground">
|
|
Last updated 5 minutes ago
|
|
</p>
|
|
),
|
|
}}
|
|
hero={{
|
|
icon: Home,
|
|
title: "Dashboard",
|
|
description: "Welcome back! Here's what's happening.",
|
|
actions: [
|
|
{
|
|
label: "Create Report",
|
|
onClick: () => console.log("Create report"),
|
|
icon: Plus,
|
|
},
|
|
],
|
|
}}
|
|
>
|
|
{/* Stats Grid */}
|
|
<PageSection title="Quick Stats">
|
|
<PageGrid cols={4}>
|
|
<PageCard>
|
|
<h3 className="text-sm font-medium text-muted-foreground">
|
|
Total Users
|
|
</h3>
|
|
<p className="text-3xl font-bold mt-2">1,234</p>
|
|
</PageCard>
|
|
<PageCard>
|
|
<h3 className="text-sm font-medium text-muted-foreground">
|
|
Active Sessions
|
|
</h3>
|
|
<p className="text-3xl font-bold mt-2">89</p>
|
|
</PageCard>
|
|
<PageCard>
|
|
<h3 className="text-sm font-medium text-muted-foreground">
|
|
Revenue
|
|
</h3>
|
|
<p className="text-3xl font-bold mt-2">$12,345</p>
|
|
</PageCard>
|
|
<PageCard>
|
|
<h3 className="text-sm font-medium text-muted-foreground">
|
|
Conversion
|
|
</h3>
|
|
<p className="text-3xl font-bold mt-2">3.2%</p>
|
|
</PageCard>
|
|
</PageGrid>
|
|
</PageSection>
|
|
|
|
{/* Recent Activity */}
|
|
<PageSection
|
|
title="Recent Activity"
|
|
description="Latest updates from your team"
|
|
>
|
|
<PageCard>
|
|
<div className="space-y-4">
|
|
<div className="flex items-center gap-3">
|
|
<div className="h-8 w-8 rounded-full bg-primary/10" />
|
|
<div>
|
|
<p className="text-sm font-medium">User signed up</p>
|
|
<p className="text-xs text-muted-foreground">2 minutes ago</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</PageCard>
|
|
</PageSection>
|
|
|
|
{/* Empty State Example */}
|
|
<PageSection title="Messages">
|
|
<PageCard>
|
|
<PageEmptyState
|
|
icon={Mail}
|
|
title="No messages yet"
|
|
description="When you receive messages, they'll appear here"
|
|
action={{
|
|
label: "Send Message",
|
|
onClick: () => console.log("Send"),
|
|
icon: Plus,
|
|
}}
|
|
/>
|
|
</PageCard>
|
|
</PageSection>
|
|
</PageTemplate>
|
|
);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Props Reference
|
|
|
|
### PageTemplate
|
|
|
|
| Prop | Type | Description |
|
|
|------|------|-------------|
|
|
| `children` | `ReactNode` | Main content |
|
|
| `sidebar` | `object` | Optional sidebar configuration |
|
|
| `hero` | `object` | Optional hero section configuration |
|
|
| `containerWidth` | `"default" \| "wide" \| "full"` | Content container width (default: "default") |
|
|
| `className` | `string` | Custom wrapper class |
|
|
| `contentClassName` | `string` | Custom content class |
|
|
|
|
### Sidebar Config
|
|
|
|
| Prop | Type | Description |
|
|
|------|------|-------------|
|
|
| `title` | `string` | Sidebar title |
|
|
| `description` | `string` | Optional subtitle |
|
|
| `items` | `array` | Navigation items |
|
|
| `footer` | `ReactNode` | Optional footer content |
|
|
|
|
### Hero Config
|
|
|
|
| Prop | Type | Description |
|
|
|------|------|-------------|
|
|
| `icon` | `LucideIcon` | Optional icon |
|
|
| `title` | `string` | Page title |
|
|
| `description` | `string` | Optional description |
|
|
| `actions` | `array` | Optional action buttons |
|
|
|
|
---
|
|
|
|
## Tips
|
|
|
|
1. **Consistent Icons**: Always use Lucide icons for consistency
|
|
2. **Active States**: Pass `isActive` to sidebar items to highlight current page
|
|
3. **Responsive**: Grid and card components are responsive by default
|
|
4. **Accessibility**: All components include proper ARIA attributes
|
|
5. **Performance**: Use "use client" only when you need client-side interactivity
|
|
|
|
---
|
|
|
|
## Migration Guide
|
|
|
|
To migrate an existing page:
|
|
|
|
1. Import `PageTemplate` and utility components
|
|
2. Wrap content in `<PageTemplate>`
|
|
3. Move navigation to `sidebar` prop
|
|
4. Move page header to `hero` prop
|
|
5. Replace div sections with `<PageSection>`
|
|
6. Replace card divs with `<PageCard>`
|
|
7. Use `<PageGrid>` for responsive grids
|
|
|
|
Before:
|
|
```tsx
|
|
<div className="flex h-full">
|
|
<div className="w-64 border-r">
|
|
{/* sidebar */}
|
|
</div>
|
|
<div className="flex-1">
|
|
{/* content */}
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
After:
|
|
```tsx
|
|
<PageTemplate sidebar={{...}} hero={{...}}>
|
|
{/* content */}
|
|
</PageTemplate>
|
|
```
|
|
|