Skip to main content

Documentation Index

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

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

The ArcadeCabinet component presents a single project as a miniature arcade cabinet. Each card is divided into three visual sections — a top bezel with the project title, a CRT screen area showing the category and description, and a bottom pedestal housing the coin slot and action buttons. On hover, the entire cabinet lifts with a smooth vertical translate, reinforcing the tactile, physical-object metaphor. Color variants let each cabinet carry its own accent color to visually distinguish projects on the grid.

Props

title
string
required
The project name displayed in the top bezel section using the font-pixel typeface. Rendered in the accent color defined by the color prop.
description
string
required
A short project description displayed on the CRT screen area. Appears below the category badge in a smaller, dimmed text style.
category
string
required
A label displayed as a badge overlaid on the screen area (e.g., "WEB APP", "TOOL", "GAME"). Styled with the accent color border and text.
color
"lime" | "magenta" | "cyan" | "orange"
required
The accent color theme for the cabinet. Controls border colors, title text, category badge, and button accents. Maps to the four primary palette colors of the app.
ValueHexUsed for
lime#a3ff12Borders, title, category badge
magenta#ff00aaBorders, title, category badge
cyan#00ffffBorders, title, category badge
orange#ff6600Borders, title, category badge
mockDataNote
string
Optional notice string rendered inside the screen area to indicate placeholder or work-in-progress content (e.g., "DEMO COMING SOON"). When present, it is prefixed with an asterisk (*) and displayed in orange italic text. When omitted, no note is displayed.

Usage

import ArcadeCabinet from "./components/ArcadeCabinet";

<ArcadeCabinet
  title="PIXEL DUNGEON"
  description="A procedurally generated dungeon crawler built with React and Canvas API."
  category="GAME"
  color="magenta"
/>

// With optional mock data note
<ArcadeCabinet
  title="RETRO DASHBOARD"
  description="Analytics dashboard with arcade-themed data visualisations."
  category="WEB APP"
  color="cyan"
  mockDataNote="LIVE DATA COMING SOON"
/>

Visual Structure

The cabinet is composed of three stacked sections inside a single motion.div:

1. Top Bezel

The bezel is a narrow header strip with a colored border-top (4 px solid, accent color) that mimics the painted trim of a real arcade cabinet. The project title is centered inside using font-pixel, colored with the accent.
┌─────────────────────────────┐  ← accent-colored top border
│        PIXEL DUNGEON         │  ← font-pixel title

2. Screen Area

The screen occupies a 16:9 aspect-video region with a black background. It contains:
  • CRT overlay effect — a local scanline layer applied directly to the screen div, independent of the root CRTOverlay.
  • Category badge — a small pill/label in the top-left corner with accent-colored border and text.
  • Description text — the project description rendered in a reduced-opacity monospace style.
  • mockDataNote (optional) — if provided, displayed at the bottom of the screen with an asterisk prefix (*), rendered in orange italic text.
┌─────────────────────────────┐
│ [GAME]                       │  ← category badge
│                              │
│  A procedurally generated    │  ← description
│  dungeon crawler built with  │
│  React and Canvas API.       │
│                              │
└─────────────────────────────┘

3. Bottom Pedestal

The pedestal section houses the cabinet controls:
  • Coin slot visual — a decorative horizontal slot shape with an orange pulsing indicator dot, echoing the HUD’s INSERT COIN prompt.
  • Action buttons — three buttons arranged in a row:
ButtonIconColor
RUN DEMOPlay (Lucide)Lime
SOURCEGithub (Lucide)Cyan
READMEFileText (Lucide)Magenta
        ●  [== COIN SLOT ==]
  [▶ RUN DEMO] [⌥ SOURCE] [☰ README]

Hover Animation

The entire cabinet is wrapped in a motion.div with a whileHover prop:
<motion.div whileHover={{ y: -10 }}>
Hovering lifts the cabinet 10 px upward, simulating the physical sensation of picking up a miniature cabinet.

Implementation Notes

import { motion } from "framer-motion";
import { Play, Github, FileText } from "lucide-react";

const colorMap = {
  lime:    "#a3ff12",
  magenta: "#ff00aa",
  cyan:    "#00ffff",
  orange:  "#ff6600",
};

export default function ArcadeCabinet({
  title,
  description,
  category,
  color,
  mockDataNote,
}) {
  const accent = colorMap[color];

  return (
    <motion.div
      whileHover={{ y: -10 }}
      className="flex flex-col border border-current rounded-sm overflow-hidden"
      style={{ color: accent }}
    >
      {/* Bezel */}
      <div className="border-t-4 border-current px-4 py-3">
        <h3 className="font-pixel text-sm text-current text-center">{title}</h3>
      </div>

      {/* Screen */}
      <div className="aspect-video bg-black relative overflow-hidden">
        {/* scanlines */}
        <div className="crt-overlay absolute inset-0 pointer-events-none" />

        <span className="absolute top-2 left-2 font-pixel text-xs border border-current px-2 py-1">
          {category}
        </span>
        <p className="absolute inset-0 flex items-center px-4 text-xs text-white/60 font-mono mt-8">
          {description}
        </p>
        {mockDataNote && (
          <p className="absolute bottom-2 left-0 right-0 text-center font-pixel text-xs text-orange-400 italic">
            *{mockDataNote}
          </p>
        )}
      </div>

      {/* Pedestal */}
      <div className="px-4 py-3 flex flex-col gap-3 bg-black/40">
        {/* Coin slot */}
        <div className="flex items-center gap-2">
          <span className="w-2 h-2 rounded-full bg-orange-500 animate-pulse" />
          <div className="h-1 flex-1 bg-white/10 rounded-full" />
        </div>

        {/* Buttons */}
        <div className="flex gap-2 flex-wrap">
          <button className="font-pixel text-xs text-lime flex items-center gap-1 border border-lime px-2 py-1">
            <Play size={10} /> RUN DEMO
          </button>
          <button className="font-pixel text-xs text-cyan flex items-center gap-1 border border-cyan px-2 py-1">
            <Github size={10} /> SOURCE
          </button>
          <button className="font-pixel text-xs text-magenta flex items-center gap-1 border border-magenta px-2 py-1">
            <FileText size={10} /> README
          </button>
        </div>
      </div>
    </motion.div>
  );
}
<ArcadeCabinet
  title="OPEN SOURCE CLI"
  description="A developer productivity tool for scaffolding projects with opinionated defaults."
  category="TOOL"
  color="lime"
/>
Lay multiple ArcadeCabinet components out in a CSS grid (grid-cols-1 md:grid-cols-2 lg:grid-cols-3) for the Level Select page. The fixed aspect-video screen ratio means all cards maintain consistent heights in the grid without any extra height-matching logic.

Where It’s Used

ArcadeCabinet is the primary display unit on the /projects (LEVEL SELECT) page. Each project in the portfolio data array maps to one ArcadeCabinet instance. The color variant is typically assigned by cycling through the four available values to ensure visual variety across the grid.

Build docs developers (and LLMs) love