Files
vibn-frontend/components/layout/PAGE_TEMPLATE_GUIDE.md

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>
```