Library / SDK
p-m-p/slider avatar
p-m-p/slider

BoxSlider: a zero dependency slider that ships three ways

A modern, light weight content slider

891 stars230 forksTypeScriptMIT

At a glance

What is it?
BoxSlider is a small TypeScript content slider with no runtime dependencies, published as three packages: a core library with factory functions, React 19 component wrappers, and framework-agnostic web components. The same four transition effects are exposed through all three, which is the interesting part of the design, and the project also ships a bundle size budget that it enforces in CI.
Who is it for?
BoxSlider fits a team that wants a slider without a dependency tree, that is already on React 19 and would rather not write a carousel from scratch, and that cares about bundle size enough to want a size-limit budget in CI.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Zero dependencies is the headline, and the size budget enforces it

BoxSlider is described as a small library with zero dependencies that provides a light-weight, responsive content slider with multiple slide transition effects for modern browsers.

The zero dependency claim is worth examining rather than taking on faith, because a slider is exactly the kind of component that usually drags in a framework, an animation library and a utility CSS package. The core package is described as the core JavaScript library with zero runtime dependencies, providing factory functions and a BoxSlider class for attaching transition effects to any container element.

The repository structure backs the claim. The root package.json has a dependencies block that is not present at all, only devDependencies. There is a size-limit configuration file, .size-limit.json, and a size script wired to size-limit, plus a size:check script. The size-limit tool is a way of asserting a byte budget on a built artefact, and having one checked in, wired to a script, means the claim is testable rather than aspirational.

The build itself is Turborepo over a pnpm workspace, and the root manifest pins pnpm at 12.9.1. The packages directory holds the three published packages, and there is an examples directory, since the dev script runs the examples filter.

The publishing pipeline is also in the manifest, and it is a modern one. The release script is changeset publish, with a .changeset directory and the changesets CLI in the dev dependencies, so version bumps and changelogs are generated from commit-shaped change entries. There is a commitlint configuration and a conventional changelog tool, and a Chromatic configuration alongside a chromatic script that runs with --exit-zero-on-changes, which is the setting that keeps a visual regression service from failing the build on an unrelated diff. And renovate.json is in the tree, so dependency updates are automated.

One set of effects, three ways to reach them

The package list is the clearest description of the design, and it is a deliberate one.

The core package, @boxslider/slider, is the JavaScript library with zero runtime dependencies. It works standalone or via React and web components.

The React package, @boxslider/react, provides React 19 component wrappers with typed props and event handlers for all slider effects, plus a SliderControls component that adds navigation controls automatically. The available components are CarouselSlider, CubeSlider, FadeSlider, TileSlider and SliderControls.

The web components package, @boxslider/components, provides framework-agnostic web components that work in any modern browser or JavaScript framework without additional configuration. The available elements are bs-carousel, bs-cube, bs-fade, bs-tile and bs-slider-controls.

The effect list is identical across all three: carousel, cube, fade and tile. In the core package they are factory functions named createCarouselSlider, createCubeSlider, createFadeSlider and createTileSlider. In the React package they are components. In the components package they are custom elements.

That consistency is the useful part. The behaviour lives in one place, and the three packages are adapters over it. A team that starts on the core package and later moves to React does not change the slider behaviour, and a team that has to support both a React app and a server rendered page can use the web components in the second without maintaining two implementations.

The four effects are also a deliberate narrowing. There is no fade of individual elements, no partial slide, no lazy loading behaviour described, no autoplay configuration described in the README. This is a transition-effect library with navigation added, not a full featured carousel.

Three ways to install, and one that needs no build step at all

Each package is installed from NPM, and each also has a CDN route that requires no build step, which is the most interesting installation detail here.

The core package installs like this:

sh
npm install --save @boxslider/slider

And the CDN usage is a module script that imports the factory function and calls it against a selector:

html
<script type="module">
  import { createCarouselSlider } from 'https://cdn.jsdelivr.net/npm/@boxslider/slider/+esm'

  createCarouselSlider('#slider')
</script>

The React package installs as @boxslider/react and is used as a component, with the controls wrapper handling the navigation:

tsx
import { SliderControls, CarouselSlider } from '@boxslider/react'

function MySlider() {
  return (
    <SliderControls>
      <CarouselSlider>
        <div>Slide 1</div>
        <div>Slide 2</div>
        <div>Slide 3</div>
      </CarouselSlider>
    </SliderControls>
  )
}

The web components package installs as @boxslider/components, and its CDN form is a plain script tag followed by the custom elements in markup:

html
<script type="module" src="https://cdn.jsdelivr.net/npm/@boxslider/components/+esm"></script>

<bs-slider-controls>
  <bs-carousel>
    <div>Slide 1</div>
    <div>Slide 2</div>
    <div>Slide 3</div>
  </bs-carousel>
</bs-slider-controls>

The fact that the same library is usable from a script tag, from a React component and from a custom element is the practical argument for the three-package split. A project that is not a React application, or that has a marketing page served by something other than its main app, does not need to give up the slider or duplicate the implementation.

The README links separate guides for React and for web components, and the project site carries full details.

The testing setup treats the slider as a visual component

The repository contains a Storybook setup, and that says something about how the project treats itself.

The top level listing has a .storybook directory, a stories directory, and a testSetup.ts file, and the root manifest has scripts for storybook, build-storybook, test-storybook and chromatic. There is a @storybook/react-vite dependency, so the stories are React components running in Vite, and @storybook/test and @storybook/test-runner along with @testing-library/dom, @testing-library/jest-dom and @testing-library/user-event for interaction testing. A vitest.config.ts sits at the root along with a tsconfig.base.json, and the test scripts run vitest with a coverage variant using the v8 coverage provider and a UI mode.

