Skip to content

rynonl/react-desktop-os

Repository files navigation

React Desktop OS

A complete, windowed desktop operating system component library for React. Build desktop applications with windows, menus, icons, and a full window management system.

Features

  • πŸͺŸ Full Window Management - Draggable, resizable windows with minimize/maximize/close controls
  • 🎨 Runtime Theming - Switch themes on-the-fly with CSS variables
  • πŸ–₯️ System Bar - Customizable top menu bar with dropdown menus, submenus, and icons
  • πŸ“Š Taskbar - Window management bar showing all open windows (automatically included)
  • 🎯 Desktop Icons - Grid-based icons with drag-and-drop, selection, and double-click to open
  • ⚑ Zero Dependencies - Only React as peer dependency
  • πŸ“¦ TypeScript - Full type safety with comprehensive type definitions
  • πŸ§ͺ Tested - Comprehensive test coverage with Vitest

Screenshots

React Desktop OS Demo

System Bar Menu Demo

Installation

npm install react-desktop-os

Quick Start

import { DesktopOS, Window } from 'react-desktop-os'
import 'react-desktop-os/styles'

function App() {
  return (
    <DesktopOS theme="default">
      <Window
        id="my-app"
        title="My Application"
        initialPosition="center"
        initialSize={{ width: 600, height: 400 }}
      >
        <div>Your app content here</div>
      </Window>
    </DesktopOS>
  )
}

The Window component automatically registers itself with the desktop context when mounted. The window will be rendered by the built-in WindowManager and will appear in the taskbar.

Demo Application

A full-featured demo is included showing all capabilities.

Running the Demo

# Clone the repository
git clone <repo-url>
cd react-desktop-os

# Install dependencies
npm install

# Start the dev server
npm run dev

Open your browser to http://localhost:3001 to see the demo.

Testing

# Run tests
npm test

# Run tests with UI
npm run test:ui

# Run tests with coverage
npm run test:coverage

Complete Example

Here's a more complete example demonstrating the key features:

import {
  DesktopOS,
  SystemBar,
  SystemMenu,
  MenuItem,
  Clock,
  useDesktop,
  useTheme,
} from 'react-desktop-os'
import 'react-desktop-os/styles'
import { useEffect } from 'react'

function MyDesktopApp() {
  const { openWindow, addDesktopIcon } = useDesktop()
  const { setTheme, themes } = useTheme()

  useEffect(() => {
    // Add desktop icons
    addDesktopIcon({
      id: 'my-app',
      label: 'My App',
      icon: 'πŸ“',
      position: { row: 0, col: 0 },
      window: {
        title: 'My Application',
        icon: 'πŸ“',
        initialSize: { width: 600, height: 400 },
        content: (
          <div>
            <h1>Hello Desktop!</h1>
          </div>
        ),
      },
    })
  }, [])

  return (
    <>
      {/* System Bar with Menus */}
      <SystemBar position="top">
        <SystemMenu label="File" icon="πŸ“" align="left">
          <MenuItem
            label="New Window"
            shortcut="Ctrl+N"
            icon="βž•"
            onClick={() =>
              openWindow({
                id: `window-${Date.now()}`,
                title: 'New Window',
                initialPosition: 'cascade',
                content: <div>New window content</div>,
              })
            }
          />
          <MenuItem divider />
          <MenuItem label="Exit" icon="πŸšͺ" disabled />
        </SystemMenu>

        <SystemMenu label="View" icon="πŸ‘οΈ" align="left">
          <MenuItem label="Theme" icon="🎨">
            {Object.keys(themes).map((themeName) => (
              <MenuItem
                key={themeName}
                label={themeName}
                onClick={() => setTheme(themeName)}
              />
            ))}
          </MenuItem>
        </SystemMenu>

        <Clock format="12h" align="right" />
      </SystemBar>
    </>
  )
}

function App() {
  return (
    <DesktopOS theme="dark">
      <MyDesktopApp />
    </DesktopOS>
  )
}

Core Concepts

DesktopOS Component

