Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/dev-haunt/llms.txt

Use this file to discover all available pages before exploring further.

EvidenceBoard transforms your case studies into an atmospheric detective evidence board — a dark cork surface covered in pinned paper cards connected by dashed red string, where clicking any card reveals the full investigation details in a modal overlay. It lives on the /case-studies route and fills the full width of its container.

Overview

The component is entirely self-contained: the case study data, board layout, and modal state are all managed internally. There are no props to pass — drop <EvidenceBoard /> onto the page and the board renders immediately.
The Evidence Board is intentionally self-contained so the spatial card layout (each card has a fixed x/y percentage position and rotation value) stays cohesive. Moving data outside the component would decouple the positions from the content they belong to.

Built-in Case Studies

Three case studies ship with the component, each positioned and rotated to look like they were pinned by hand:
IDTitleSummaryPosition
c1The Missing RenderA React performance mystery.10% / 10%, –5°
c2Curse of the Z-IndexStacking context horrors.55% / 5%, +3°
c3Phantom Layout ShiftCLS optimization.30% / 50%, –2°

Visual Design

The board mimics a physical detective’s cork board:
  • Background — warm brown (#8d6e63) with a thick dark border (#4e342e) and a subtle dot-grid texture at 20 % opacity.
  • Pinned cards — off-white (#f4f1ea) paper with a red pushpin at the top centre, a drop shadow, and a slight rotation applied via the rotate CSS property. Cards scale to 1.05 and straighten on hover.
  • String connections — an SVG layer rendered above the board draws three dashed red paths (stroke="#d32f2f", strokeDasharray="5,5") linking the three cards as quadratic Bézier curves.
  • Modal overlay — clicking a card opens a full-bleed backdrop-blur-sm panel that fades in. The detail card itself slides up from scale: 0.9, y: 20 to scale: 1, y: 0. An X button (Lucide X icon) or a click on the backdrop closes the modal.

Entrance Animation

The Case Studies page wraps <EvidenceBoard /> in a Framer Motion motion.div that animates the whole board into view:
<motion.div
  initial={{ opacity: 0, scale: 0.95 }}
  animate={{ opacity: 1, scale: 1 }}
  transition={{ delay: 0.2, duration: 0.5 }}
>
  <EvidenceBoard />
</motion.div>
The board scales up from 95 % with a 0.2 s delay and reaches full size over 0.5 s.

Usage

import { EvidenceBoard } from './components/EvidenceBoard';

export default function CaseStudiesPage() {
  return (
    <div className="w-full max-w-6xl mx-auto py-12">
      <EvidenceBoard />
    </div>
  );
}
The board uses aspect-[4/3] to maintain its proportions at any width. Wrap it in a max-w-4xl container (as the Case Studies page does) for the best card density and readability.

Customising Case Study Content

Because there are no external props, edit the internal case-study data array directly inside EvidenceBoard.js. In the dist build the array is minified to n; in a source build it would look like:
const caseStudies = [
  {
    id: 'c1',
    title: 'The Missing Render',
    summary: 'A React performance mystery.',
    details: 'Investigated a severe memory leak causing the app to freeze at midnight...',
    x: 10,   // percentage from left edge of the board
    y: 10,   // percentage from top edge of the board
    rotation: -5,
  },
  {
    id: 'c2',
    title: 'Curse of the Z-Index',
    summary: 'Stacking context horrors.',
    details: 'Modals were appearing behind the footer...',
    x: 55,
    y: 5,
    rotation: 3,
  },
  // Add more cards here
];
Each field controls a different aspect of the board:
FieldTypeDescription
idstringUnique key used by React and the selected-card state.
titlestringDisplayed on the pinned card in the spooky font.
summarystringShort tagline shown on the card face.
detailsstringFull text revealed in the modal overlay.
xnumberHorizontal position as a percentage of board width.
ynumberVertical position as a percentage of board height.
rotationnumberCSS rotation in degrees (negative = counter-clockwise).
When adding new cards, update the SVG string paths to connect them. Each <path> element uses percentage-based coordinates ("M 20% 25% Q 40% 40% 65% 20%") so they scale with the board automatically.

Accessibility

  • Each pinned card is a div with an onClick handler. Add role="button" and tabIndex={0} plus an onKeyDown handler if keyboard navigation is a requirement for your audience.
  • The modal close button uses a native <button> element and is keyboard-focusable by default.
  • The modal backdrop click-to-close relies on stopPropagation on the inner card to prevent accidental dismissal.

Build docs developers (and LLMs) love