React Comparison Slider is a fully customizable component for building bespoke, keyboard-accessible "before & after" sliders for the web.

Overview

react-comparison-slider

npm version

https://react-comparison-slider.vercel.app/

React Comparison Slider is a fully customizable component for building bespoke, keyboard-accessible "before & after" sliders for the web. You bring the content and the visuals, and it'll handle the heavy lifting.

ezgif-3-0cbdbb348e5a

ezgif-3-d3d224f0ae64

Installation

yarn add react-comparison-slider

The "Hello World" example

The key ingredients to this component are:

  1. aspectRatio, expressed either numerically as a fraction (e.g., 16/9), or as a string (e.g., "16x9" or "16:9"). Providing an aspect ratio ensures that the before and after "images" (or HTML elements, whatever you decide to provide) line up with one another.
  2. itemOne of type React.ReactNode or function as a child ({value}) => React.ReactNode
  3. itemTwo of type React.ReactNode or function as a child ({value}) => React.ReactNode
  4. defaultValue, if you'd like to use the component in an uncontrolled fashion
  5. orientation, where you can pass either vertical or horizontal. Horizontal sliders are the default.
} itemTwo={
} aspectRatio={16 / 9} orientation="horizontal" /> ); }; ">
import { ComparisonSlider } from 'react-comparison-slider';

export const HelloWorldExample = () => {
  return (
    <ComparisonSlider
      defaultValue={50}
      itemOne={<div className="bg-red-200"></div>}
      itemTwo={<div className="bg-blue-200"></div>}
      aspectRatio={16 / 9}
      orientation="horizontal"
    />
  );
};

Customization

React Comparison Slider does ship with some very lightweight styling, but encourages you to bring your own styling (BYOS) ™️ . Customization is handled via a set of render props that expose all of the underlying components for your needs. There is a total of 4 of these visual elements

React.ReactNode; ">
// For adding a "bar" above the handle (or to the left, if in "vertical" orientation)
handleBefore?: React.ReactNode;

// For adding a "bar" below the handle (or to the right, if in "vertical" orientation)
handleAfter?: React.ReactNode;

// For customizing the slider handle itself. Note that `ComparisonSliderHandleProps` exposes an `isFocused` prop that you can use to style the handle when it has keyboard focus.
handle?: (props: ComparisonSliderHandleProps) => React.ReactNode;

handleBefore and handleAfter

These props allows you to add visual indicators such as a scrubbing bar to the slider handle itself. In the example below, we add a thin white bar above and below the handle as shown in the screenshot below.

} itemTwo={
} aspectRatio={16 / 9} handleBefore={
} handleAfter={
} handle={({ isFocused }) => { return (
); }} /> ); }; ">
import { ComparisonSlider } from 'react-comparison-slider';

export const CustomHandleDecorations = () => {
  return (
    <ComparisonSlider
      defaultValue={50}
      itemOne={<div className="bg-red"></div>}
      itemTwo={<div className="bg-blue"></div>}
      aspectRatio={16 / 9}
      handleBefore={
        <div className="bg-gradient-to-t from-white to-transparent w-2 h-full"></div>
      }
      handleAfter={
        <div className="bg-gradient-to-b from-white to-transparent w-2 h-full"></div>
      }
      handle={({ isFocused }) => {
        return (
          <div
            className={cc([
              'rounded-full w-8 h-8 bg-white',
              { ring: isFocused },
            ])}
          ></div>
        );
      }}
    />
  );
};

Screen Shot 2021-07-17 at 9 10 08 PM

handle

Of course, you can fully style the handle itself. You can make it bigger, add an icon, add fancy shadows...

} itemTwo={
} aspectRatio={16 / 9} handle={({ isFocused }) => { return (
); }} /> ); }; ">
import { ComparisonSlider } from 'react-comparison-slider';

export const CustomHandle = () => {
  return (
    <ComparisonSlider
      defaultValue={50}
      itemOne={<div className="bg-red"></div>}
      itemTwo={<div className="bg-blue"></div>}
      aspectRatio={16 / 9}
      handle={({ isFocused }) => {
        return (
          <div
            className={cc([
              'rounded-full w-10 h-10 bg-white text-graty-600 flex items-center justify-center',
              { ring: isFocused },
            ])}
          >
            <BiMoveHorizontal size={24} />
          </div>
        );
      }}
    />
  );
};