A slider is a component whose behaviour is mostly visual, and testing it only with unit assertions on internal state would tell you very little. Storybook lets you render every effect in every state, and Chromatic takes a screenshot of each story and diffs it against the baseline, which is a way of catching a regression where the carousel still functions but the transition looks wrong.

The chromatic script runs with --exit-zero-on-changes, which is a deliberate choice. It means the visual check reports differences but does not block the build on them. For a library with a small number of maintainers that is a reasonable trade, since a strict visual gate on every pull request becomes a queue that nobody wants to sit in, and a contributor whose change is correct but changes a snapshot should not be stuck.

The build and test orchestration runs through Turborepo, so a change in one package only rebuilds and retests what depends on it, and the lint and test tasks are run per package and aggregated.

A version 3 rewrite with a new package name

The release history shows a project that renamed itself and rebuilt its structure, and the recent tags make that clear.

The recent releases are @boxslider/slider at 3.0.1 and @boxslider/react at 3.0.1, both on 2026-03-09, and @boxslider/slider at 3.0.0 earlier the same day. The repository is named slider, the GitHub user is p-m-p, the author in the manifest is Phil Parsons, and the packages are scoped under @boxslider. So the npm scope, the package names and the repository name are three different words, and the homepage is a personal site at philparsons.co.uk rather than a product domain.

The 3.0.0 and 3.0.1 pair on the same day is the pattern of a major release followed immediately by a fix, which is what you would expect when a package layout changes. The earlier 1.x line of the project shipped under a different name, and any tutorial or blog post referring to the old package will not install.

Maintenance is current. The last push to the repository was on 2026-10-06 and the repository is not archived. The version 3 tags are from March 2026, so there has been no release since, which for a small library with a recently restructured package set is a normal quiet period rather than a signal of abandonment.

The licence is MIT, and the manifest records the author as Phil Parsons with the MIT licence explicitly. The repository also carries a CHANGELOG.md, a CLAUDE.md for coding assistant guidance, a .commitlintrc enforcing conventional commits, and a .husky directory with lint-staged wired in through the prepare script that runs husky.

The practical consequence for an adopter is that the API surface you are learning is version 3, and the guides on the project site are the reference for it.

Where BoxSlider is the wrong choice

Three situations rule it out, and they are all about scope rather than about the quality of the work.

The first is a feature set expectation. The effect list is four entries, carousel, cube, fade and tile, and the components are the same four plus the controls wrapper. If you want per-item animation, partial slides, autoplay with a progress bar, lazy loading of slide content, or accessibility behaviours such as pause on hover, the README describes none of them and you would be adding them. This is a light-weight library, and the word is doing real work in that sentence.

The second is React 18 or earlier. The React package is described as React 19 component wrappers, and the manifest pins @types/react at 19. The core package and the web components package have no such constraint, so if you are not on React 19, the answer is to use one of those two instead of the React package rather than to try the React wrapper.

The third is server rendering and frameworks that own the DOM. A library that attaches transition effects to a container element and manipulates it is doing DOM work, and a framework that renders on the server or virtualises the DOM will not enjoy that. The web components route is the one that survives that, since custom elements are designed to live in the markup, but the core library is not a framework-agnostic renderer in the sense of producing virtual nodes.

There is also the obvious alternative to weigh, which is not another slider library but writing the twenty lines. A carousel in its simplest form is a container, a transform, and a counter, and the whole justification for a library is the transitions and the controls. If the transitions do not matter to you, the dependency is not worth it, and the fact that this library is MIT and dependency free means that judgement is at least easy to make and easy to reverse.

Editorial conclusion

BoxSlider fits a team that wants a slider without a dependency tree, that is already on React 19 and would rather not write a carousel from scratch, and that cares about bundle size enough to want a size-limit budget in CI. It is the wrong choice if you need a slider with a large feature set, since the project describes itself as light weight and the effect list is four entries, and it is the wrong choice if you are on React 18 or earlier, because the React package targets React 19. Before adopting it, check the size-limit configuration in the repository to see what the budget is, and read the guide for the integration you actually want, because the three packages expose the same effects through different APIs and picking the wrong one means writing the wrapper yourself.

Frequently asked questions

What is BoxSlider and how many packages does it publish?

BoxSlider is a small TypeScript content slider with zero runtime dependencies. It publishes three packages: @boxslider/slider as the core library with factory functions and a BoxSlider class, @boxslider/react with React 19 component wrappers, and @boxslider/components with framework-agnostic web components.

Which slide transitions does BoxSlider support?

Four: carousel, cube, fade and tile. They are exposed as createCarouselSlider, createCubeSlider, createFadeSlider and createTileSlider in the core package, as the matching React components, and as the bs-carousel, bs-cube, bs-fade and bs-tile custom elements.

Can I use BoxSlider without a build step?

Yes. The core package can be loaded as an ES module from jsDelivr and used by calling a factory function against a selector, and the web components package can be loaded with a script tag and used with bs-carousel and bs-slider-controls elements in plain markup.

Does BoxSlider depend on any runtime libraries?

No. The core package is described as the core JavaScript library with zero runtime dependencies, and the root package manifest lists only devDependencies. The repository also carries a size-limit configuration and a size script, so the bundle budget is enforced rather than just asserted.

Is BoxSlider still being worked on?

The last push to the repository was on 2026-10-06 and the repository is not archived. The recent releases are @boxslider/slider and @boxslider/react at 3.0.1 on 2026-03-09, and 3.0.0 earlier the same day, and the licence is MIT.

Official sources

  1. License: MIT
  2. p-m-p/slider on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/p-m-p-slider.svg)](https://hysenlabs.com/projects/p-m-p-slider)

Was this useful?