The root component that wraps your entire desktop application. It includes theme and desktop context providers.

<DesktopOS
  theme="default" // 'default', 'dark', or 'light'
  wallpaper="/path/to/bg.jpg" // Optional wallpaper (string or WallpaperConfig)
>
  {children}
</DesktopOS>

Wallpaper Options:

// Simple string URL
<DesktopOS wallpaper="/wallpaper.jpg">

// Full configuration
<DesktopOS wallpaper={{
  url: "/wallpaper.jpg",
  fit: "cover",  // 'cover', 'contain', 'fill', or 'none'
  color: "#2c2c2c"  // Optional background color
}}>

Desktop Component

The Desktop component is automatically rendered by DesktopOS and includes:

  • Window rendering via WindowManager
  • Taskbar (automatically included at the bottom)
  • Desktop icon grid
  • Wallpaper handling

You typically don't need to use Desktop directly unless you're building a custom layout.

Context and Hooks

Access desktop functionality using the useDesktop hook:

import { useDesktop } from 'react-desktop-os'

function MyComponent() {
  const {
    state, // Current desktop state
    openWindow, // Open a new window programmatically
    closeWindow, // Close a window by ID
    minimizeWindow, // Minimize a window by ID
    maximizeWindow, // Maximize a window by ID
    restoreWindow, // Restore a minimized/maximized window
    focusWindow, // Bring a window to front
    addDesktopIcon, // Add a desktop icon
    removeDesktopIcon, // Remove a desktop icon
    selectIcon, // Select/deselect an icon
  } = useDesktop()

  // Use desktop methods...
}

Access theme functionality using the useTheme hook:

import { useTheme } from 'react-desktop-os'

function MyComponent() {
  const {
    theme, // Current theme object
    setTheme, // Change theme by name or Theme object
    themes, // Available themes (default, dark, light)
    registerTheme, // Register a custom theme
  } = useTheme()
}

Windows

Windows can be created two ways:

1. Declarative (JSX)

Use the Window component directly as a child of DesktopOS. It will automatically register itself when mounted:

<DesktopOS>
  <Window
    id="my-window"
    title="My Window"
    icon="πŸ“„"
    initialPosition="center" // or 'cascade' or { x: 100, y: 100 }
    initialSize={{ width: 600, height: 400 }}
    minSize={{ width: 300, height: 200 }}
    maxSize={{ width: 1200, height: 800 }}
    closable={true}
    minimizable={true}
    maximizable={true}
    resizable={true}
    draggable={true}
  >
    <div>Window content</div>
  </Window>
</DesktopOS>

2. Imperative (programmatically)

Use the openWindow method from useDesktop:

import { useDesktop } from 'react-desktop-os'

function MyComponent() {
  const { openWindow } = useDesktop()

  const handleOpenWindow = () => {
    openWindow({
      id: 'unique-id',
      title: 'My Window',
      icon: 'πŸ“„',
      initialPosition: 'center',
      initialSize: { width: 600, height: 400 },
      minSize: { width: 300, height: 200 },
      maxSize: { width: 1200, height: 800 },
      closable: true,
      minimizable: true,
      maximizable: true,
      resizable: true,
      draggable: true,
      content: <div>Window content</div>,
    })
  }

  return <button onClick={handleOpenWindow}>Open Window</button>
}

Window Position Options:

  • "center" - Center in the desktop
  • "cascade" - Automatically cascade from the last window
  • { x: number, y: number } - Specific pixel position

Desktop Icons

Desktop icons are grid-based shortcuts that can open windows when double-clicked.

import { useDesktop } from 'react-desktop-os'

function MyComponent() {
  const { addDesktopIcon, removeDesktopIcon } = useDesktop()

  useEffect(() => {
    addDesktopIcon({
      id: 'documents',
      label: 'Documents',
      icon: 'πŸ“„',
      position: { row: 0, col: 0 }, // or 'auto' for automatic placement
      window: {
        title: 'Documents',
        icon: 'πŸ“„',
        initialSize: { width: 600, height: 400 },
        content: <div>Documents folder</div>,
      },
    })
  }, [])
}

