forked from cardosofelipe/fast-next-template
Introduce DevBreadcrumbs component for navigation and replace headers in /dev pages with breadcrumb navigation. Adjust spacing for consistent layout.
This commit is contained in:
@@ -9,6 +9,7 @@ import { promises as fs } from 'fs';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import matter from 'gray-matter';
|
import matter from 'gray-matter';
|
||||||
import { MarkdownContent } from '@/components/docs/MarkdownContent';
|
import { MarkdownContent } from '@/components/docs/MarkdownContent';
|
||||||
|
import { DevBreadcrumbs } from '@/components/dev/DevBreadcrumbs';
|
||||||
|
|
||||||
interface DocPageProps {
|
interface DocPageProps {
|
||||||
params: Promise<{ slug: string[] }>;
|
params: Promise<{ slug: string[] }>;
|
||||||
@@ -56,11 +57,24 @@ export default async function DocPage({ params }: DocPageProps) {
|
|||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract title from first heading or use filename
|
||||||
|
const title = doc.content.match(/^#\s+(.+)$/m)?.[1] || slug[slug.length - 1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto px-4 py-8">
|
<div className="bg-background">
|
||||||
|
{/* Breadcrumbs */}
|
||||||
|
<DevBreadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: 'Documentation', href: '/dev/docs' },
|
||||||
|
{ label: title }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-12">
|
||||||
<div className="mx-auto max-w-4xl">
|
<div className="mx-auto max-w-4xl">
|
||||||
<MarkdownContent content={doc.content} />
|
<MarkdownContent content={doc.content} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { BookOpen, Sparkles, Layout, Palette, Code2, FileCode, Accessibility, Li
|
|||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import { DevBreadcrumbs } from '@/components/dev/DevBreadcrumbs';
|
||||||
|
|
||||||
interface DocItem {
|
interface DocItem {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -98,8 +99,11 @@ const referencesDocs: DocItem[] = [
|
|||||||
export default function DocsHub() {
|
export default function DocsHub() {
|
||||||
return (
|
return (
|
||||||
<div className="bg-background">
|
<div className="bg-background">
|
||||||
|
{/* Breadcrumbs */}
|
||||||
|
<DevBreadcrumbs items={[{ label: 'Documentation' }]} />
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="border-b bg-gradient-to-b from-background to-muted/20 py-16">
|
<section className="border-b bg-gradient-to-b from-background to-muted/20 py-12">
|
||||||
<div className="container mx-auto px-4">
|
<div className="container mx-auto px-4">
|
||||||
<div className="mx-auto max-w-3xl text-center">
|
<div className="mx-auto max-w-3xl text-center">
|
||||||
<h2 className="text-4xl font-bold tracking-tight mb-4">
|
<h2 className="text-4xl font-bold tracking-tight mb-4">
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ import Link from 'next/link';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { ArrowLeft, CheckCircle2, Loader2 } from 'lucide-react';
|
import { CheckCircle2, Loader2 } from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { DevBreadcrumbs } from '@/components/dev/DevBreadcrumbs';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -94,26 +95,12 @@ export default function FormsPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="bg-background">
|
||||||
{/* Header */}
|
{/* Breadcrumbs */}
|
||||||
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<DevBreadcrumbs items={[{ label: 'Forms' }]} />
|
||||||
<div className="container mx-auto flex h-16 items-center gap-4 px-4">
|
|
||||||
<Link href="/dev">
|
|
||||||
<Button variant="ghost" size="icon" aria-label="Back to hub">
|
|
||||||
<ArrowLeft className="h-5 w-5" />
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<div>
|
|
||||||
<h1 className="text-xl font-bold">Form Patterns</h1>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
react-hook-form + Zod validation examples
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<main className="container mx-auto px-4 py-8">
|
<main className="container mx-auto px-4 py-12">
|
||||||
<div className="space-y-12">
|
<div className="space-y-12">
|
||||||
{/* Introduction */}
|
{/* Introduction */}
|
||||||
<div className="max-w-3xl space-y-4">
|
<div className="max-w-3xl space-y-4">
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { ArrowLeft, Grid3x3 } from 'lucide-react';
|
import { Grid3x3 } from 'lucide-react';
|
||||||
|
import { DevBreadcrumbs } from '@/components/dev/DevBreadcrumbs';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -26,26 +27,12 @@ export const metadata: Metadata = {
|
|||||||
|
|
||||||
export default function LayoutsPage() {
|
export default function LayoutsPage() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="bg-background">
|
||||||
{/* Header */}
|
{/* Breadcrumbs */}
|
||||||
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<DevBreadcrumbs items={[{ label: 'Layouts' }]} />
|
||||||
<div className="container mx-auto flex h-16 items-center gap-4 px-4">
|
|
||||||
<Link href="/dev">
|
|
||||||
<Button variant="ghost" size="icon" aria-label="Back to hub">
|
|
||||||
<ArrowLeft className="h-5 w-5" />
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<div>
|
|
||||||
<h1 className="text-xl font-bold">Layout Patterns</h1>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Essential patterns for pages, dashboards, and forms
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<main className="container mx-auto px-4 py-8">
|
<main className="container mx-auto px-4 py-12">
|
||||||
<div className="space-y-12">
|
<div className="space-y-12">
|
||||||
{/* Introduction */}
|
{/* Introduction */}
|
||||||
<div className="max-w-3xl space-y-4">
|
<div className="max-w-3xl space-y-4">
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { ArrowLeft, Ruler } from 'lucide-react';
|
import { Ruler } from 'lucide-react';
|
||||||
|
import { DevBreadcrumbs } from '@/components/dev/DevBreadcrumbs';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -41,26 +42,12 @@ export const metadata: Metadata = {
|
|||||||
|
|
||||||
export default function SpacingPage() {
|
export default function SpacingPage() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="bg-background">
|
||||||
{/* Header */}
|
{/* Breadcrumbs */}
|
||||||
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<DevBreadcrumbs items={[{ label: 'Spacing' }]} />
|
||||||
<div className="container mx-auto flex h-16 items-center gap-4 px-4">
|
|
||||||
<Link href="/dev">
|
|
||||||
<Button variant="ghost" size="icon" aria-label="Back to hub">
|
|
||||||
<ArrowLeft className="h-5 w-5" />
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<div>
|
|
||||||
<h1 className="text-xl font-bold">Spacing Patterns</h1>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Parent-controlled spacing philosophy
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<main className="container mx-auto px-4 py-8">
|
<main className="container mx-auto px-4 py-12">
|
||||||
<div className="space-y-12">
|
<div className="space-y-12">
|
||||||
{/* Introduction */}
|
{/* Introduction */}
|
||||||
<div className="max-w-3xl space-y-4">
|
<div className="max-w-3xl space-y-4">
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
} from '@/components/ui/table';
|
} from '@/components/ui/table';
|
||||||
import { Example, ExampleGrid, ExampleSection } from './Example';
|
import { Example, ExampleGrid, ExampleSection } from './Example';
|
||||||
|
import { DevBreadcrumbs } from './DevBreadcrumbs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component showcase
|
* Component showcase
|
||||||
@@ -76,8 +77,11 @@ export function ComponentShowcase() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-background">
|
<div className="bg-background">
|
||||||
|
{/* Breadcrumbs */}
|
||||||
|
<DevBreadcrumbs items={[{ label: 'Components' }]} />
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<main className="container mx-auto px-4 py-8">
|
<main className="container mx-auto px-4 py-12">
|
||||||
<div className="space-y-12">
|
<div className="space-y-12">
|
||||||
{/* Colors */}
|
{/* Colors */}
|
||||||
<ExampleSection
|
<ExampleSection
|
||||||
|
|||||||
64
frontend/src/components/dev/DevBreadcrumbs.tsx
Normal file
64
frontend/src/components/dev/DevBreadcrumbs.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DevBreadcrumbs Component
|
||||||
|
* Breadcrumb navigation for dev pages
|
||||||
|
* This file is excluded from coverage as it's a development tool
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { ChevronRight, Home } from 'lucide-react';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
interface Breadcrumb {
|
||||||
|
label: string;
|
||||||
|
href?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DevBreadcrumbsProps {
|
||||||
|
items: Breadcrumb[];
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DevBreadcrumbs({ items, className }: DevBreadcrumbsProps) {
|
||||||
|
return (
|
||||||
|
<nav
|
||||||
|
className={cn('bg-muted/30 border-b', className)}
|
||||||
|
aria-label="Breadcrumb"
|
||||||
|
>
|
||||||
|
<div className="container mx-auto px-4 py-3">
|
||||||
|
<ol className="flex items-center gap-2 text-sm">
|
||||||
|
{/* Home link */}
|
||||||
|
<li>
|
||||||
|
<Link
|
||||||
|
href="/dev"
|
||||||
|
className="inline-flex items-center gap-1.5 text-muted-foreground hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
<Home className="h-4 w-4" />
|
||||||
|
<span>Hub</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{/* Breadcrumb items */}
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<li key={index} className="flex items-center gap-2">
|
||||||
|
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
||||||
|
{item.href ? (
|
||||||
|
<Link
|
||||||
|
href={item.href}
|
||||||
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span className="text-foreground font-medium">{item.label}</span>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user