VIBN Frontend for Coolify deployment
This commit is contained in:
355
components/layout/PAGE_TEMPLATE_GUIDE.md
Normal file
355
components/layout/PAGE_TEMPLATE_GUIDE.md
Normal file
@@ -0,0 +1,355 @@
|
||||
# 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>
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user