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

@dylanwells/react-3d-slideshow

v0.2.1

Published

A React slideshow component with stunning 3D transitions powered by Three.js

Readme

React 3D Slideshow

Warning: This library is a work in progress and has not been thoroughly tested. Use at your own risk in production environments.

A React slideshow component with 3D transitions powered by Three.js and @react-three/fiber.

Live Demo

Installation

npm install @dylanwells/react-3d-slideshow

Quick Start

import { Slideshow } from '@dylanwells/react-3d-slideshow'

const slides = [
  { id: 1, image: '/image1.jpg' },
  { id: 2, image: '/image2.jpg' },
  { id: 3, image: '/image3.jpg' },
]

function App() {
  return (
    <Slideshow
      slides={slides}
      style="glitch"
      aspectRatio={16 / 9}
      autoPlay
      loop
    />
  )
}

Transition Styles

  • glitch - Chromatic aberration, scanlines, and film grain effects
  • cascade - 3D cube grid with diagonal wave animation
  • cube - Simple 3D cube rotation between slides

Props

Core Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | slides | SlideData[] | required | Array of slide objects with id and image properties | | style | 'glitch' \| 'cascade' \| 'cube' | 'cascade' | Transition style to use | | transitionDuration | number | 800 | Duration of transitions in milliseconds | | aspectRatio | number | 1.5 (3:2) | Aspect ratio for the slideshow display area | | fullscreen | boolean | false | Fill the entire viewport (glitch and cascade only) |

Autoplay Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | autoPlay | boolean | false | Automatically advance slides | | autoPlayInterval | number | 5000 | Time between auto-advances in milliseconds | | pauseOnHover | boolean | true | Pause autoplay when hovering over the slideshow | | loop | boolean | true | Loop back to first slide after reaching the end |

Layout Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | width | string \| number | '100%' | Width of the slideshow container | | height | string \| number | 400 | Height of the slideshow container | | initialSlide | number | 0 | Index of the initial slide to display | | className | string | - | CSS class for the container element |

UI Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | showControls | boolean | true | Show prev/next navigation buttons | | showIndicators | boolean | true | Show slide indicator dots | | enableSwipe | boolean | true | Enable touch swipe and mouse drag navigation | | enableKeyboard | boolean | true | Enable arrow key navigation |

Custom UI Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | loadingSpinner | ReactElement \| null | default spinner | Custom loading spinner. Set to null to hide | | prevButton | ReactElement \| null | default button | Custom previous button. Set to null to hide | | nextButton | ReactElement \| null | default button | Custom next button. Set to null to hide | | renderIndicator | (index: number, isActive: boolean) => ReactElement | - | Custom indicator renderer | | focusRingStyles | FocusRingStyles | - | Customize keyboard focus ring appearance |

Glitch Effect Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | glitchAberration | number | 0.5 | Chromatic aberration intensity (0-1) | | glitchScanlines | number | 0.5 | Scanlines effect intensity (0-1) | | glitchGrain | number | 0.5 | Film grain effect intensity (0-1) |

Cascade Effect Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | cascadeMinTiles | number | 10 | Minimum number of tiles in the shorter dimension |

Accessibility Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | ariaLabel | string | 'Image slideshow' | Accessible label for the slideshow region | | getSlideAriaLabel | (index: number, total: number) => string | - | Custom function to generate slide announcements | | focusRingStyles | FocusRingStyles | - | Customize focus ring color, width, and offset |

WebGL Fallback Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | fallback | ReactElement \| null | crossfade slideshow | Custom fallback when WebGL is unavailable. Set to null to show nothing | | onWebGLUnsupported | () => void | - | Callback fired when WebGL is not supported |

Callbacks

| Prop | Type | Description | |------|------|-------------| | onSlideChange | (index: number) => void | Called when the active slide changes | | onWebGLUnsupported | () => void | Called when WebGL is not available |

Customization

Custom Navigation Buttons

<Slideshow
  slides={slides}
  prevButton={<MyCustomPrevButton />}
  nextButton={<MyCustomNextButton />}
/>

Set to null to hide a button entirely:

<Slideshow
  slides={slides}
  prevButton={null}  // Hide prev button
  nextButton={<MyNextButton />}
/>

Custom Indicators

