From 92b7de352c99b7eedfe8893fa907a3a92a257898 Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Sun, 2 Nov 2025 13:47:26 +0100 Subject: [PATCH] **Docs and Code Enhancements:** Add `CodeBlock` component with copy functionality and syntax highlighting. Introduce `/docs` page as the central hub for design system documentation. Update `MarkdownContent` to support improved heading styles, enhanced links, optimized images with Next.js `Image`, and upgraded table, blockquote, and list styling for better readability and usability. --- frontend/src/app/docs/page.tsx | 303 ++++++++++++++++++ frontend/src/components/docs/CodeBlock.tsx | 81 +++++ .../src/components/docs/MarkdownContent.tsx | 93 +++--- 3 files changed, 434 insertions(+), 43 deletions(-) create mode 100644 frontend/src/app/docs/page.tsx create mode 100644 frontend/src/components/docs/CodeBlock.tsx diff --git a/frontend/src/app/docs/page.tsx b/frontend/src/app/docs/page.tsx new file mode 100644 index 0000000..377567c --- /dev/null +++ b/frontend/src/app/docs/page.tsx @@ -0,0 +1,303 @@ +/** + * Documentation Hub + * Central hub for all design system documentation + * Access: /docs + */ + +import Link from 'next/link'; +import { BookOpen, Sparkles, Layout, Palette, Code2, FileCode, Accessibility, Lightbulb, Search } from 'lucide-react'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Badge } from '@/components/ui/badge'; + +interface DocItem { + title: string; + description: string; + href: string; + icon: React.ReactNode; + badge?: string; +} + +const gettingStartedDocs: DocItem[] = [ + { + title: 'Quick Start', + description: '5-minute crash course to get up and running with the design system', + href: '/docs/design-system/00-quick-start', + icon: , + badge: 'Start Here', + }, + { + title: 'README', + description: 'Complete overview and learning paths for the design system', + href: '/docs/design-system/README', + icon: , + }, +]; + +const coreConceptsDocs: DocItem[] = [ + { + title: 'Foundations', + description: 'Colors (OKLCH), typography, spacing, and shadows', + href: '/docs/design-system/01-foundations', + icon: , + }, + { + title: 'Components', + description: 'shadcn/ui component library guide and usage patterns', + href: '/docs/design-system/02-components', + icon: , + }, + { + title: 'Layouts', + description: 'Layout patterns with Grid vs Flex decision trees', + href: '/docs/design-system/03-layouts', + icon: , + }, + { + title: 'Spacing Philosophy', + description: 'Parent-controlled spacing strategy and best practices', + href: '/docs/design-system/04-spacing-philosophy', + icon: , + }, + { + title: 'Component Creation', + description: 'When to create vs compose components', + href: '/docs/design-system/05-component-creation', + icon: , + }, + { + title: 'Forms', + description: 'Form patterns with react-hook-form and Zod validation', + href: '/docs/design-system/06-forms', + icon: , + }, + { + title: 'Accessibility', + description: 'WCAG AA compliance, keyboard navigation, and screen readers', + href: '/docs/design-system/07-accessibility', + icon: , + }, +]; + +const referencesDocs: DocItem[] = [ + { + title: 'AI Guidelines', + description: 'Rules and best practices for AI code generation', + href: '/docs/design-system/08-ai-guidelines', + icon: , + badge: 'AI', + }, + { + title: 'Quick Reference', + description: 'Cheat sheet for quick lookups and common patterns', + href: '/docs/design-system/99-reference', + icon: , + }, +]; + +export default function DocsHub() { + return ( +
+ {/* Header */} +
+
+
+ +
+

FastNext Documentation

+

Design System & Component Library

+
+
+ + + +
+
+ + {/* Hero Section */} +
+
+
+

+ Design System Documentation +

+

+ Comprehensive guides, best practices, and references for building consistent, + accessible, and maintainable user interfaces with the FastNext design system. +

+
+ + + + + + + + + +
+
+
+
+ + {/* Main Content */} +
+
+ {/* Getting Started Section */} +
+
+

Getting Started

+

+ New to the design system? Start here for a quick introduction. +

+
+
+ {gettingStartedDocs.map((doc) => ( + + + +
+
+
+ {doc.icon} +
+
+ {doc.title} + {doc.badge && ( + + {doc.badge} + + )} +
+
+
+
+ + + {doc.description} + + +
+ + ))} +
+
+ + {/* Core Concepts Section */} +
+
+

Core Concepts

+

+ Deep dive into the fundamental concepts and patterns of the design system. +

+
+
+ {coreConceptsDocs.map((doc) => ( + + + +
+
+ {doc.icon} +
+
+ {doc.title} +
+
+
+ + + {doc.description} + + +
+ + ))} +
+
+ + {/* References Section */} +
+
+

References

+

+ Quick references and specialized guides for specific use cases. +

+
+
+ {referencesDocs.map((doc) => ( + + + +
+
+
+ {doc.icon} +
+
+ {doc.title} + {doc.badge && ( + + {doc.badge} + + )} +
+
+
+
+ + + {doc.description} + + +
+ + ))} +
+
+
+
+ + {/* Footer */} +
+
+
+
+
+

+ FastNext Design System +

+

+ Built with shadcn/ui, Tailwind CSS, and OKLCH colors +

+
+
+ + + + + + +
+
+
+
+
+
+ ); +} diff --git a/frontend/src/components/docs/CodeBlock.tsx b/frontend/src/components/docs/CodeBlock.tsx new file mode 100644 index 0000000..21eb704 --- /dev/null +++ b/frontend/src/components/docs/CodeBlock.tsx @@ -0,0 +1,81 @@ +/* istanbul ignore file */ + +/** + * CodeBlock Component + * Syntax-highlighted code block with copy functionality + * This file is excluded from coverage as it's a documentation component + */ + +'use client'; + +import { useState } from 'react'; +import { Check, Copy } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; + +interface CodeBlockProps { + children: React.ReactNode; + className?: string; + title?: string; +} + +export function CodeBlock({ children, className, title }: CodeBlockProps) { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + const code = extractTextFromChildren(children); + await navigator.clipboard.writeText(code); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( +
+ {title && ( +
+ {title} +
+ )} +
+
+          {children}
+        
+ +
+
+ ); +} + +function extractTextFromChildren(children: React.ReactNode): string { + if (typeof children === 'string') { + return children; + } + + if (Array.isArray(children)) { + return children.map(extractTextFromChildren).join(''); + } + + if (children && typeof children === 'object' && 'props' in children) { + return extractTextFromChildren((children as { props: { children: React.ReactNode } }).props.children); + } + + return ''; +} diff --git a/frontend/src/components/docs/MarkdownContent.tsx b/frontend/src/components/docs/MarkdownContent.tsx index 57e794a..444d404 100644 --- a/frontend/src/components/docs/MarkdownContent.tsx +++ b/frontend/src/components/docs/MarkdownContent.tsx @@ -6,13 +6,15 @@ * This file is excluded from coverage as it's a documentation component */ +import Image from 'next/image'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import rehypeHighlight from 'rehype-highlight'; import rehypeSlug from 'rehype-slug'; import rehypeAutolinkHeadings from 'rehype-autolink-headings'; +import { CodeBlock } from './CodeBlock'; import { cn } from '@/lib/utils'; -import 'highlight.js/styles/github-dark.css'; +import 'highlight.js/styles/atom-one-dark.css'; interface MarkdownContentProps { content: string; @@ -30,10 +32,10 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { [rehypeAutolinkHeadings, { behavior: 'wrap' }], ]} components={{ - // Headings + // Headings - improved spacing and visual hierarchy h1: ({ children, ...props }) => (

