Documentation Website Layout
A three-column documentation reading layout with hierarchical sidebar navigation, a focused prose content area, and a scroll-spy table of contents. Designed for developer documentation sites, knowledge bases, and technical reference pages. Inspired by Next.js docs, Nextra, Docusaurus, and Mintlify.
Structure Specification
Layout Hierarchy
The layout consists of a DocsContainer that holds five regions. A sticky Header spans the full viewport width and contains a Logo, primary Navigation Links (Docs, Blog, API), a Search Trigger (Cmd+K), a Theme Toggle, and an external GitHub Link. Below the header, a three-column body contains a Left Sidebar for hierarchical page navigation, a Main Content Area for prose documentation, and a Right Sidebar (Table of Contents) for on-page anchor navigation. A Footer sits below the content area.
On mobile the sidebar becomes an off-canvas drawer, the TOC collapses into an inline "On this page" disclosure above the content, and the header shows a hamburger menu toggle.
Detailed Component Specifications
1. Header
Dimensions:
- Height: 60px
- Width: 100% viewport
- Position: Sticky at top (z-index above sidebar)
Elements:
Logo
- Height: 24-32px
- Position: Left-most
- Behavior: Links to homepage
Navigation Links
- Font size: 14-16px, medium weight (500)
- Gap: 24-32px between links
- Typical links: Docs, Blog, API Reference
- Active link: Highlighted with underline or color change
- Visibility: Hidden on mobile, moved into hamburger menu
Search Trigger
- Appearance: Pill-shaped button or input placeholder showing "Search docs..." with Cmd+K / Ctrl+K badge
- Min width: 200px on desktop, icon-only on mobile
- Behavior: Opens Command Palette overlay on click or Cmd+K / Ctrl+K keyboard shortcut
- IMPORTANT: The search overlay MUST be implemented as a full Command Palette following the Command Palette component potion. Read and follow that potion's complete specification — do not implement a simple filter input. The palette must include fuzzy matching, grouped results, keyboard navigation, active row tracking, and all accessibility features defined in the Command Palette potion.
Theme Toggle
- Size: 36-40px button
- Icons: Sun/Moon or system icons
- Behavior: Toggles between light, dark, and system theme (see Dark/Light Mode pattern potion)
GitHub Link
- Size: 36-40px icon button
- Icon: GitHub logo
- Behavior: Opens project repository in new tab
Mobile Menu Toggle
- Size: 40px x 40px
- Icon: Hamburger / close
- Visibility: Hidden on desktop (>=1280px), visible below
- Behavior: Opens left sidebar as off-canvas drawer
Behavior:
- Sticky positioning, remains visible on scroll
- Subtle bottom border or shadow for separation
- On mobile: collapses nav links into hamburger menu, search becomes icon-only
2. Left Sidebar (Navigation)
Dimensions:
- Width: 260px
- Height: Full viewport minus header height
- Position: Fixed (desktop), off-canvas drawer (mobile)
- Top offset: Header height (60px)
Elements:
Navigation Tree
- Hierarchical structure with collapsible sections
- Section headers: 12-13px uppercase, medium weight (500-600), muted color
- Page links: 14px, regular weight (400)
- Nested depth indicator: 12-16px left padding per level, max 3 levels recommended
- Vertical gap: 2-4px between items, 16-24px between sections
Active Page Indicator
- Visual treatment: Background highlight (primary color at 8-12% opacity) plus left border (2-3px, primary color) or text color change to primary
- Must be clearly distinguishable from hover state
Section Expand/Collapse
- Chevron icon (12-16px) rotates on toggle
- Animation: 180ms rotation
- Expanded state persisted per session (sessionStorage or component state)
Scroll Behavior
- Independent scroll within sidebar (overflow-y: auto)
- Custom thin scrollbar (6px width, subtle color)
- Active page should be scrolled into view on initial load
Behavior:
- Desktop: Always visible, fixed position alongside content
- Mobile: Off-canvas drawer sliding in from left with backdrop
- Backdrop: Semi-transparent overlay, click dismisses sidebar
- Focus trap when drawer is open on mobile
- Body scroll lock when drawer is open on mobile
- Close on navigation (when user clicks a page link on mobile)
- Close on Escape key
3. Main Content Area
Dimensions:
- Max width: 768px for prose content
- Padding: 32-48px horizontal, 32px vertical
- Position: Centered between sidebar and TOC
- Min height: Fill available viewport
Elements:
Breadcrumbs
- Font size: 13-14px
- Color: Muted text
- Separator: Chevron or slash
- Pattern: Section > Subsection > Current Page
- Last item (current page): Not a link, slightly bolder or different color
- Position: Above page title
Page Title (H1)
- Font size: 30-36px, bold (700)
- Margin bottom: 16-24px
- Only one H1 per page
Prose Content
- Font size: 16px, regular weight (400)
- Line height: 1.7-1.8 for readability
- Paragraph spacing: 16-24px
- Max width constrains text for comfortable reading (65-75 characters per line)
Headings (H2, H3)
- H2: 22-26px, semibold (600), margin-top 32-48px, margin-bottom 16px
- H3: 18-20px, semibold (600), margin-top 24-32px, margin-bottom 12px
- Each heading should have an anchor link (hover-revealed # icon or click-to-copy link)
- Anchor IDs auto-generated from heading text (kebab-case)
Code Blocks
- Background: Slightly different from page background (darker in light mode, lighter in dark mode)
- Border radius: 8px
- Padding: 16px
- Font: Monospace, 13-14px
- Syntax highlighting (build-time via Shiki or similar)
- Copy button: Top-right corner, icon-only (clipboard icon), appears on hover or always visible
- File name label: Optional top bar showing file path (e.g., "app/layout.tsx"), 12-13px, muted background
- Horizontal scroll for long lines (no wrapping)
- Line numbers: Optional, muted color
Callout/Admonition Blocks
- Types: info (blue), warning (amber/yellow), tip (green), danger (red)
- Structure: Left border (3-4px, type color) + light tinted background + icon + title (optional) + content
- Border radius: 6-8px
- Padding: 12-16px
- Icon: 20px, type-specific (info circle, warning triangle, lightbulb, exclamation)
- Font size: 14-15px
Previous/Next Navigation
- Position: Bottom of content, full width
- Layout: Two-column (Previous on left, Next on right)
- Each shows: Direction label ("Previous" / "Next") + Page title
- Padding: 16px
- Border: 1px border, hover highlight
- Border radius: 8px
Page Meta
- "Last updated: [date]" text, 13px, muted
- "Edit this page on GitHub" link, 13px
- Optional "Was this helpful?" feedback widget (thumbs up/down)
- Position: Below content, above prev/next navigation
Behavior:
- Content scrolls naturally (page-level scroll, not container scroll)
- Smooth scroll to anchor when clicking TOC links
- Heading anchor links update URL hash without full page reload
4. Right Sidebar (Table of Contents)
Dimensions:
- Width: 220px
- Position: Sticky (top offset: header height + 16-24px padding)
- Max height: Viewport minus header and padding
Elements:
TOC Header
- Text: "On this page"
- Font size: 12-13px uppercase, medium weight (500-600), muted color
TOC Links
- List of H2 and H3 headings from current page
- H2 links: 13-14px, regular weight
- H3 links: 13-14px, regular weight, indented 12-16px
- Active state: Primary color text or left border indicator
- Hover: Subtle color change
- Vertical gap: 6-8px between items
Scroll Spy
- Implementation: Intersection Observer API watching all H2/H3 elements
- Active heading: The heading currently in or nearest to the top of the viewport
- Threshold: Heading is "active" when it crosses into the top ~20-30% of the viewport
- Transition: Smooth color change (150ms) when active heading changes
- Only one heading is active at a time
Behavior:
- Desktop (>=1280px): Visible, sticky alongside content
- Tablet (768-1279px): Hidden (insufficient space for three columns)
- Mobile (<768px): Rendered as collapsible "On this page" disclosure widget above the content area
- Hidden entirely when page has fewer than 2 headings
- Independent scroll if TOC is longer than viewport (overflow-y: auto)
5. Footer
Dimensions:
- Width: 100% viewport
- Padding: 32-48px vertical, 24-32px horizontal
Layout:
- Multi-column link grid: 3-4 columns (Resources, Community, Legal, Product)
- Column header: 13-14px, semibold (600), uppercase or normal case
- Column links: 14px, regular weight, muted color, hover reveals primary color
Elements:
- Link columns with category headers
- Social media icons row (GitHub, X/Twitter, Discord, etc.)
- Copyright notice: 13px, muted
Behavior:
- Appears after content (not fixed)
- Responsive: Columns stack on mobile (2 columns on tablet, single column on smallest screens)
Responsive Breakpoints
Desktop (>=1280px)
- Three columns visible: Sidebar (260px) + Content (flexible, max 768px) + TOC (220px)
- Header: Full navigation visible
- Sidebar: Fixed position, always visible
- TOC: Sticky, visible
- Search trigger: Full pill-shaped button with text
Tablet (768px-1279px)
- Two columns: Sidebar (260px) + Content (fills remaining)
- TOC: Hidden (or collapsed inline above content)
- Header: May collapse some nav links
- Sidebar: Visible on larger tablets, off-canvas on smaller
- Search trigger: May shrink to icon + shorter text
Mobile (<768px)
- Single column: Content only
- Sidebar: Off-canvas drawer (slide from left)
- TOC: Collapsible "On this page" disclosure above content
- Header: Hamburger menu, icon-only search
- Footer: Stacked columns
- Content padding: Reduced to 16-20px
Window Resize Handling
- Debounce: 200ms
- Close mobile sidebar drawer when resizing to desktop
- TOC visibility toggles based on breakpoint
Interaction Patterns
Sidebar Tree Navigation
- User clicks section header to expand/collapse
- Chevron rotates to indicate state
- Child items reveal/hide with smooth height transition (150-200ms)
- Clicking a page link navigates to that page
- Active page is highlighted
- On mobile: sidebar closes after navigation
Scroll Spy (TOC)
- As user scrolls, Intersection Observer tracks heading visibility
- The heading nearest the top of the viewport becomes "active"
- Corresponding TOC link highlights with primary color
- Clicking a TOC link smooth-scrolls to that heading
- URL hash updates to reflect current heading
Command Palette Search (Cmd+K)
IMPORTANT: Implement the search overlay by reading and following the full Command Palette component potion. The palette should be populated with a command registry built from the sidebar navigation tree (each page becomes a searchable command). The implementation below summarizes the key interaction flow — see the Command Palette potion for complete details on fuzzy matching, scoring, grouping, keyboard navigation order, pointer-moved flag, ARIA, and mobile behavior.
- User presses Cmd+K / Ctrl+K or clicks search trigger
- Command Palette overlay opens with focus on search input
- When query is empty, all commands are shown grouped by section (matching sidebar sections)
- User types search query, results are fuzzy-matched and re-ranked instantly
- ArrowUp/Down navigates results in visual grouped order, Enter executes
- Escape clears query first, then closes on second press
- User selects result, navigates to that page, palette closes
- Recently executed commands are persisted in localStorage
Mobile Sidebar Drawer
- User taps hamburger icon in header
- Sidebar slides in from left (300ms)
- Backdrop fades in (200ms)
- Focus moves to first focusable element in sidebar
- Focus is trapped within sidebar
- Body scroll is locked
- User navigates or taps backdrop or presses Escape
- Sidebar slides out, focus returns to hamburger button
Accessibility Requirements
WCAG 2.1 Compliance (Level AA Target)
- 1.3.1 Info and Relationships: Semantic HTML structure with proper landmark roles (nav, main, aside, header, footer)
- 1.4.3 Contrast Minimum: 4.5:1 for body text, 3:1 for large text
- 2.1.1 Keyboard: All interactive elements keyboard accessible
- 2.1.2 No Keyboard Trap: Focus trapping only in mobile sidebar overlay
- 2.4.2 Page Titled: Descriptive page title reflecting current docs page
- 2.4.3 Focus Order: Logical tab order (Header > Sidebar > Content > TOC > Footer)
- 2.4.4 Link Purpose: All links have descriptive text
- 2.4.5 Multiple Ways: Both sidebar navigation and search provide multiple ways to reach content
- 2.4.7 Focus Visible: Clear focus indicators on all interactive elements
- 3.2.1 On Focus: No context changes on focus
- 4.1.2 Name, Role, Value: All elements have accessible names and roles
Keyboard Navigation
Tab Order:
- Header (logo, nav, search, theme, github) > Sidebar navigation > Main content links > TOC links > Footer links
Sidebar Navigation:
- Arrow Up/Down: Move between items within current section
- Enter/Space: Navigate to page or expand/collapse section
- Escape: Close mobile drawer
TOC:
- Tab through TOC links
- Enter: Scroll to heading
ARIA Attributes
Required:
Sidebar (desktop):
- nav element with aria-label="Documentation navigation"
Sidebar (mobile drawer):
- role="dialog", aria-modal="true", aria-label="Documentation navigation"
Mobile Menu Toggle:
- aria-label="Toggle navigation menu", aria-expanded="true/false", aria-controls="docs-sidebar"
Active Page Link:
- aria-current="page"
TOC:
- nav element with aria-label="On this page"
Search Trigger:
- aria-label="Search documentation", aria-keyshortcuts="Meta+K" (or "Control+K")
Section Expand/Collapse:
- button with aria-expanded="true/false", aria-controls="section-id"
Theme Toggle:
- aria-label="Switch to dark/light theme" (update dynamically)
Main Content:
- main element with id="main-content"
Breadcrumbs:
- nav with aria-label="Breadcrumb", ol with list items, current page marked with aria-current="page"
Screen Reader Support
Announcements:
- Sidebar state changes announced via aria-live region
- Page navigation announced via document title update
Landmarks:
- header: Site header
- nav (sidebar): Documentation navigation
- main: Page content
- nav (TOC): On this page
- footer: Site footer
Hidden Text:
- Icon-only buttons (theme toggle, github, copy, hamburger) must have aria-label
- Decorative icons use aria-hidden="true"
Color Contrast
- Body text: 4.5:1 minimum
- Heading text: 4.5:1 minimum
- Muted text (breadcrumbs, meta): 4.5:1 minimum
- TOC links: 4.5:1 minimum
- Active indicators: 3:1 minimum against adjacent colors
- Focus outlines: 3:1 minimum
Design System Specifications
Important: These design specifications are tool-agnostic. Implement using the project's chosen styling approach.
Color Guidelines
Dark mode uses a modern 2026 aesthetic with near-black backgrounds (#0a0a0a), zinc grays for text (#a1a1aa, #71717a), and refined borders (rgba 0.06).
Header
- Background (Light): White (#ffffff) or very light gray (#f9fafb)
- Background (Dark): #0a0a0a
- Border: 1px solid bottom border, light: rgba(0,0,0,0.08), dark: rgba(255,255,255,0.06)
- Text (Light): #1f2937
- Text (Dark): #fafafa
- Icons: Default #6b7280 (light) / #71717a (dark), hover #374151 (light) / #fafafa (dark)
Left Sidebar
- Background (Light): White (#ffffff) or very light gray (#fafafa)
- Background (Dark): #0f0f0f
- Border: 1px solid end border, light: rgba(0,0,0,0.08), dark: rgba(255,255,255,0.06)
- Section headers: #6b7280 (light), #71717a (dark)
- Page links (Light): #374151 default, #111827 hover
- Page links (Dark): #a1a1aa default, #fafafa hover
- Active item: Primary color text + primary background (8-12% opacity) + start border (2-3px)
- Hover: Neutral at 5-8% opacity, 150ms transition
Main Content
- Background (Light): White (#ffffff)
- Background (Dark): #0a0a0a
- Body text (Light): #1f2937 or #374151
- Body text (Dark): #a1a1aa
- Heading text (Light): #111827, (Dark): #fafafa
- Link color: Primary color with underline on hover
- Muted text: #6b7280 (light), #71717a (dark)
- Code block background (Light): #f8fafc or #f5f5f5
- Code block background (Dark): #171717
Right Sidebar (TOC)
- Background: Transparent (same as content area)
- TOC header: #6b7280 (light), #71717a (dark)
- TOC links default: #6b7280 (light), #71717a (dark)
- TOC links hover: #374151 (light), #a1a1aa (dark)
- TOC active link: Primary color (#6366f1)
Footer
- Background (Light): #f9fafb or white
- Background (Dark): #0a0a0a
- Border: 1px solid top border, light: rgba(0,0,0,0.08), dark: rgba(255,255,255,0.06)
- Text: #6b7280 (light), #71717a (dark)
- Links: Muted default, primary or lighter on hover
Code Blocks
- Background (Light): #f8fafc, #f5f5f5, or #fafafa
- Background (Dark): #171717
- Border: light rgba(0,0,0,0.08), dark rgba(255,255,255,0.06)
- File label bar: Slightly different shade from code background
- Copy button: Muted icon, hover reveals full opacity
Callouts
- Info: Blue (bg: #eff6ff light, rgba(59,130,246,0.08) dark, border: #3b82f6)
- Warning: Amber (bg: #fffbeb light, rgba(245,158,11,0.08) dark, border: #f59e0b)
- Tip: Green (bg: #f0fdf4 light, rgba(34,197,94,0.08) dark, border: #22c55e)
- Danger: Red (bg: #fef2f2 light, rgba(239,68,68,0.08) dark, border: #ef4444)
Backdrop (Mobile Drawer)
- Light: rgba(0,0,0,0.5), optional blur
- Dark: rgba(0,0,0,0.7), optional backdrop-filter: blur(8px)
Typography
- Font family: Use project font stack (system-ui, -apple-system, sans-serif or custom)
- Code font: Monospace (JetBrains Mono, Fira Code, Menlo, or system monospace)
- Body: 16px, regular (400), line-height 1.7-1.8
- H1 (page title): 30-36px, bold (700), line-height 1.2
- H2: 22-26px, semibold (600), line-height 1.3
- H3: 18-20px, semibold (600), line-height 1.4
- Sidebar nav items: 14px, regular (400)
- Sidebar section headers: 12-13px, medium (500), uppercase
- TOC links: 13-14px, regular (400)
- Breadcrumbs: 13-14px, regular (400)
- Code: 13-14px, monospace
- Footer: 13-14px, regular (400)
Spacing System
Use consistent spacing scale (4, 8, 12, 16, 20, 24, 32, 48, 64px):
- Header: 16-24px horizontal padding, 16px vertical
- Sidebar: 16-20px horizontal padding, 8-12px vertical per item
- Content: 32-48px horizontal padding, 32px vertical (16-20px on mobile)
- TOC: 16px start padding
- Footer: 32-48px vertical padding, 24-32px horizontal
- Between sections: 24-32px
- Between paragraphs: 16-24px
Shadows and Borders
- Header: Bottom border preferred over shadow for clean documentation aesthetic
- Sidebar: End border (1px solid) on desktop, shadow on mobile drawer
- Mobile drawer shadow: 4px 0 16px rgba(0,0,0,0.1) (light), 4px 0 16px rgba(0,0,0,0.3) (dark)
- Code blocks: Subtle border, no shadow
- Callouts: No shadow, rely on border and background tint
- Prev/Next cards: 1px border, shadow on hover (light: 0 2px 8px rgba(0,0,0,0.08), dark: 0 2px 8px rgba(0,0,0,0.2))
Border Radius
- Code blocks: 8px
- Callouts: 6-8px
- Search trigger: 8px or pill (9999px)
- Prev/Next cards: 8px
- Buttons (header): 6-8px
- Mobile sidebar: 0 (full edge)
Mobile Safe Area
- On devices with notches, add safe-area padding to the sticky header: env(safe-area-inset-top)
RTL Support
- Use logical CSS properties (inset-inline-start/end, margin-inline-start/end, padding-inline-start/end) so sidebar and TOC swap sides in RTL layouts
- Sidebar on start (left in LTR, right in RTL), TOC on end
Reduced Motion Preferences
When prefers-reduced-motion: reduce:
- Disable sidebar drawer slide animation (use instant show/hide)
- Disable section expand/collapse animation
- Disable smooth scroll (use instant jump)
- Keep TOC active state color change (subtle, non-motion)
- Keep backdrop opacity change but reduce to 100ms
State Management Considerations
States to Track
- sidebarOpen: boolean - Mobile drawer visibility (default: false, component state only)
- activePage: string - Current page identifier (synced with router/URL)
- expandedSections: string[] - Which sidebar sections are expanded (sessionStorage or component state, auto-expand section containing active page)
- activeHeading: string - Currently visible heading for scroll spy (component state, derived from Intersection Observer)
- searchOpen: boolean - Whether Cmd+K search overlay is open (component state only)
Theme is handled by the Dark/Light Mode pattern potion (separate).
State Persistence
- sidebarOpen: Component state only (resets on navigation)
- activePage: Sync with router/URL
- expandedSections: sessionStorage recommended (expand parent of active page on load)
- activeHeading: Component state only (derived from scroll position)
- searchOpen: Component state only
SSR/Hydration Considerations
- sessionStorage access: Only in onMounted/useEffect
- Default expanded sections: Derive from active page URL on server, expand on client
- Scroll spy: Initialize Intersection Observer only on client
- Theme: Prevent flash of wrong theme (inject script in head to set data-theme attribute before render)
Critical Implementation Guidelines
Scroll Spy Implementation
Use Intersection Observer API to track heading visibility:
- Observe all H2 and H3 elements in the content area
- Use rootMargin to offset for the sticky header (e.g., rootMargin: "-60px 0px -70% 0px")
- When multiple headings are intersecting, use the one closest to the top
- Debounce is not needed (Intersection Observer is already efficient)
- Clean up observer on unmount/page change
Vanilla CSS Detection
CRITICAL: When detecting vanilla CSS, ALWAYS create CSS classes in a stylesheet. NEVER use inline style attributes.
- Define classes like .docs-sidebar, .docs-content, .docs-toc, .toc-link--active
- Apply via className/class attributes
- Do NOT use: style="width: 240px"
React Hook Patterns
CRITICAL: When detecting React, extract logic into separate custom hooks:
- useScrollSpy(headingSelector) - Handles Intersection Observer for TOC
- useSidebarNavigation(activePage) - Manages sidebar expansion state
- useBodyScrollLock(isLocked) - Handles mobile drawer scroll lock
- useFocusTrap(containerRef, isActive) - Handles mobile drawer focus trap
- useMediaQuery(query) - Responsive breakpoint detection
Code Implementation Patterns
React Example Pattern
<DocsLayout>
<DocsHeader
onMenuToggle={toggleSidebar}
onSearchOpen={openSearch}
/>
<DocsSidebar
navigation={sidebarTree}
activePage={currentPage}
open={sidebarOpen}
onClose={closeSidebar}
/>
<DocsContent>
<Breadcrumbs items={breadcrumbPath} />
<article>{children}</article>
<PageMeta lastUpdated={meta.updated} editUrl={meta.editUrl} />
<PrevNextNav previous={prevPage} next={nextPage} />
</DocsContent>
<DocsTOC headings={pageHeadings} activeId={activeHeading} />
<DocsFooter />
</DocsLayout>
Vue Example Pattern
<template>
<DocsLayout>
<DocsHeader @menu-toggle="toggleSidebar" @search-open="openSearch" />
<DocsSidebar
:navigation="sidebarTree"
:active-page="currentPage"
:open="sidebarOpen"
@close="closeSidebar"
/>
<DocsContent>
<Breadcrumbs :items="breadcrumbPath" />
<article><slot /></article>
<PageMeta :last-updated="meta.updated" :edit-url="meta.editUrl" />
<PrevNextNav :previous="prevPage" :next="nextPage" />
</DocsContent>
<DocsTOC :headings="pageHeadings" :active-id="activeHeading" />
<DocsFooter />
</DocsLayout>
</template>
Angular Example Pattern
<app-docs-layout>
<app-docs-header
(menuToggle)="toggleSidebar()"
(searchOpen)="openSearch()"
/>
<app-docs-sidebar
[navigation]="sidebarTree"
[activePage]="currentPage"
[open]="sidebarOpen"
(close)="closeSidebar()"
/>
<main class="docs-content">
<app-breadcrumbs [items]="breadcrumbPath" />
<article><router-outlet></router-outlet></article>
<app-page-meta [lastUpdated]="meta.updated" [editUrl]="meta.editUrl" />
<app-prev-next-nav [previous]="prevPage" [next]="nextPage" />
</main>
<app-docs-toc [headings]="pageHeadings" [activeId]="activeHeading" />
<app-docs-footer />
</app-docs-layout>
Svelte Example Pattern
<DocsLayout>
<DocsHeader on:menutoggle={toggleSidebar} on:searchopen={openSearch} />
<DocsSidebar
{navigation}
{activePage}
{sidebarOpen}
on:close={closeSidebar}
/>
<DocsContent>
<Breadcrumbs {items} />
<article><slot /></article>
<PageMeta {lastUpdated} {editUrl} />
<PrevNextNav {previous} {next} />
</DocsContent>
<DocsTOC {headings} {activeHeading} />
<DocsFooter />
</DocsLayout>
CSS Layout Approach
The three-column layout is best achieved with CSS Grid:
.docs-layout {
display: grid;
grid-template-columns: 260px minmax(0, 1fr) 220px;
grid-template-rows: auto 1fr auto;
}
On tablet, drop the TOC column. On mobile, single column with sidebar as overlay.
Animation Specifications
Sidebar Drawer (Mobile)
- Slide in: 300ms, cubic-bezier(0.4, 0, 0.2, 1)
- Slide out: 250ms, cubic-bezier(0.4, 0, 0.2, 1)
- Transform: translateX(-100%) to translateX(0)
Backdrop (Mobile)
- Fade in: 200ms, ease
- Fade out: 150ms, ease
- Opacity: 0 to 0.5
Sidebar Section Expand/Collapse
- Height transition: 180ms, ease-in-out
- Use max-height or grid-template-rows animation technique
TOC Active State
- Color transition: 150ms, ease
- Smooth color change when scroll spy updates active heading
Anchor Scroll
- Smooth scroll behavior: scroll-behavior: smooth on html or programmatic scrollTo with behavior: "smooth"
- Offset for sticky header: scroll-margin-top on heading elements (header height + 16-24px)
Search Overlay
- Fade in: 200ms, ease-out
- Fade out: 150ms, ease-in
- Scale: Optional subtle scale(0.98) to scale(1) with opacity
Z-Index Layer System
- Header: 40
- Sidebar (desktop): 30
- TOC: 10
- Mobile Backdrop: 40
- Mobile Sidebar Drawer: 50
- Search Overlay: 60
- Tooltips: 70
Edge Cases
Very Long Sidebar Navigation
- Sidebar scrolls independently from content
- Active page should be scrolled into view on load
- Maintain scroll position when navigating between pages in same section
Short Pages (Few Headings)
- Hide TOC when page has fewer than 2 H2/H3 headings
- Content expands to fill available width
Very Long Headings
- TOC links: Truncate with ellipsis after 2 lines (line-clamp: 2)
- Sidebar links: Truncate with ellipsis after 1 line
Deep Nesting in Sidebar
- Max recommended depth: 3 levels
- Beyond 3 levels: Flatten or use separate sidebar section
Code Block Overflow
- Horizontal scroll within code block container
- Never allow code blocks to expand beyond content width
Rapid Scroll (Scroll Spy)
- Intersection Observer handles this efficiently by design
- No additional debounce needed
Print Styles
- Hide sidebar, TOC, header nav, and footer
- Show content area at full width
- Expand all code blocks
Common Variations
With Version Switcher
- Add dropdown in sidebar header or main header for version selection
- URL pattern: /docs/v2/... or /docs/latest/...
With API Reference Layout
- Wider content area or two-panel (description + code example side by side)
- Auto-generated from code or OpenAPI spec
With Search Results Page
- Replace content area with search results list
- Maintain sidebar context
With Feedback Widget
- "Was this helpful?" thumbs up/down at page bottom
- Optional comment field on negative feedback
With Tabbed Content
- Inline tabs for showing code in multiple languages or framework variants (e.g., npm/yarn/pnpm, React/Vue/Angular)
- See Tabs component potion for full specification
Testing Checklist
When implementing this layout, test:
- [ ] Three-column layout renders correctly on desktop (>=1280px)
- [ ] Two-column layout works on tablet (sidebar + content, no TOC)
- [ ] Single-column layout works on mobile (content only, sidebar as drawer)
- [ ] Sidebar navigation tree expands and collapses sections
- [ ] Active page is highlighted in sidebar
- [ ] Active page's parent section auto-expands on load
- [ ] Sidebar scrolls independently and active page is visible on load
- [ ] TOC displays H2/H3 headings from current page
- [ ] Scroll spy correctly highlights current heading in TOC
- [ ] Clicking TOC link scrolls to heading with proper offset for sticky header
- [ ] URL hash updates when scrolling to headings
- [ ] Cmd+K / Ctrl+K opens search overlay
- [ ] Search trigger button opens search overlay on click
- [ ] Mobile sidebar drawer opens and closes with animation
- [ ] Mobile backdrop dismisses sidebar on click
- [ ] Focus is trapped in mobile sidebar drawer
- [ ] Focus returns to hamburger button when drawer closes
- [ ] Body scroll is locked when mobile drawer is open
- [ ] Escape closes mobile drawer
- [ ] Sidebar closes after navigation on mobile
- [ ] Breadcrumbs display correct path
- [ ] Prev/Next navigation links work correctly
- [ ] Code blocks have syntax highlighting and copy button
- [ ] Code block copy button copies content to clipboard
- [ ] Code block file labels display correctly
- [ ] Callout blocks render with correct type styling
- [ ] Theme toggle switches between light and dark mode
- [ ] Keyboard navigation works throughout (Tab, Enter, Escape, Arrow keys)
- [ ] Screen reader landmarks are correctly identified
- [ ] All icon-only buttons have aria-label
- [ ] aria-current="page" set on active sidebar link
- [ ] aria-expanded updated on sidebar section toggles
- [ ] Color contrast meets WCAG AA (4.5:1 body text)
- [ ] Responsive at all breakpoints (no horizontal scroll)
- [ ] Window resize transitions between layouts correctly
- [ ] TOC hides on pages with fewer than 2 headings
- [ ] Footer renders below content (not fixed)
- [ ] Print styles hide navigation and show content at full width
- [ ] Prefers-reduced-motion reduces or disables animations
- [ ] Styling uses only project conventions (no ad-hoc CSS)
- [ ] SSR/hydration safe (no sessionStorage/Intersection Observer during SSR)
See Also
This documentation layout works well with these components:
- Command Palette — Required for the Cmd+K search overlay. The documentation search MUST be implemented as a Command Palette following this potion's full specification (fuzzy matching, grouped results, keyboard navigation, active row tracking, ARIA, mobile full-screen takeover)
- Navbar - For the header navigation bar with responsive mobile menu
- Tabs - For content variant switching within documentation (e.g., npm/yarn/pnpm installation tabs)
- Dark/Light Mode - For the theme switching functionality
- Button - For header actions, copy buttons, navigation buttons, and feedback widgets
These are suggestions for components that pair well with documentation layouts. The layout works independently.
Summary for AI Agents
This documentation layout is a three-column reading layout (sidebar + content + TOC) for developer documentation. Key implementation points:
- Layout: CSS Grid with three columns on desktop, two on tablet, one on mobile
- Sidebar: Hierarchical nav tree with collapsible sections, off-canvas drawer on mobile
- Content: Prose area (max 768px) with breadcrumbs, code blocks, callouts, prev/next nav
- TOC: Scroll-spy powered "On this page" navigation using Intersection Observer
- Search: Cmd+K trigger opens a full Command Palette overlay — MUST read and follow the Command Palette component potion for fuzzy matching, grouped results, keyboard navigation, active row tracking, and accessibility. Do not implement a simple filter input.
- Accessibility: Landmarks, ARIA attributes, keyboard navigation, focus management
- Responsive: Three columns (desktop) > two columns (tablet) > one column (mobile drawer)
- Framework-agnostic: Adapt patterns to any framework's component model