npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mohamedfariz/react-idle-screensaver

v0.2.6

Published

A lightweight React component and hook for detecting user inactivity and displaying a customizable idle screensaver. Ideal for kiosks, dashboards, TVs, and unattended React applications. Fully typed and compatible with React 18+

Readme

@mohamedfariz/react-idle-screensaver

A lightweight, TypeScript-first React library for detecting user inactivity and displaying customizable screensaver overlays.

Built for kiosks, dashboards, TVs, digital signage, and unattended React applications.
Compatible with React 18+ and designed to be tree-shakable, SSR-safe, and bundler-friendly.


✨ Features

  • Idle / inactivity detection
  • Pluggable screensaver components
  • Built-in screensavers included
  • React 18+ compatible
  • TypeScript-first API with .d.ts
  • CSS-based styling (no inline styles)
  • Tree-shakable and Rollup-friendly
  • Safe for kiosk / long-running displays

🎮 Live Demo

Try out the library in a live CodeSandbox environment:

🚀 View Interactive Demo

Explore all built-in screensavers and customize settings in real-time.


📦 Installation

Via Package Manager (Recommended)

npm install @mohamedfariz/react-idle-screensaver

or

yarn add @mohamedfariz/react-idle-screensaver

or

pnpm add @mohamedfariz/react-idle-screensaver

or

bun add @mohamedfariz/react-idle-screensaver

Via CDN (No Build Tool Required)

You can use the library directly in the browser without a build tool:

Using unpkg:

<!-- React and ReactDOM (peer dependencies) -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<!-- Lucide React (required for BouncingScreensaver) -->
<script src="https://unpkg.com/lucide-react@latest/dist/umd/lucide-react.js"></script>

<!-- React Idle Screensaver -->
<link rel="stylesheet" href="https://unpkg.com/@mohamedfariz/react-idle-screensaver/dist/style.css" />
<script src="https://unpkg.com/@mohamedfariz/react-idle-screensaver/dist/index.umd.js"></script>

Using jsDelivr:

<!-- React and ReactDOM (peer dependencies) -->
<script crossorigin src="https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js"></script>

<!-- Lucide React (required for BouncingScreensaver) -->
<script src="https://cdn.jsdelivr.net/npm/lucide-react@latest/dist/umd/lucide-react.js"></script>

<!-- React Idle Screensaver -->
<link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/@mohamedfariz/react-idle-screensaver/dist/style.css"
/>
<script src="https://cdn.jsdelivr.net/npm/@mohamedfariz/react-idle-screensaver/dist/index.umd.js"></script>

CDN Usage Example:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>React Idle Screensaver - CDN Example</title>

        <!-- CSS -->
        <link rel="stylesheet" href="https://unpkg.com/@mohamedfariz/react-idle-screensaver/dist/style.css" />
    </head>
    <body>
        <div id="root"></div>

        <!-- React -->
        <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
        <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

        <!-- Lucide React (required for BouncingScreensaver) -->
        <script src="https://unpkg.com/lucide-react@latest/dist/umd/lucide-react.js"></script>

        <!-- React Idle Screensaver -->
        <script src="https://unpkg.com/@mohamedfariz/react-idle-screensaver/dist/index.umd.js"></script>

        <script>
            const { ScreensaverManager, MatrixScreensaver } = window.ReactIdleScreensaver;
            const { createElement } = React;
            const { createRoot } = ReactDOM;

            function App() {
                return createElement(
                    ScreensaverManager,
                    { component: MatrixScreensaver, timeout: 5000 },
                    createElement(
                        'div',
                        { style: { height: '100vh', padding: '20px' } },
                        createElement('h1', null, 'My Application'),
                        createElement('p', null, 'Move your mouse to dismiss the screensaver'),
                    ),
                );
            }

            const root = createRoot(document.getElementById('root'));
            root.render(createElement(App));
        </script>
    </body>
</html>

Note: When using CDN, the library is available as window.ReactIdleScreensaver and includes all exports:

  • ScreensaverManager
  • MatrixScreensaver
  • BouncingScreensaver
  • StarfieldScreensaver
  • ImageSliderScreensaver
  • useIdleTimer
  • ScreensaverContext

