mdxui

DocsPage Component

Documentation page layout with sidebar, table of contents, and navigation

DocsPage Component

The <DocsPage> component provides a specialized layout for documentation pages with sidebar navigation, table of contents, breadcrumbs, and edit links.

Interface

import type { DocsPageProps } from 'mdxui'

interface DocsPageProps {
  /** Doc slug or ID */
  slug?: string
  /** Manual override - pass doc directly */
  doc?: any
  /** Show edit link */
  showEdit?: boolean
  /** Show last updated */
  showLastUpdated?: boolean
}

Usage

Basic Example

import { DocsPage } from '@mdxui/beacon'

<DocsPage slug="getting-started">
  <h1>Getting Started</h1>
  <p>Welcome to our documentation...</p>

  <h2>Installation</h2>
  <CodeBlock language="bash">
    npm install @mdxui/beacon
  </CodeBlock>

  <h2>Quick Start</h2>
  <p>Here's how to get started...</p>
</DocsPage>

MDX Usage

Perfect for MDX documentation:

import { DocsPage } from '@mdxui/beacon'

<DocsPage slug="api-reference" showEdit={true}>

# API Reference

Complete reference for all components and utilities.

## Components

### Button

The Button component provides...

</DocsPage>

With Manual Doc Data

Override auto-fetching with manual data:

const docData = {
  title: "Installation Guide",
  description: "How to install and configure",
  slug: "installation",
  content: "...",
  lastUpdated: "2025-01-15",
  author: "Jane Doe"
}

<DocsPage doc={docData} showEdit={true} showLastUpdated={true}>
  {/* Content rendered from doc.content */}
</DocsPage>

Auto-Wire to Payload

The component automatically queries the docs collection:

// Fetches from Payload CMS based on slug
<DocsPage slug="getting-started" />

Props

slug (optional)

Type: string

Document slug for fetching from Payload CMS. If provided, the component will auto-fetch the doc data.

<DocsPage slug="api-reference" />

doc (optional)

Type: any

Manual doc data override. Use this to bypass auto-fetching and provide doc data directly.

<DocsPage doc={{ title: "Guide", content: "..." }} />

showEdit (optional)

Type: boolean (default: true)

Show "Edit this page" link that points to the source file in the repository.

<DocsPage slug="guide" showEdit={true} />

showLastUpdated (optional)

Type: boolean (default: true)

Show last updated date at the bottom of the page.

<DocsPage slug="guide" showLastUpdated={true} />

Implementation Details

The reference implementation from @mdxui/beacon includes:

Features

  • Sidebar Navigation - Collapsible sidebar with doc tree
  • Table of Contents - Auto-generated from h2/h3 headings
  • Breadcrumbs - Navigation breadcrumbs showing current location
  • Prev/Next Links - Navigate between related docs
  • Edit Link - Link to edit source on GitHub
  • Last Updated - Show when doc was last modified
  • Search Integration - Built-in search functionality
  • Mobile Responsive - Sidebar collapses on mobile
  • Syntax Highlighting - Code blocks with syntax highlighting

Structure

<div className="flex min-h-screen">
  {/* Sidebar */}
  <aside className="w-64 border-r">
    <DocsNav tree={docTree} currentSlug={slug} />
  </aside>

  {/* Main Content */}
  <main className="flex-1 max-w-4xl">
    <article className="px-8 py-12">
      {/* Breadcrumbs */}
      <Breadcrumbs path={breadcrumbPath} />

      {/* Content */}
      <div className="prose lg:prose-xl dark:prose-invert">
        {children}
      </div>

      {/* Footer */}
      <footer className="mt-12 pt-8 border-t">
        {showLastUpdated && (
          <p className="text-sm text-muted-foreground">
            Last updated: {doc.lastUpdated}
          </p>
        )}
        {showEdit && (
          <a href={editUrl} className="text-sm">
            Edit this page on GitHub
          </a>
        )}
      </footer>

      {/* Prev/Next Navigation */}
      <PrevNextNav prev={prevDoc} next={nextDoc} />
    </article>
  </main>

  {/* Table of Contents */}
  <aside className="w-64 border-l">
    <TableOfContents headings={tocHeadings} />
  </aside>
