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 🙏

© 2024 – Pkg Stats / Ryan Hefner

yet-another-react-lightbox-lite

v1.5.0

Published

Lightweight React lightbox component

Downloads

642

Readme

Yet Another React Lightbox Lite

Lightweight React lightbox component. This is a trimmed-down version of the yet-another-react-lightbox that provides essential lightbox features and slick UX with just 4.6KB bundle size.

Overview

NPM Version Bundle Size License MIT

  • Built for React: works with React 18+
  • UX: supports keyboard, mouse, touchpad and touchscreen navigation
  • Zoom: zoom is supported out of the box
  • Performance: preloads a fixed number of images without compromising performance or UX
  • Responsive: responsive images with automatic resolution switching are supported out of the box
  • Customization: customize any UI element or add your own custom slides
  • No bloat: supports only essential lightbox features
  • TypeScript: type definitions come built-in in the package

Documentation

https://github.com/igordanchenko/yet-another-react-lightbox-lite

Examples

Changelog

https://github.com/igordanchenko/yet-another-react-lightbox-lite/releases

Requirements

  • React 18+
  • Node 18+
  • modern ESM-compatible bundler

Installation

npm install yet-another-react-lightbox-lite

Minimal Setup Example

import { useState } from "react";
import Lightbox from "yet-another-react-lightbox-lite";
import "yet-another-react-lightbox-lite/styles.css";

export default function App() {
  const [index, setIndex] = useState<number>();

  return (
    <>
      <button type="button" onClick={() => setIndex(0)}>
        Open Lightbox
      </button>

      <Lightbox
        slides={[
          { src: "/image1.jpg" },
          { src: "/image2.jpg" },
          { src: "/image3.jpg" },
        ]}
        index={index}
        setIndex={setIndex}
      />
    </>
  );
}

Responsive Images

To utilize responsive images with automatic resolution switching, provide srcset images in the slide srcSet array.

<Lightbox
  slides={[
    {
      src: "/image1x3840.jpg",
      srcSet: [
        { src: "/image1x320.jpg", width: 320, height: 213 },
        { src: "/image1x640.jpg", width: 640, height: 427 },
        { src: "/image1x1200.jpg", width: 1200, height: 800 },
        { src: "/image1x2048.jpg", width: 2048, height: 1365 },
        { src: "/image1x3840.jpg", width: 3840, height: 2560 },
      ],
    },
    // ...
  ]}
  // ...
/>

Next.js Image

If your project is based on Next.js, you may want to take advantage of the next/image component. The next/image component provides a more efficient way to handle images in your Next.js project. You can replace the standard <img> element with next/image with the following render.slide render function.

<Lightbox
  render={{
    slide: ({ slide, rect }) => {
      const width =
        slide.width && slide.height
          ? Math.round(
              Math.min(rect.width, (rect.height / slide.height) * slide.width),
            )
          : rect.width;

      const height =
        slide.width && slide.height
          ? Math.round(
              Math.min(rect.height, (rect.width / slide.width) * slide.height),
            )
          : rect.height;

      return (
        <Image
          src={slide.src}
          alt={slide.alt || ""}
          width={width}
          height={height}
          loading="eager"
          draggable={false}
          blurDataURL={(slide as any).blurDataURL}
          style={{
            minWidth: 0,
            minHeight: 0,
            maxWidth: "100%",
            maxHeight: "100%",
            objectFit: "contain",
          }}
        />
      );
    },
  }}
  // ...
/>

API

Yet Another React Lightbox Lite comes with CSS stylesheet that needs to be imported in your app.

import "yet-another-react-lightbox-lite/styles.css";

The lightbox component accepts the following props.

slides

Type: Slide[]

An array of slides to display in the lightbox. This prop is required. By default, the lightbox supports only image slides. You can add support for custom slides through a custom render function (see example below).

Image slide props:

  • src - image source (required)
  • alt - image alt attribute

index

Type: number | undefined

Current slide index. This prop is required.

setIndex