🚀 Quick Start

1. Import CSS (Required)

The library requires CSS to be imported in your application:

import '@mohamedfariz/react-idle-screensaver/style.css';

Important: Place this import at the top of your main app file (e.g., main.tsx, App.tsx, or index.tsx).

2. Basic Usage

Wrap your application with ScreensaverManager and provide a screensaver component:

import { ScreensaverManager, MatrixScreensaver } from '@mohamedfariz/react-idle-screensaver';
import '@mohamedfariz/react-idle-screensaver/style.css';

function App() {
    return (
        <ScreensaverManager component={MatrixScreensaver} timeout={5000}>
            <div style={{ height: '100vh' }}>
                <h1>My Application</h1>
                <p>Your content here...</p>
            </div>
        </ScreensaverManager>
    );
}

export default App;

The screensaver will automatically activate after 5 seconds (5000ms) of user inactivity.


📚 Complete Examples

Example 1: Using Different Built-in Screensavers

import {
    ScreensaverManager,
    MatrixScreensaver,
    BouncingScreensaver,
    StarfieldScreensaver,
    ImageSliderScreensaver,
} from '@mohamedfariz/react-idle-screensaver';
import '@mohamedfariz/react-idle-screensaver/style.css';

// Example with Matrix
function AppWithMatrix() {
    return (
        <ScreensaverManager component={MatrixScreensaver} timeout={10000}>
            <YourApp />
        </ScreensaverManager>
    );
}

// Example with Bouncing Badge
function AppWithBouncing() {
    return (
        <ScreensaverManager
            component={BouncingScreensaver}
            componentProps={{ customText: 'Kiosk Mode' }}
            timeout={8000}>
            <YourApp />
        </ScreensaverManager>
    );
}

// Example with Starfield
function AppWithStarfield() {
    return (
        <ScreensaverManager
            component={StarfieldScreensaver}
            componentProps={{ starCount: 600, speed: 5 }}
            timeout={15000}>
            <YourApp />
        </ScreensaverManager>
    );
}

// Example with Image Slider
function AppWithImages() {
    return (
        <ScreensaverManager
            component={ImageSliderScreensaver}
            componentProps={{
                images: ['/images/photo1.jpg', '/images/photo2.jpg', '/images/photo3.jpg'],
                customText: 'My Gallery',
                showTime: true,
                showDate: true,
                interval: 5000,
            }}
            timeout={12000}>
            <YourApp />
        </ScreensaverManager>
    );
}

Example 2: Custom Screensaver with Context

Create a custom screensaver that responds to user interaction:

import { ScreensaverContext } from '@mohamedfariz/react-idle-screensaver';
import { useContext } from 'react';

const InteractiveScreensaver = () => {
    const { stopScreensaver } = useContext(ScreensaverContext);

    return (
        <div
            onClick={stopScreensaver}
            style={{
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'center',
                height: '100vh',
                background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                color: 'white',
                cursor: 'pointer',
            }}>
            <h1 style={{ fontSize: '4rem', marginBottom: '2rem' }}>Welcome Back!</h1>
            <p style={{ fontSize: '1.5rem' }}>👆 Tap anywhere to continue</p>
        </div>
    );
};

// Use it in your app
function App() {
    return (
        <ScreensaverManager component={InteractiveScreensaver} timeout={10000}>
            <YourApp />
        </ScreensaverManager>
    );
}

Example 3: With Callbacks and Dynamic Control

import { useState } from 'react';
import { ScreensaverManager, MatrixScreensaver } from '@mohamedfariz/react-idle-screensaver';