</div>

Layout Grid

Three-column layout on desktop:

┌─────────┬────────────────┬──────────┐
│ Sidebar │ Main Content   │   TOC    │
│  (nav)  │   (article)    │ (headings)│
│ 256px   │    flex-1      │  256px   │
└─────────┴────────────────┴──────────┘

Mobile layout (stacked):

┌──────────────┐
│   Sidebar    │ (collapsible menu)
├──────────────┤
│    Content   │
├──────────────┤
│     TOC      │ (bottom or hidden)
└──────────────┘

Auto-Wiring

The DocsPage component can auto-wire to Payload CMS:

How It Works

  1. Component receives slug prop
  2. Queries Payload docs collection for matching document
  3. Renders doc metadata and content
  4. Populates sidebar navigation from doc tree
  5. Generates breadcrumbs from doc hierarchy

Payload Collection Schema

const Docs = {
  slug: 'docs',
  fields: [
    { name: 'title', type: 'text', required: true },
    { name: 'slug', type: 'text', required: true, unique: true },
    { name: 'description', type: 'text' },
    { name: 'content', type: 'richText' },
    { name: 'category', type: 'relationship', relationTo: 'doc-categories' },
    { name: 'order', type: 'number' },
    { name: 'lastUpdated', type: 'date' },
    { name: 'author', type: 'relationship', relationTo: 'users' },
  ]
}

Example Query

const doc = await payload.find({
  collection: 'docs',
  where: {
    slug: { equals: slug }
  }
})

The sidebar shows hierarchical doc structure:

Tree Structure

const docTree = [
  {
    title: "Getting Started",
    items: [
      { title: "Installation", slug: "installation" },
      { title: "Quick Start", slug: "quick-start" },
    ]
  },
  {
    title: "Components",
    items: [
      { title: "Button", slug: "components/button" },
      { title: "Card", slug: "components/card" },
      { title: "Dialog", slug: "components/dialog" },
    ]
  },
  {
    title: "API Reference",
    items: [
      { title: "Configuration", slug: "api/config" },
      { title: "Theming", slug: "api/theming" },
    ]
  }
]

Features

  • Collapsible Sections - Categories can expand/collapse
  • Active State - Current page is highlighted
  • Keyboard Navigation - Arrow keys navigate tree
  • Scroll Sync - Sidebar scrolls to active item

Table of Contents

Auto-generated from page headings:

Generation