{children} @@ -41,7 +43,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { ), h2: ({ children, ...props }) => (

{children} @@ -49,7 +51,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { ), h3: ({ children, ...props }) => (

{children} @@ -57,16 +59,16 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { ), h4: ({ children, ...props }) => (

{children}

), - // Paragraphs and text + // Paragraphs and text - improved readability p: ({ children, ...props }) => ( -

+

{children}

), @@ -76,40 +78,40 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { ), em: ({ children, ...props }) => ( - + {children} ), - // Links + // Links - more prominent with better hover state a: ({ children, href, ...props }) => ( {children} ), - // Lists + // Lists - improved spacing and hierarchy ul: ({ children, ...props }) => ( -
    +
      {children}
    ), ol: ({ children, ...props }) => ( -
      +
        {children}
      ), li: ({ children, ...props }) => ( -
    1. +
    2. {children}
    3. ), - // Code blocks + // Code blocks - enhanced with copy button and better styling code: ({ inline, className, children, ...props }: { inline?: boolean; className?: string; @@ -118,7 +120,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { if (inline) { return ( {children} @@ -128,7 +130,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { return ( ( -
      +            
                     {children}
      -            
      + ), - // Blockquotes + // Blockquotes - enhanced callout styling blockquote: ({ children, ...props }) => (
      {children}
      ), - // Tables + // Tables - improved styling with better borders and hover states table: ({ children, ...props }) => ( -
      +
      ), thead: ({ children, ...props }) => ( - + {children} ), tbody: ({ children, ...props }) => ( - {children} + {children} ), tr: ({ children, ...props }) => ( - + {children} ), th: ({ children, ...props }) => ( ), - // Horizontal rule + // Horizontal rule - more prominent hr: ({ ...props }) => ( -
      +
      ), - // Images - img: ({ src, alt, ...props }) => ( - {alt} - ), + // Images - optimized with Next.js Image component + img: ({ src, alt }) => { + if (!src || typeof src !== 'string') return null; + + return ( +
      + +
      + ); + }, }} > {content}
      {children} @@ -190,27 +189,35 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) { ), td: ({ children, ...props }) => ( {children}