function App() {
    const [isActive, setIsActive] = useState(true);
    const [timeout, setTimeout] = useState(5000);

    const handleScreensaverStop = () => {
        console.log('User is back!');
        // Log analytics, reset timers, etc.
    };

    return (
        <div>
            <div style={{ padding: '20px', background: '#f0f0f0' }}>
                <button onClick={() => setIsActive(!isActive)}>
                    {isActive ? 'Disable' : 'Enable'} Screensaver
                </button>
                <input
                    type='number'
                    value={timeout / 1000}
                    onChange={(e) => setTimeout(Number(e.target.value) * 1000)}
                />
                <span> seconds</span>
            </div>

            <ScreensaverManager
                component={MatrixScreensaver}
                componentProps={{
                    color: '#00ff00',
                    speed: 30,
                }}
                timeout={timeout}
                active={isActive}
                zIndex={9999}
                onScreenSaverStop={handleScreensaverStop}>
                <div style={{ padding: '20px' }}>
                    <h1>My Dashboard</h1>
                    <p>Content goes here...</p>
                </div>
            </ScreensaverManager>
        </div>
    );
}

Example 4: Custom Screensaver with Props

interface BrandedScreensaverProps {
    companyName: string;
    logoUrl?: string;
    backgroundColor?: string;
    tagline?: string;
}

const BrandedScreensaver: React.FC<BrandedScreensaverProps> = ({
    companyName,
    logoUrl,
    backgroundColor = '#1a1a1a',
    tagline,
}) => {
    return (
        <div
            style={{
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'center',
                height: '100vh',
                backgroundColor,
                color: 'white',
            }}>
            {logoUrl && (
                <img
                    src={logoUrl}
                    alt={`${companyName} logo`}
                    style={{ width: '200px', marginBottom: '2rem' }}
                />
            )}
            <h1 style={{ fontSize: '3rem', margin: '1rem 0' }}>{companyName}</h1>
            {tagline && <p style={{ fontSize: '1.5rem', opacity: 0.8 }}>{tagline}</p>}
        </div>
    );
};

// Use it
function App() {
    return (
        <ScreensaverManager
            component={BrandedScreensaver}
            componentProps={{
                companyName: 'ACME Corporation',
                logoUrl: '/logo.svg',
                backgroundColor: '#2c3e50',
                tagline: 'Innovation at its finest',
            }}
            timeout={10000}>
            <YourApp />
        </ScreensaverManager>
    );
}

🛠 Built-in Screensavers

| Component | Description | | ---------------------- | --------------------------------------------- | | BouncingScreensaver | Floating badge that bounces around the screen | | MatrixScreensaver | Matrix-style falling characters | | ImageSliderScreensaver | Fullscreen image slideshow with clock | | StarfieldScreensaver | Animated starfield / space-warp effect |

📘 API Reference

<ScreensaverManager />

The main wrapper component that handles idle detection and screensaver display.

| Prop | Type | Default | Description | | ------------------- | ------------------ | ------- | ---------------------------------------------- | | component | ComponentType<T> | — | The screensaver component to display | | componentProps | T | {} | Props to pass to the screensaver component | | timeout | number | 5000 | Idle timeout in milliseconds before activation | | active | boolean | true | Enable or disable the screensaver | | zIndex | number | 50 | CSS z-index for the screensaver overlay | | onScreenSaverStop | () => void | — | Callback function when user resumes activity | | children | ReactNode | — | Your application content |

Example:

<ScreensaverManager
    component={MatrixScreensaver}
    timeout={10000}
    active={true}
    zIndex={100}
    onScreenSaverStop={() => console.log('User is back!')}>
    <YourApp />
</ScreensaverManager>

Built-in Screensaver Components

<BouncingScreensaver />

A floating badge that smoothly bounces around the screen edges.

| Prop | Type | Default | Description | | ------------ | -------- | ------------------ | ------------------------------------- | | customText | string | "System Standby" | Text to display on the bouncing badge |

Example:

<ScreensaverManager
    component={BouncingScreensaver}
    componentProps={{
        customText: 'Idle Mode',
    }}
    timeout={5000}>
    <YourApp />
</ScreensaverManager>

<MatrixScreensaver />

Classic Matrix-style falling characters effect with customizable appearance.