Desktop Icon Grid:

  • Icons are positioned on a grid (default: 96px per cell)
  • Position uses { row: number, col: number }
  • Use position: 'auto' for automatic placement in the next available slot
  • Icons can be dragged to reposition
  • Single-click to select, double-click to open

Taskbar

The Taskbar component is automatically included in the Desktop component at the bottom of the screen. It shows all open windows and allows quick access to minimize/restore.

The taskbar automatically:

  • Shows all open windows with their icons and titles
  • Highlights the active (focused) window
  • Shows minimized windows with a visual indicator
  • Allows clicking to restore minimized windows or focus windows

You don't need to manually add the taskbar - it's built into the desktop environment.

Window Manager

The WindowManager component is automatically included in the Desktop component. It handles rendering all windows from the desktop state. You don't need to use it directly.

System Bar & Menus

The system bar provides a top-level menu interface similar to Linux desktop environments. See SYSTEM_BAR.md for complete documentation.

Basic System Bar

import { SystemBar, SystemMenu, MenuItem, Clock } from 'react-desktop-os'
;<SystemBar position="top">
  <SystemMenu label="File" align="left">
    <MenuItem label="New" icon="βž•" onClick={() => {}} />
    <MenuItem label="Open" icon="πŸ“‚" onClick={() => {}} />
    <MenuItem divider />
    <MenuItem label="Exit" icon="πŸšͺ" onClick={() => {}} />
  </SystemMenu>

  <Clock format="12h" align="right" />
</SystemBar>

Menu with Submenus

<SystemMenu label="Edit" align="left">
  <MenuItem label="Copy" shortcut="Ctrl+C" icon="πŸ“‹" />
  <MenuItem label="Paste" shortcut="Ctrl+V" icon="πŸ“„" />
  <MenuItem divider />
  <MenuItem label="Preferences" icon="βš™οΈ">
    <MenuItem label="General" />
    <MenuItem label="Appearance" />
    <MenuItem label="Keyboard" />
  </MenuItem>
</SystemMenu>

Icon-Only Menus

Perfect for system tray icons:

<SystemMenu icon="πŸ””" align="right">
  <MenuItem label="No new notifications" disabled />
</SystemMenu>

See full System Bar documentation β†’

Theming

React Desktop OS includes a powerful theming system with three built-in themes and full customization support. See THEMING.md for complete documentation.

Switching Themes

import { useTheme } from 'react-desktop-os'

function ThemeSwitcher() {
  const { theme, setTheme, themes } = useTheme()

  return (
    <div>
      {Object.keys(themes).map((themeName) => (
        <button key={themeName} onClick={() => setTheme(themeName)}>
          {themeName}
        </button>
      ))}
    </div>
  )
}

Available Themes

  • default - Linux-style modern theme with blue accents
  • dark - Dark theme with warm accents
  • light - Clean light theme

Creating Custom Themes

import { useTheme } from 'react-desktop-os'

function CustomThemeExample() {
  const { registerTheme, setTheme } = useTheme()

  useEffect(() => {
    registerTheme('custom', {
      name: 'custom',
      colors: {
        desktopBg: '#1e293b',
        desktopAccent: '#38bdf8',
        // ... other colors
      },
      // ... other theme properties
    })
    setTheme('custom')
  }, [])
}

See full Theming documentation β†’

API Reference

Types

// Window Configuration
interface WindowConfig {
  id: string
  title: string
  icon?: ReactNode | string
  initialPosition?: Position | 'center' | 'cascade'
  initialSize?: Size
  minSize?: Size
  maxSize?: Size
  content?: ReactNode
  children?: ReactNode // Alternative to content
  closable?: boolean // Default: true
  minimizable?: boolean // Default: true
  maximizable?: boolean // Default: true
  resizable?: boolean // Default: true
  draggable?: boolean // Default: true
  chromeless?: boolean // Hide title bar (default: false)
  modal?: boolean // Modal window (default: false)
}