<Slideshow
  slides={slides}
  renderIndicator={(index, isActive) => (
    <div className={isActive ? 'dot active' : 'dot'} />
  )}
/>

Custom Loading Spinner

import { LoadingSpinner } from '@dylanwells/react-3d-slideshow'

// Use built-in spinner with custom props
<Slideshow
  slides={slides}
  loadingSpinner={<LoadingSpinner size={64} color="#ff0000" />}
/>

// Or use your own component
<Slideshow
  slides={slides}
  loadingSpinner={<MyCustomSpinner />}
/>

// Or hide it entirely
<Slideshow
  slides={slides}
  loadingSpinner={null}
/>

Focus Ring Styles

Customize the keyboard focus ring for accessibility:

<Slideshow
  slides={slides}
  focusRingStyles={{
    color: '#00ff00',  // Focus ring color (default: '#fff')
    width: 3,          // Ring width in pixels (default: 2)
    offset: 4,         // Ring offset in pixels (default: 2)
  }}
/>

WebGL Fallback

When WebGL is not supported, the slideshow automatically falls back to a simple crossfade effect. You can customize this behavior:

// Use default crossfade fallback (default behavior)
<Slideshow slides={slides} />

// Custom fallback component
<Slideshow
  slides={slides}
  fallback={<MyCustomFallbackSlideshow slides={slides} />}
  onWebGLUnsupported={() => console.log('WebGL not available')}
/>

// Show nothing when WebGL unavailable
<Slideshow
  slides={slides}
  fallback={null}
/>

You can also check WebGL support programmatically:

import { isWebGLSupported } from '@dylanwells/react-3d-slideshow'

if (isWebGLSupported()) {
  // WebGL is available
}

Ref API

The Slideshow component exposes methods via a ref for programmatic control:

import { useRef } from 'react'
import { Slideshow, SlideshowHandle } from '@dylanwells/react-3d-slideshow'

function App() {
  const slideshowRef = useRef<SlideshowHandle>(null)

  return (
    <>
      <Slideshow ref={slideshowRef} slides={slides} />
      <button onClick={() => slideshowRef.current?.next()}>Next</button>
      <button onClick={() => slideshowRef.current?.prev()}>Previous</button>
      <button onClick={() => slideshowRef.current?.goTo(2)}>Go to slide 3</button>
    </>
  )
}

Methods

| Method | Description | |--------|-------------| | next() | Advance to the next slide | | prev() | Go to the previous slide | | goTo(index: number) | Jump to a specific slide by index | | getCurrentIndex() | Get the current slide index |

CSS Class Names

The component uses BEM-style class names for styling customization:

| Class | Description | |-------|-------------| | .r3dss | Root container | | .r3dss--cascade | Root with cascade style | | .r3dss--cube | Root with cube style | | .r3dss--glitch | Root with glitch style | | .r3dss--empty | Root when no slides provided | | .r3dss__canvas | Three.js canvas element | | .r3dss__controls | Navigation controls container | | .r3dss__control | Navigation button | | .r3dss__control--prev | Previous button | | .r3dss__control--next | Next button | | .r3dss__control--disabled | Disabled button state | | .r3dss__control--hovered | Hovered button state | | .r3dss__control--custom | Custom button element | | .r3dss__indicators | Indicator dots container | | .r3dss__indicator | Individual indicator dot | | .r3dss__indicator--active | Active indicator | | .r3dss__indicator--custom | Custom indicator element | | .r3dss__loader | Loading spinner container | | .r3dss__spinner | Default loading spinner | | .r3dss__live-region | Screen reader announcements | | .r3dss__empty-message | Empty state message | | .r3dss__fallback | WebGL fallback container | | .r3dss__fallback-slide | Fallback slide element |

Slide Data

Each slide object should have the following structure:

interface SlideData {
  id: string | number      // Unique identifier
  image?: string           // Image URL
  content?: ReactNode      // Custom React content (not fully supported)
  backgroundColor?: string // Fallback background color
}

Types

All TypeScript types are exported for convenience:

import type {
  SlideshowProps,
  SlideshowHandle,
  SlideData,
  TransitionStyle,
  ControlsProps,
  IndicatorsProps,
  FocusRingStyles,
  LoadingSpinnerProps,
  FallbackSlideshowProps,
} from '@dylanwells/react-3d-slideshow'

License

MIT