| Prop | Type | Default | Description | | ------------ | -------- | ---------------------------------------------- | ---------------------------------------------- | | characters | string | "01アイウエオカキクケコサシスセソタチツテト" | Characters to display in the falling animation | | fontSize | number | 14 | Font size in pixels | | speed | number | 33 | Animation speed in ms (lower = faster) | | color | string | "#0f0" | Color of the matrix characters (CSS color) |

Example:

<ScreensaverManager
    component={MatrixScreensaver}
    componentProps={{
        characters: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
        fontSize: 16,
        speed: 40,
        color: '#00ff00',
    }}
    timeout={8000}>
    <YourApp />
</ScreensaverManager>

<ImageSliderScreensaver />

Fullscreen image slideshow with optional clock and date display.

| Prop | Type | Default | Description | | ------------ | ---------- | ------------------------------------ | ---------------------------------------------- | | customText | string | "Photography Collection" | Text displayed at the bottom of the screen | | showTime | boolean | true | Show current time in HH:MM format | | showDate | boolean | true | Show current date (e.g., "Monday, January 25") | | images | string[] | Array of 4 default Unsplash images | Array of image URLs to display | | interval | number | 6000 | Time between slides in milliseconds |

Example:

<ScreensaverManager
    component={ImageSliderScreensaver}
    componentProps={{
        customText: 'Company Showcase',
        showTime: true,
        showDate: true,
        images: [
            '/images/slide1.jpg',
            '/images/slide2.jpg',
            '/images/slide3.jpg',
            'https://example.com/image.jpg',
        ],
        interval: 5000,
    }}
    timeout={10000}>
    <YourApp />
</ScreensaverManager>

Default Images:

  • Mountain landscape
  • City skyline
  • Technology/circuit boards
  • Desert landscape

<StarfieldScreensaver />

Animated 3D starfield effect simulating space travel.

| Prop | Type | Default | Description | | ----------- | -------- | ------- | ---------------------------------------- | | starCount | number | 400 | Number of stars to render | | speed | number | 4 | Speed of star movement (higher = faster) |

Example:

<ScreensaverManager
    component={StarfieldScreensaver}
    componentProps={{
        starCount: 800,
        speed: 6,
    }}
    timeout={7000}>
    <YourApp />
</ScreensaverManager>

🪝 Advanced: useIdleTimer Hook

For more granular control, you can use the useIdleTimer hook directly in your components:

import { useIdleTimer } from '@mohamedfariz/react-idle-screensaver';

function MyComponent() {
    const isIdle = useIdleTimer(5000, true);

    return (
        <div>
            <p>Status: {isIdle ? 'User is idle' : 'User is active'}</p>
        </div>
    );
}

Hook Parameters

| Parameter | Type | Default | Description | | --------- | --------- | ------- | -------------------------------------- | | timeout | number | 5000 | Time in milliseconds before idle state | | active | boolean | true | Whether the idle detection is enabled |

Hook Return Value

Returns a boolean indicating whether the user is currently idle.

Example: Custom Idle Behavior

import { useIdleTimer } from "@mohamedfariz/react-idle-screensaver";
import { useEffect } from "react";

function Dashboard() {
    const isIdle = useIdleTimer(10000);

    useEffect(() => {
        if (isIdle) {
            console.log('User went idle - pausing animations');
            // Pause expensive operations
        } else {
            console.log('User is active - resuming animations');
            // Resume operations
        }
    }, [isIdle]);

    return (
        <div style={{ opacity: isIdle ? 0.5 : 1 }}>
            <h1>Dashboard</h1>
            {/* Your content */}
        </div>
    );
}

## 🎯 Intended Use Cases

- **Kiosks and digital signage** - Prevent screen burn-in with automatic screensavers
- **Unattended applications** - Provide visual feedback when system is idle
- **TV and dashboard interfaces** - Keep displays visually engaging
- **Long-running displays** - Reduce power consumption and extend screen life
- **Public terminals** - Privacy protection by hiding sensitive information
- **Reception areas** - Display branded content when not in use

---

## 🔧 Troubleshooting

### Screensaver Not Appearing

**Issue:** Screensaver doesn't activate after timeout period.