const generateTOC = (content: string) => {
  const headings = content.match(/#{2,3} .+/g)
  return headings?.map(h => ({
    level: h.match(/^#+/)[0].length,
    text: h.replace(/^#+\s/, ''),
    id: slugify(h.replace(/^#+\s/, ''))
  }))
}

Features

  • H2/H3 Extraction - Captures level 2 and 3 headings
  • Active Scrollspy - Highlights current section
  • Click to Scroll - Smooth scroll to section
  • Sticky Position - Stays visible while scrolling

Common Use Cases

API Documentation

<DocsPage slug="api/components" showEdit={true}>
  <h1>Component API</h1>

  <h2>Button</h2>
  <h3>Props</h3>
  <PropsTable component="Button" />

  <h3>Examples</h3>
  <CodeBlock language="tsx">
    {`<Button variant="primary">Click me</Button>`}
  </CodeBlock>

  <h2>Input</h2>
  <h3>Props</h3>
  <PropsTable component="Input" />

  <h3>Examples</h3>
  <CodeBlock language="tsx">
    {`<Input label="Email" type="email" />`}
  </CodeBlock>
</DocsPage>

Tutorial Guide

<DocsPage slug="guides/authentication" showLastUpdated={true}>
  <h1>Authentication Guide</h1>
  <p>Learn how to implement authentication in your app.</p>

  <h2>Prerequisites</h2>
  <ul>
    <li>Node.js 18+</li>
    <li>Basic React knowledge</li>
  </ul>

  <h2>Step 1: Install Dependencies</h2>
  <CodeBlock language="bash">
    npm install next-auth
  </CodeBlock>

  <h2>Step 2: Configure Providers</h2>
  <p>Set up your authentication providers...</p>
  <CodeBlock language="typescript">
    {authConfigCode}
  </CodeBlock>

  <h2>Step 3: Protect Routes</h2>
  <p>Add middleware to protect your routes...</p>
</DocsPage>

Migration Guide

<DocsPage slug="migrations/v2" showEdit={true}>
  <h1>Migration Guide: v1 to v2</h1>

  <Callout type="warning">
    This is a major version upgrade. Please read carefully.
  </Callout>

  <h2>Breaking Changes</h2>
  <ul>
    <li>Component API changes</li>
    <li>Theme system updates</li>
    <li>Deprecated features removed</li>
  </ul>

  <h2>Step-by-Step Migration</h2>

  <h3>1. Update Dependencies</h3>
  <CodeBlock language="bash">
    npm install @mdxui/beacon@2.0.0
  </CodeBlock>

  <h3>2. Update Imports</h3>
  <CodeBlock language="diff">
    {`- import { Button } from '@mdxui/beacon/button'
+ import { Button } from '@mdxui/beacon'`}
  </CodeBlock>

  <h3>3. Update Component Props</h3>
  <p>The Button component now uses...</p>
</DocsPage>

Changelog

<DocsPage slug="changelog" showLastUpdated={false}>
  <h1>Changelog</h1>

  <h2>Version 2.0.0 - January 2025</h2>
  <h3>Added</h3>
  <ul>
    <li>New Dashboard component</li>
    <li>Dark mode support</li>
  </ul>

  <h3>Changed</h3>
  <ul>
    <li>Updated theme system</li>
    <li>Improved accessibility</li>
  </ul>

  <h3>Fixed</h3>
  <ul>
    <li>Fixed mobile menu bug</li>
    <li>Fixed TypeScript types</li>
  </ul>

  <h2>Version 1.9.0 - December 2024</h2>
  <h3>Added</h3>
  <ul>
    <li>Export functionality</li>
  </ul>
</DocsPage>

Configure GitHub edit links:

const editUrl = `https://github.com/owner/repo/edit/main/docs/${slug}.mdx`

<a
  href={editUrl}
  target="_blank"
  rel="noopener noreferrer"
  className="inline-flex items-center text-sm"
>
  <Edit className="mr-2 h-4 w-4" />
  Edit this page on GitHub
</a>

Configuration:

  • Repository URL
  • Branch name (main, master, develop)
  • Docs directory path
  • File extension (.md, .mdx)

Search Integration

Built-in search for documentation:

<DocsSearch
  placeholder="Search docs..."
  onSearch={async (query) => {
    const results = await searchDocs(query)
    return results
  }}
/>

Features:

  • Fuzzy search
  • Keyboard shortcuts (⌘K, Ctrl+K)
  • Result highlighting
  • Category filtering

Accessibility

The reference implementation includes:

  • Semantic HTML - Uses <article>, <aside>, <nav>
  • Heading Hierarchy - Proper h1-h6 structure
  • Landmark Regions - ARIA landmarks for navigation
  • Skip Links - Skip to main content
  • Keyboard Navigation - Full keyboard support
  • Focus Management - Focus indicators on all interactive elements
  • Screen Reader Support - ARIA labels and descriptions
<nav aria-label="Documentation navigation">
  <ul role="list">
    {/* Sidebar items */}
  </ul>
</nav>

<main id="main-content" role="main" aria-label="Documentation content">
  <article>
    {/* Doc content */}
  </article>
</main>

<aside aria-label="Table of contents">
  {/* TOC headings */}
</aside>

TypeScript

Full type definitions:

import type { ReactNode } from 'react'
import type { z } from 'zod'
import type { Component } from 'mdxui'

export const DocsPagePropsSchema = z.object({
  slug: z.string().optional(),
  doc: z.any().optional(),
  showEdit: z.boolean().default(true),
  showLastUpdated: z.boolean().default(true),
})

export type DocsPageProps = z.infer<typeof DocsPagePropsSchema>
export type DocsPage = Component<DocsPageProps>

On this page