Screen Shot 2021-07-17 at 8 45 08 PM

The API

Below is a high-level interface definition for the component. Note that because this component can be used in both a controlled and uncontrolled fashion, the first three props – value, defaultValue, and onChange are actually totally dynamic. That is to say, if you provide a defaultValue you won't be asked for value or onChange. In fact, you'll get a compilation error if you try to use them. Conversely, if you provide value and onChange, you won't be asked for defaultValue and will error out accordingly if you provide it.

React.ReactNode); // The "second" item in the viewport. itemTwo: | React.ReactNode | (({ value }: { value: number }) => React.ReactNode); // The...aspect ratio. aspectRatio: number | string; // Decoration that appears above (or to the left of, depending on orientation) the handle. handleBefore?: React.ReactNode; // Decoration that appears below (or to the bottom of, depending on orientation) the handle. handleAfter?: React.ReactNode; // Handle component handle?: (props: ComparisonSliderHandleProps) => React.ReactNode; // Whether the slider is vertical or horizontal 😋 orientation?: 'vertical' | 'horizontal'; // Whether only the handle itself should be interactive onlyHandleDraggable?: boolean; ">
value?: number;
onValueChange?: (value: number) => void;
defaultValue?: number;

// The "first" item in the viewport.
itemOne:
    | React.ReactNode
    | (({ value }: { value: number }) => React.ReactNode);

// The "second" item in the viewport.
itemTwo:
  | React.ReactNode
  | (({ value }: { value: number }) => React.ReactNode);

// The...aspect ratio.
aspectRatio: number | string;

// Decoration that appears above (or to the left of, depending on orientation) the handle.
handleBefore?: React.ReactNode;

// Decoration that appears below (or to the bottom of, depending on orientation) the handle.
handleAfter?: React.ReactNode;

// Handle component
handle?: (props: ComparisonSliderHandleProps) => React.ReactNode;

// Whether the slider is vertical or horizontal 😋
orientation?: 'vertical' | 'horizontal';

// Whether only the handle itself should be interactive
onlyHandleDraggable?: boolean;
Issues
  • Consider reseting the handle to the

    Consider reseting the handle to the "defaultValue"/"initialValue" on double click

    Hey. Thank you for an awesome library! I've integrated it into my project and it works like a charm.

    Following an established pattern, I keep wanting for the handle's position to reset to the defaultValue when I double click on it. Have you considered this behavior?

    enhancement 
    opened by kettanaito 6
  • feat: expose orientation prop

    feat: expose orientation prop

    TODO

    • [x] Update docs
    opened by mattrothenberg 2
  • feat: use react-range

    feat: use react-range

    Resolves https://github.com/mattrothenberg/react-comparison-slider/issues/2 but introduces several breaking changes via a refactor.

    Changes

    • beforeComponent ➡️ itemOne
    • afterComponent ➡️ itemTwo
    • 💥 handleDecorationComponent
    • 💥 beforeDecorationComponent
    • 💥 afterDecorationComponent
    • handle
    • handleAfter
    • handleBefore
    • onlyHandleDraggable
    opened by mattrothenberg 2
Releases(v1.0.0)
  • v1.0.0(Jul 20, 2021)

    Resolves https://github.com/mattrothenberg/react-comparison-slider/issues/2 but introduces several breaking changes via a refactor.

    Changes

    • beforeComponent ➡️ itemOne
    • afterComponent ➡️ itemTwo
    • 💥 handleDecorationComponent
    • 💥 beforeDecorationComponent
    • 💥 afterDecorationComponent
    • handle
    • handleAfter
    • handleBefore
    • onlyHandleDraggable

    Usage

    export const DOMElements = () => {
      return (
        <div className="max-w-lg border border-black">
          <ComparisonSlider
            defaultValue={50}
            handleBefore={<div className="bg-white w-1 h-full"></div>}
            handleAfter={<div className="bg-white w-1 h-full"></div>}
            handle={({ isFocused }) => {
              return (
                <div
                  className={cc([
                    'rounded-full w-8 h-8 bg-white',
                    { ring: isFocused },
                  ])}
                ></div>
              );
            }}
            itemOne={
              <div className="bg-red-200 flex items-center justify-center text-2xl">
                <div className="absolute top-4 left-4">👍</div>
                Before
              </div>
            }
            itemTwo={
              <div className="bg-blue-200 flex items-center justify-center text-2xl">
                <div className="absolute top-4 right-4">👎</div>
                After
              </div>
            }
            aspectRatio={16 / 9}
          />
        </div>
      );
    };
    
    Source code(tar.gz)
    Source code(zip)