**Solutions:**
1. Ensure CSS is imported:
   ```tsx
   import '@mohamedfariz/react-idle-screensaver/style.css';
  1. Check that active prop is not set to false:

    <ScreensaverManager active={true} ... />
  2. Verify timeout is set correctly (value is in milliseconds):

    <ScreensaverManager timeout={5000} ... /> {/* 5 seconds */}

Styles Not Applied

Issue: Built-in screensavers appear unstyled or broken.

Solutions:

  1. Import the CSS file at the top of your main entry file:

    // In main.tsx, App.tsx, or index.tsx
    import '@mohamedfariz/react-idle-screensaver/style.css';
  2. If using a bundler, ensure CSS files are processed. For Vite, this works automatically. For Webpack, ensure you have css-loader configured.

TypeScript Errors

Issue: TypeScript complains about missing types or prop types.

Solutions:

  1. Ensure you're importing from the correct path:

    import { ScreensaverManager, MatrixScreensaver } from '@mohamedfariz/react-idle-screensaver';
  2. Explicitly type your custom screensaver props:

    interface MyProps {
        message: string;
    }
    
    const MyScreensaver: React.FC<MyProps> = ({ message }) => {
        return <div>{message}</div>;
    };

Screensaver Stuck/Won't Dismiss

Issue: Screensaver activates but won't dismiss on user interaction.

Solutions:

  1. Check that you haven't set pointer-events: none on parent elements
  2. Ensure no modal or overlay is blocking interaction
  3. The screensaver automatically dismisses on:
    • Mouse movement
    • Mouse clicks
    • Keyboard input
    • Touch events

Performance Issues

Issue: Application feels sluggish or animations are choppy.

Solutions:

  1. For MatrixScreensaver, reduce character count or increase speed:

    <ScreensaverManager component={MatrixScreensaver} componentProps={{ fontSize: 16, speed: 50 }} />
  2. For StarfieldScreensaver, reduce star count:

    <ScreensaverManager component={StarfieldScreensaver} componentProps={{ starCount: 200 }} />
  3. For ImageSliderScreensaver, optimize images (compress, reduce resolution)

Images Not Loading in ImageSliderScreensaver

Issue: Images don't appear in the slider.

Solutions:

  1. Verify image URLs are accessible:

    componentProps={{
        images: [
            '/public/image1.jpg',  // ❌ Wrong for Vite
            '/image1.jpg',         // ✅ Correct for Vite (in public folder)
            'https://example.com/image.jpg'  // ✅ External URL
        ]
    }}
  2. Check browser console for CORS errors if using external images

  3. Ensure images are in the correct public directory for your bundler


⚠️ Notes & Limitations

Browser Only

This library is designed for browser environments only and will not work in Node.js or SSR (Server-Side Rendering) contexts during the render phase. The components safely check for window availability.

CSS Import Required

You must manually import the CSS file in your application:

import '@mohamedfariz/react-idle-screensaver/style.css';

The library does not automatically inject styles to give you control over CSS loading strategy.

Event Detection

The screensaver deactivates on:

  • mousemove
  • mousedown
  • keydown
  • touchstart
  • wheel (scroll)

These events are attached at the document level for maximum compatibility.

Z-Index Considerations

The default zIndex is 50. If your application uses higher z-index values (e.g., modals, dropdowns), you may need to adjust:

<ScreensaverManager zIndex={9999} ... />

Performance

  • Canvas-based screensavers (Matrix, Starfield) use requestAnimationFrame for smooth 60 FPS animations
  • All animations are optimized with will-change CSS properties where appropriate
  • For best performance on low-end devices, reduce complexity (fewer stars, larger fonts, etc.)

Memory Management

All components properly clean up:

  • Event listeners on unmount
  • setInterval timers
  • requestAnimationFrame calls
  • Canvas contexts

No memory leaks should occur during normal usage.

React Version

Requires React 18.0.0 or higher due to modern Context API usage.


📄 License

MIT License - See LICENSE file for details


🤝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.


📞 Support


🗺️ Roadmap

See ROADMAP.md for planned features and improvements.


Made with ❤️ for the React community