Skip to main content

Documentation Index

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

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

The Window component is the foundational UI panel in Digital Domain. It wraps any content in an authentic Windows 98-style chrome — complete with a navy-to-blue gradient title bar, bevel-shadow borders, a minimize button, a maximize/restore toggle, and an optional close button. By default it is absolutely positioned and fully draggable via Framer Motion’s drag controls; applying className="!static" removes drag behaviour so the window flows naturally within the document.

Import

import { W as Window } from '../components/Window.js';
Window.js is a pre-built ES module produced by Vite. The named export is W — aliased to Window at the import site for readability, as shown above and in assets/main.js.

Props

title
string
required
Text displayed in the Win98-style title bar. Rendered in font-comic font-bold text-sm tracking-wide alongside any provided icon.
icon
ReactNode
A small icon rendered to the left of the title text inside the title bar. Typically a 14 px Lucide icon — e.g. <FileText size={14} />. The icon is wrapped in a 16×16 px flex container.
children
ReactNode
required
Content rendered inside the window body. The body area uses bg-white shadow-win-in mt-[2px] overflow-auto p-2 and grows to fill available height via flex-1.
defaultPosition
object
Initial CSS position as { x: number, y: number }. Passed directly to Framer Motion’s initial prop, which sets the element’s transform translation on first render. Defaults to { x: 0, y: 0 }.
defaultSize
object
Initial dimensions as { width: string | number, height: string | number }. Values are passed to Framer Motion’s animate prop, so you can use CSS strings like "100%" or "auto" as well as pixel numbers. Defaults to { width: 400, height: "auto" }.
className
string
Additional Tailwind utility classes applied to the outermost motion.div root element. Use !static here to disable drag positioning and allow the window to participate in normal document flow (used on the Work and Contact pages).
zIndex
number
CSS z-index for stacking order. When multiple windows share a desktop surface, the focused window should receive the highest value. Defaults to 10.
onFocus
function
Callback fired via onMouseDown on the root element. Use this to bring the clicked window to the front by updating zIndex in the parent’s state.
onClose
function
Callback fired when the ✕ close button in the title bar is clicked. If this prop is omitted the close button is still rendered — pair it with state in the parent to unmount or hide the window.

Usage

Basic static window

The simplest usage: a fixed-size window that sits in the document flow, not draggable.
import { W as Window } from '../components/Window.js';
import { FileText } from 'lucide-react';

function MyPage() {
  return (
    <Window
      title="readme.txt - Notepad"
      icon={<FileText size={14} />}
      defaultSize={{ width: 400, height: 'auto' }}
      className="!static"
    >
      <div className="p-4 font-comic">
        <p>Hello from inside the window!</p>
      </div>
    </Window>
  );
}

Draggable desktop with multiple windows

The Projects and Skills pages render several windows on a shared surface. Each window tracks focus state in the parent so only the active window sits on top.
import { useState } from 'react';
import { W as Window } from '../components/Window.js';
import { FolderGit2 } from 'lucide-react';

const projects = [
  { id: 1, title: 'E-Commerce_2025.exe', name: 'NextGen Storefront', pos: { x: 20,  y: 20  } },
  { id: 2, title: 'AI_Chat_Bot.sys',     name: 'SassyBot AI',        pos: { x: 100, y: 150 } },
  { id: 3, title: 'Legacy_Migrator.bat', name: 'The Data Mover',     pos: { x: 300, y: 80  } },
];

function ProjectsDesktop() {
  const [focusedId, setFocusedId] = useState(null);

  return (
    <div className="h-[80vh] relative overflow-hidden bg-retro-teal/20 border-4 border-win-gray shadow-win-in">
      {projects.map((project) => (
        <Window
          key={project.id}
          title={project.title}
          icon={<FolderGit2 size={14} />}
          defaultPosition={project.pos}
          defaultSize={{ width: 350, height: 'auto' }}
          zIndex={focusedId === project.id ? 50 : 10}
          onFocus={() => setFocusedId(project.id)}
          onClose={() => console.log(`Closed ${project.title}`)}
        >
          <div className="p-4 font-comic">
            <h3 className="font-bold text-xl text-retro-purple">{project.name}</h3>
          </div>
        </Window>
      ))}
    </div>
  );
}

Static window note

Adding className="!static" to a Window removes the absolute positioning that Framer Motion’s drag system relies on, making the window participate in normal block-level document flow. This is used on pages where a single window should expand to fill a column (Work page, Contact page, Case Studies) rather than float freely over a desktop surface.
// Flows with the document — no drag, no absolute positioning
// import { W as Window } from '../components/Window.js';
<Window
  title="CAREER.TXT - Notepad"
  icon={<FileText size={14} />}
  defaultSize={{ width: '100%', height: '100%' }}
  className="!static h-full"
>
  {/* ... */}
</Window>

Styling notes

ElementClasses
Root wrapperabsolute bg-win-gray shadow-win-out p-[3px] flex flex-col
Title barbg-titlebar text-white px-1 py-[2px] — the bg-titlebar utility applies the classic navy → bright-blue horizontal gradient
Title textfont-comic font-bold text-sm tracking-wide
Title bar buttons (minimize, maximize, close)w-4 h-4 bg-win-gray shadow-win-btn active:shadow-win-btn-active
Window bodyflex-1 bg-white shadow-win-in mt-[2px] overflow-auto p-2
Window.js is one of the larger pre-built component chunks in the components/ directory. It bundles Lucide icons (Minus, Square, X) and Framer Motion’s useDragControls alongside the component logic. If you are importing multiple components on the same page, be aware that each *.js file in components/ imports shared dependencies from ../assets/proxy.js to avoid duplicating the React runtime.

Build docs developers (and LLMs) love