Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/neon-retro-web/llms.txt

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

The Window component is the primary layout primitive of the Neon Retro Web portfolio. It renders every content panel — Projects, About, Skills, and Contact — as a Windows 98/XP-era application window complete with a gradient title bar, beveled Win98-style control buttons, and a snappy spring entrance animation powered by Framer Motion. Drop any JSX into its children and it is instantly wrapped in authentic Y2K chrome.
In the compiled bundle, Window is exported under the minified name W. When building on top of this project, import from the source file (components/Window.js) to use the readable Window name shown in the examples below.

Props

title
string
required
The text displayed in the window’s title bar. Conventionally written in the style of a retro filename, e.g. "My_Projects.exe" or "About_Me.txt".
icon
ReactNode
An optional icon rendered to the left of the title text inside the title bar. Pass any React node — a Lucide icon at w-4 h-4 works best to match the built-in scale.
className
string
default:"\"\""
Additional CSS classes applied to the outermost motion wrapper. Use this to constrain width (max-w-2xl), add margin, or override layout properties without touching the interior chrome.
isActive
boolean
default:"true"
Controls whether the window appears focused. When true the title bar renders with a bg-gradient-to-r from-y2k-teal to-y2k-turquoise and the window sits at z-10 with full opacity. When false the title bar falls back to bg-gray-700, the window drops to z-0, and opacity reduces to opacity-80 to suggest it is in the background.
onClose
() => void
Callback fired when the user clicks the close button (the rightmost control button in the title bar). If omitted the close button is still rendered but produces no effect.

Basic Usage

import { Window } from '../components/Window';
import { Settings } from 'lucide-react';

<Window
  title="My_Projects.exe"
  icon={<Settings className="w-4 h-4" />}
  className="max-w-2xl"
  isActive={true}
  onClose={() => console.log('closed')}
>
  <p className="font-code text-y2k-teal">Content goes here</p>
</Window>

Active vs Inactive State

Windows in the portfolio stack can be layered. The isActive prop mirrors the focus model of a real desktop OS: the foreground window is vivid and elevated while background windows fade and recede.
When isActive is true (the default), the window receives:
  • Title bar: bg-gradient-to-r from-y2k-teal to-y2k-turquoise — the signature cyan-to-turquoise sweep, with text-black font-bold title text
  • Z-index: z-10 — sits above inactive siblings
  • Opacity: full (no modifier applied)
Use this state for whichever window the user is currently interacting with.
<Window title="Active_Window.exe" isActive={true}>
  <p className="font-code text-y2k-teal">I am in focus.</p>
</Window>

Title Bar Control Buttons

The title bar renders three Win98-style beveled buttons at its right edge — each is a w-5 h-5 bg-gray-300 square with a raised bevel border (border-t-white border-l-white border-b-gray-600 border-r-gray-600):
ButtonIconBehavior
Minimizeminus (Lucide)No default behavior — wire up via children or state
Maximizesquare (Lucide)No default behavior — wire up via children or state
Closex (Lucide)Calls onClose if provided
Only the close button is wired to a prop. Minimize and maximize are rendered for visual authenticity; add your own click handlers if you need them.

Framer Motion Entrance Animation

Every Window mounts and unmounts through a Framer Motion AnimatePresence spring. The animation configuration is baked in and cannot be overridden via props — it is intentionally snappy to reinforce the Y2K “dialog pop” feel:
initial:    { scale: 0.95, opacity: 0 }
animate:    { scale: 1,    opacity: 1 }
exit:       { scale: 0.95, opacity: 0 }
transition: { type: 'spring', stiffness: 300, damping: 25 }
Wrap Window instances in Framer Motion’s <AnimatePresence> whenever you conditionally render them so the exit animation plays on unmount.

Scrollable Content Area

The inner content wrapper carries two Tailwind classes that are always applied regardless of props:
  • .bg-y2k-bg/80 — semi-transparent dark background that lets any canvas or gradient beneath the window bleed through subtly.
  • .scrollbar-retro — a custom scrollbar utility defined in the project’s global CSS. It renders a thin teal-on-dark scrollbar styled to match the retro aesthetic.
If your content overflows vertically the retro scrollbar will appear automatically. There is no need to add overflow-y-auto manually — the content area handles it.

Nesting Components Inside Window

Window renders its children prop directly inside the styled content area, so any combination of React components works:
import { Window } from '../components/Window';
import { Marquee, BadgeNew } from '../components/RetroElements';
import { Code } from 'lucide-react';

<Window
  title="Skills.exe"
  icon={<Code className="w-4 h-4" />}
  className="max-w-xl"
>
  {/* Scrolling ticker at the top of the panel */}
  <Marquee text="JavaScript · TypeScript · React · Node.js ·" speed="15s" />

  <div className="p-4 space-y-2">
    <p className="font-code text-y2k-teal">
      Full-stack developer specialising in modern web.
    </p>
    <BadgeNew text="Hiring!" color="lime" />
  </div>
</Window>

RetroElements

Marquee tickers, blinking badges, hit counters, and the Under Construction panel — all designed to nest inside Window.

Framer Motion Docs

Learn more about the spring physics driving the Window entrance animation.

Build docs developers (and LLMs) love