Type: (index: number | undefined) => void

A callback to update current slide index state. This prop is required.

labels

Type: { [key: string]: string }

Custom UI labels / translations.

<Lightbox
  labels={{
    Previous: t("Previous"),
    Next: t("Next"),
    Close: t("Close"),
  }}
  // ...
/>

toolbar

Type: object

Toolbar settings.

  • buttons - custom toolbar buttons (type: ReactNode[])
  • fixed - if true, the toolbar is positioned statically above the carousel

Usage example:

<Lightbox
  toolbar={{
    fixed: true,
    buttons: [
      <button
        type="button"
        className="yarll__button"
        onClick={() => {
          // ...
        }}
      >
        <ButtonIcon />
      </button>,
    ],
  }}
  // ...
/>

carousel

Type: object

Carousel settings.

  • preload - the lightbox preloads (2 * preload + 1) slides (default: 2)
  • imageProps - custom image slide attributes

Usage example:

<Lightbox
  carousel={{
    preload: 5,
    imageProps: { crossOrigin: "anonymous" },
  }}
  // ...
/>

controller

Type: object

Controller settings.

  • closeOnPullUp - if true, close the lightbox on pull-up gesture (default: true)
  • closeOnPullDown - if true, close the lightbox on pull-down gesture (default: true)
  • closeOnBackdropClick - if true, close the lightbox when the backdrop is clicked (default: true)

Usage example:

<Lightbox
  controller={{
    closeOnPullUp: false,
    closeOnPullDown: false,
    closeOnBackdropClick: false,
  }}
  // ...
/>

render

Type: object

An object providing custom render functions.

<Lightbox
  render={{
    slide: ({ slide, rect, zoom, current }) => (
      <CustomSlide {...{ slide, rect, zoom, current }} />
    ),
    slideHeader: ({ slide, rect, zoom, current }) => (
      <SlideHeader {...{ slide, rect, zoom, current }} />
    ),
    slideFooter: ({ slide, rect, zoom, current }) => (
      <SlideFooter {...{ slide, rect, zoom, current }} />
    ),
    controls: () => <CustomControls />,
    iconPrev: () => <IconPrev />,
    iconNext: () => <IconNext />,
    iconClose: () => <IconClose />,
  }}
  // ...
/>

slide: ({ slide, rect, zoom, current }) => ReactNode

Render custom slide type, or override the default image slide implementation.

Parameters:

  • slide - slide object (type: Slide)
  • rect - slide rect size (type: Rect)
  • zoom - current zoom level (type: number)
  • current - if true, the slide is the current slide in the viewport (type: boolean)

slideHeader: ({ slide, rect, zoom, current }) => ReactNode

Render custom elements above each slide.

slideFooter: ({ slide, rect, zoom, current }) => ReactNode

Render custom elements below or over each slide. By default, the content is rendered right under the slide. Alternatively, you can use position: "absolute" to position the extra elements relative to the slide.

For example, you can use the slideFooter render function to add slides descriptions.

<Lightbox
  render={{
    slideFooter: ({ slide }) => (
      <div style={{ marginBlockStart: 16 }}>{slide.description}</div>
    ),
  }}
  // ...
/>

controls: () => ReactNode

Render custom controls or additional elements in the lightbox (use absolute positioning).

For example, you can use the render.controls render function to implement slides counter.

<Lightbox
  render={{
    controls: () =>
      index !== undefined && (
        <div style={{ position: "absolute", top: 16, left: 16 }}>
          {index + 1} of {slides.length}
        </div>
      ),
  }}
  // ...
/>

iconPrev: () => ReactNode

Render custom Previous icon.

iconNext: () => ReactNode

Render custom Next icon.

iconClose: () => ReactNode

Render custom Close icon.

styles

Type: { [key in Slot]?: SlotCSSProperties }

Customization slots styles allow you to specify custom CSS styles or override --yarll__* CSS variables by passing your custom styles through to the corresponding lightbox elements.