React component to compare two images with a slider

React Compare Image Simple React component to compare two images using slider. NOTE: Vue.js Version is also available! Demo & Sample codes Demo & Samp

Shota Tamura 209 Sep 21, 2021
React carousel image gallery component with thumbnail support 🖼

React Carousel Image Gallery Live Demo (try it on mobile for swipe support) linxtion.com/demo/react-image-gallery React image gallery is a React compo

Xiao Lin 2.9k Sep 20, 2021
lightGallery - A customizable, modular, responsive, lightbox gallery plugin

lightGallery - A customizable, modular, responsive, lightbox gallery plugin

Sachin N 4.7k Sep 15, 2021
A component to reveal images on user interaction, written with TypeScript + React.

A component to reveal images on user interaction, written with TypeScript + React.

Nik 67 Aug 20, 2021
React lightbox component

React Image Lightbox A flexible lightbox component for displaying images in a React project. DEMO Features Keyboard shortcuts (with rate limiting) Ima

Frontend Collective 1.1k Sep 12, 2021
React component to display imgix images

react-imgix provides custom components for integrating imgix into React sites and generating images server-side. Overview / Resources Installation Usa

imgix 296 Sep 15, 2021
React Photo Gallery

React Photo Gallery Responsive, accessible, composable, and customizable image gallery component Maintains the original aspect ratio of your photos Cr

Sandra Gonzales 1.6k Sep 10, 2021
🌄 A mobile-friendly, highly customizable, carousel component for displaying media in ReactJS

React Images ⚠️ Warning! Don't use this in a new project. This package hasn't been properly maintained in a long time and there are much better option

Joss Mackison 2.3k Sep 16, 2021
React for Upload Image Gallery. Drag & Drop, Sortable, Customize.

React Upload Gallery A simple library that lets you create an image gallery, change the order of images, select the highlighted image, and customize i

Minan 40 Aug 26, 2021
Webcam component for React.

Webcam component for React.

Moz Morris 1.1k Sep 18, 2021
React emoji picker powered by Twemoji. Maintained by the Giggl team

React emoji picker powered by Twemoji. Maintained by the Giggl team

Giggl 19 Sep 17, 2021
A minimal lightbox package for react ⚛

✨ React LightBox Pack A Lightweight NPM LightBox Package built with simplicity in mind. Since it's built from Scratch it doesn't need any additional d

Mohan Kumar 4 Aug 26, 2021
:eyes: A React component that adds pan and zoom features to SVG

react-svg-pan-zoom react-svg-pan-zoom is a React component that adds pan and zoom features to the SVG images. It helps to display big SVG images in a

Christian 605 Sep 7, 2021
react library for generating avatar

react library for generating avatar

Chill Lab 519 Sep 15, 2021
Render images as interactive particles

react-particle-image Render images as interactive particles Install npm install --save react-particle-image Links Demo (source) Docs Simple Usage code

Austin Malerba 333 Sep 16, 2021
🌄 Image editor using native modules for iOS and Android. Inherit from 2 available libraries, Brightroom (iOS) and PhotoEditor (Android)

?? Image editor using native modules for iOS and Android. Inherit from 2 available libraries, Brightroom (iOS) and PhotoEditor (Android)

Baron Ha. 84 Sep 22, 2021
An app for uploading images developed in the eighth React Track challenge in Ignite

Front end application ?? An app for uploading images developed in the eighth React Track challenge in Ignite delivered by Rocketseat ?? Technologies u

Matheus da Cruz 5 Jul 29, 2021
A React component for viewing large images up close 🔍

react-intense This component is a port of Intense Image Viewer for use with React. Demo. Usage Simply replace your <img> element with a <ReactIntense>

Bryce Dorn 158 Jun 21, 2021
This React Capstone project is a browsable catalogue of pets using React and Redux that enables users to filter and access details of a specific item.

This React Capstone project is a browsable catalogue of pets using React and Redux that enables users to filter and access details of a specific item.

David Bassey 7 Sep 16, 2021