// Desktop Icon Configuration
interface DesktopIconConfig {
  id: string
  label: string
  icon: ReactNode | string
  position?: GridPosition | 'auto'
  window?: WindowConfig
  onDoubleClick?: () => void
}

// Position and Size
interface Position {
  x: number
  y: number
}

interface Size {
  width: number
  height: number
}

interface GridPosition {
  row: number
  col: number
}

// Wallpaper Configuration
interface WallpaperConfig {
  url?: string
  color?: string
  fit?: 'cover' | 'contain' | 'fill' | 'none'
}

useDesktop Hook

interface DesktopContextValue {
  state: DesktopState
  openWindow: (config: WindowConfig) => string
  closeWindow: (id: string) => void
  minimizeWindow: (id: string) => void
  maximizeWindow: (id: string) => void
  restoreWindow: (id: string) => void
  focusWindow: (id: string) => void
  moveWindow: (id: string, position: Position) => void
  resizeWindow: (id: string, size: Size) => void
  updateWindow: (id: string, updates: Partial<WindowState>) => void
  addDesktopIcon: (config: DesktopIconConfig) => void
  removeDesktopIcon: (id: string) => void
  moveDesktopIcon: (id: string, position: GridPosition) => void
  selectIcon: (id: string | null) => void
}

useTheme Hook

interface ThemeContextValue {
  theme: Theme
  setTheme: (theme: Theme | string) => void
  themes: Record<string, Theme>
  registerTheme: (name: string, theme: Theme) => void
}

Browser Support

React Desktop OS works in all modern browsers:

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)

Performance

React Desktop OS is optimized for performance:

  • Efficient re-rendering with React context
  • CSS-based animations and transitions
  • Minimal JavaScript overhead
  • No external dependencies
  • Smart z-index management to prevent infinite growth

Project Structure

react-desktop-os/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ components/       # React components
β”‚   β”‚   β”œβ”€β”€ core/        # DesktopOS, Desktop
β”‚   β”‚   β”œβ”€β”€ window/      # Window, WindowManager, TitleBar, etc.
β”‚   β”‚   β”œβ”€β”€ system-bar/  # SystemBar, SystemMenu, MenuItem, Clock
β”‚   β”‚   β”œβ”€β”€ taskbar/     # Taskbar, TaskbarItem
β”‚   β”‚   β”œβ”€β”€ desktop-icon/# DesktopIcon, DesktopIconGrid
β”‚   β”‚   └── shared/      # Shared components (Icon, etc.)
β”‚   β”œβ”€β”€ contexts/        # React contexts
β”‚   β”‚   β”œβ”€β”€ DesktopContext.tsx
β”‚   β”‚   └── ThemeContext.tsx
β”‚   β”œβ”€β”€ hooks/           # Custom hooks
β”‚   β”‚   β”œβ”€β”€ useDesktop.ts
β”‚   β”‚   β”œβ”€β”€ useTheme.ts
β”‚   β”‚   β”œβ”€β”€ useWindow.ts
β”‚   β”‚   β”œβ”€β”€ useWindowDrag.ts
β”‚   β”‚   β”œβ”€β”€ useWindowResize.ts
β”‚   β”‚   β”œβ”€β”€ useIconDrag.ts
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ types/           # TypeScript definitions
β”‚   β”œβ”€β”€ utils/           # Utility functions
β”‚   └── styles/          # CSS and themes
β”‚       β”œβ”€β”€ components/  # Component styles
β”‚       β”œβ”€β”€ themes/      # Theme definitions (default, dark, light)
β”‚       └── index.css    # Main stylesheet
β”œβ”€β”€ demo/                # Demo application
β”œβ”€β”€ tests/               # Test files
└── dist/                # Build output

Development

Setup

# Install dependencies
npm install

# Run dev server with demo
npm run dev

# Run tests
npm test

# Run tests with UI
npm run test:ui

# Run tests with coverage
npm run test:coverage

# Build library
npm run build

# Lint code
npm run lint

# Format code
npm run format

Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

License

MIT

Credits

Built with ❀️ using React and TypeScript.

About

A window-ed OS like component system for React

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published