Supported customization slots:

  • portal - lightbox portal (root)
  • carousel - lightbox carousel
  • slide - lightbox slide
  • image - lightbox slide image
  • toolbar - lightbox toolbar
  • button - lightbox button
  • icon - lightbox icon

Usage example:

<Lightbox
  styles={{
    portal: { "--yarll__backdrop_color": "rgba(0, 0, 0, 0.6)" },
  }}
  // ...
/>

className

Type: string

CSS class of the lightbox root element. You can use this class name to provide module-scoped style overrides.

Custom Slide Attributes

You can add custom slide attributes with the following module augmentation.

declare module "yet-another-react-lightbox-lite" {
  interface GenericSlide {
    description?: string;
  }
}

Custom Slides

You can add custom slide types through module augmentation and render them with the render.slide render function.

Here is an example demonstrating video slides implementation.

declare module "yet-another-react-lightbox-lite" {
  interface SlideVideo extends GenericSlide {
    type: "video";
    src: string;
    poster: string;
    width: number;
    height: number;
  }

  interface SlideTypes {
    video: SlideVideo;
  }
}

// ...

<Lightbox
  slides={[
    {
      type: "video",
      src: "/media/video.mp4",
      poster: "/media/poster.jpg",
      width: 1280,
      height: 720,
    },
  ]}
  render={{
    slide: ({ slide }) =>
      slide.type === "video" ? (
        <video
          controls
          playsInline
          poster={slide.poster}
          width={slide.width}
          height={slide.height}
          style={{ maxWidth: "100%", maxHeight: "100%" }}
        >
          <source type="video/mp4" src={slide.src} />
        </video>
      ) : undefined,
  }}
  // ...
/>;

Code Splitting (Suspense)

// Lightbox.tsx
import LightboxComponent, {
  LightboxProps,
} from "yet-another-react-lightbox-lite";
import "yet-another-react-lightbox-lite/styles.css";

export default function Lightbox(props: LightboxProps) {
  return <LightboxComponent {...props} />;
}
// App.tsx
import { lazy, Suspense, useState } from "react";
import slides from "./slides";

const Lightbox = lazy(() => import("./Lightbox"));

export default function App() {
  const [index, setIndex] = useState<number>();

  return (
    <>
      <button type="button" onClick={() => setIndex(0)}>
        Open Lightbox
      </button>

      {index !== undefined && (
        <Suspense>
          <Lightbox slides={slides} index={index} setIndex={setIndex} />
        </Suspense>
      )}
    </>
  );
}

Body Scroll Lock

By default, the lightbox hides the browser window scrollbar and prevents document <body> from scrolling underneath the lightbox by assigning the height: 100%; overflow: hidden; styles to the document <body> element.

If this behavior causes undesired side effects in your case, and you prefer not to use this feature, you can turn it off by assigning the yarll__no_scroll_lock class to the lightbox.

<Lightbox
  className="yarll__no_scroll_lock"
  // ...
/>

However, if you keep the body scroll lock feature on, you may notice a visual layout shift of some fixed-positioned page elements when the lightbox opens. To address this, you can assign the yarll__fixed CSS class to your fixed-positioned elements to keep them in place. Please note that the fixed-positioned element container should not have its own border or padding styles. If that's the case, you can always add an extra wrapper that just defines the fixed position without visual styles.

Hooks (experimental)

The library exports the following experimental hooks that you may find helpful in customizing lightbox functionality. All experimental hooks are currently exported with the unstable_ prefix.

useZoom

You can use the useZoom hook to build your custom zoom controls.

import { unstable_useZoom as useZoom } from "yet-another-react-lightbox-lite";

The hook provides an object with the following props:

  • rect - slide rect
  • zoom - current zoom level (numeric value between 1 and 8)
  • maxZoom - maximum zoom level (1 if zoom is not supported on the current slide)
  • offsetX - horizontal slide position offset
  • offsetY - vertical slide position offset
  • changeZoom - change zoom level
  • changeOffsets - change position offsets

License

MIT © 2024 Igor Danchenko