{"id":19821232,"url":"https://github.com/mattrothenberg/react-comparison-slider","last_synced_at":"2025-05-01T12:30:36.967Z","repository":{"id":48545442,"uuid":"387057760","full_name":"mattrothenberg/react-comparison-slider","owner":"mattrothenberg","description":"A keyboard accessible \"before \u0026 after\" component for React ⬅️➡️","archived":false,"fork":false,"pushed_at":"2021-10-14T22:13:38.000Z","size":544,"stargazers_count":33,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-03-01T00:01:54.633Z","etag":null,"topics":["accessibility","image","react","slider"],"latest_commit_sha":null,"homepage":"https://react-comparison-slider.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mattrothenberg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-18T00:02:11.000Z","updated_at":"2022-09-12T16:34:35.000Z","dependencies_parsed_at":"2022-08-28T20:40:46.728Z","dependency_job_id":null,"html_url":"https://github.com/mattrothenberg/react-comparison-slider","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrothenberg%2Freact-comparison-slider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrothenberg%2Freact-comparison-slider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrothenberg%2Freact-comparison-slider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrothenberg%2Freact-comparison-slider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mattrothenberg","download_url":"https://codeload.github.com/mattrothenberg/react-comparison-slider/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224255628,"owners_count":17281399,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","image","react","slider"],"created_at":"2024-11-12T10:26:19.638Z","updated_at":"2024-11-12T10:26:20.531Z","avatar_url":"https://github.com/mattrothenberg.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-comparison-slider\n\n[![npm version](https://badge.fury.io/js/react-comparison-slider.svg)](https://badge.fury.io/js/react-comparison-slider)\n\nhttps://react-comparison-slider.vercel.app/\n\nReact Comparison Slider is a fully customizable component for building bespoke, keyboard-accessible \"before \u0026 after\" sliders for the web. You bring the content and the visuals, and it'll handle the heavy lifting.\n\n![ezgif-3-0cbdbb348e5a](https://user-images.githubusercontent.com/5148596/126052111-635805d1-6583-45f2-a9c1-76a154eb39a0.gif)\n\n![ezgif-3-d3d224f0ae64](https://user-images.githubusercontent.com/5148596/126052875-9dd65770-b544-4618-af97-9a8c17fedde9.gif)\n\n## Installation\n\n```\nyarn add react-comparison-slider\n```\n\n## The \"Hello World\" example\n\nThe key ingredients to this component are:\n\n1. `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.\n2. `itemOne` of type `React.ReactNode` or function as a child `({value}) =\u003e React.ReactNode`\n3. `itemTwo` of type `React.ReactNode` or function as a child `({value}) =\u003e React.ReactNode`\n4. `defaultValue`, if you'd like to use the component in an uncontrolled fashion\n5. `orientation`, where you can pass either `vertical` or `horizontal`. Horizontal sliders are the default.\n\n```tsx\nimport { ComparisonSlider } from 'react-comparison-slider';\n\nexport const HelloWorldExample = () =\u003e {\n  return (\n    \u003cComparisonSlider\n      defaultValue={50}\n      itemOne={\u003cdiv className=\"bg-red-200\"\u003e\u003c/div\u003e}\n      itemTwo={\u003cdiv className=\"bg-blue-200\"\u003e\u003c/div\u003e}\n      aspectRatio={16 / 9}\n      orientation=\"horizontal\"\n    /\u003e\n  );\n};\n```\n\n## Customization\n\nReact 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\n\n```ts\n// For adding a \"bar\" above the handle (or to the left, if in \"vertical\" orientation)\nhandleBefore?: React.ReactNode;\n\n// For adding a \"bar\" below the handle (or to the right, if in \"vertical\" orientation)\nhandleAfter?: React.ReactNode;\n\n// 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.\nhandle?: (props: ComparisonSliderHandleProps) =\u003e React.ReactNode;\n```\n\n### `handleBefore` and `handleAfter`\n\nThese 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.\n\n```tsx\nimport { ComparisonSlider } from 'react-comparison-slider';\n\nexport const CustomHandleDecorations = () =\u003e {\n  return (\n    \u003cComparisonSlider\n      defaultValue={50}\n      itemOne={\u003cdiv className=\"bg-red\"\u003e\u003c/div\u003e}\n      itemTwo={\u003cdiv className=\"bg-blue\"\u003e\u003c/div\u003e}\n      aspectRatio={16 / 9}\n      handleBefore={\n        \u003cdiv className=\"bg-gradient-to-t from-white to-transparent w-2 h-full\"\u003e\u003c/div\u003e\n      }\n      handleAfter={\n        \u003cdiv className=\"bg-gradient-to-b from-white to-transparent w-2 h-full\"\u003e\u003c/div\u003e\n      }\n      handle={({ isFocused }) =\u003e {\n        return (\n          \u003cdiv\n            className={cc([\n              'rounded-full w-8 h-8 bg-white',\n              { ring: isFocused },\n            ])}\n          \u003e\u003c/div\u003e\n        );\n      }}\n    /\u003e\n  );\n};\n```\n\n\u003cimg width=\"543\" alt=\"Screen Shot 2021-07-17 at 9 10 08 PM\" src=\"https://user-images.githubusercontent.com/5148596/126052824-e6cc2745-d14e-4879-b223-90578317e85c.png\"\u003e\n\n### `handle`\n\nOf course, you can fully style the handle itself. You can make it bigger, add an icon, add fancy shadows...\n\n```tsx\nimport { ComparisonSlider } from 'react-comparison-slider';\n\nexport const CustomHandle = () =\u003e {\n  return (\n    \u003cComparisonSlider\n      defaultValue={50}\n      itemOne={\u003cdiv className=\"bg-red\"\u003e\u003c/div\u003e}\n      itemTwo={\u003cdiv className=\"bg-blue\"\u003e\u003c/div\u003e}\n      aspectRatio={16 / 9}\n      handle={({ isFocused }) =\u003e {\n        return (\n          \u003cdiv\n            className={cc([\n              'rounded-full w-10 h-10 bg-white text-graty-600 flex items-center justify-center',\n              { ring: isFocused },\n            ])}\n          \u003e\n            \u003cBiMoveHorizontal size={24} /\u003e\n          \u003c/div\u003e\n        );\n      }}\n    /\u003e\n  );\n};\n```\n\n\u003cimg width=\"409\" alt=\"Screen Shot 2021-07-17 at 8 45 08 PM\" src=\"https://user-images.githubusercontent.com/5148596/126052376-c48c9800-7297-4124-b6ad-f269ba2353a9.png\"\u003e\n\n## The API\n\nBelow 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.\n\n```ts\nvalue?: number;\nonValueChange?: (value: number) =\u003e void;\ndefaultValue?: number;\n\n// The \"first\" item in the viewport.\nitemOne:\n    | React.ReactNode\n    | (({ value }: { value: number }) =\u003e React.ReactNode);\n\n// The \"second\" item in the viewport.\nitemTwo:\n  | React.ReactNode\n  | (({ value }: { value: number }) =\u003e React.ReactNode);\n\n// The...aspect ratio.\naspectRatio: number | string;\n\n// Decoration that appears above (or to the left of, depending on orientation) the handle.\nhandleBefore?: React.ReactNode;\n\n// Decoration that appears below (or to the bottom of, depending on orientation) the handle.\nhandleAfter?: React.ReactNode;\n\n// Handle component\nhandle?: (props: ComparisonSliderHandleProps) =\u003e React.ReactNode;\n\n// Whether the slider is vertical or horizontal 😋\norientation?: 'vertical' | 'horizontal';\n\n// Whether only the handle itself should be interactive\nonlyHandleDraggable?: boolean;\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattrothenberg%2Freact-comparison-slider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmattrothenberg%2Freact-comparison-slider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattrothenberg%2Freact-comparison-slider/lists"}