JSPM

@3nvs/polyfront-slider

1.1.4
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 29
  • Score
    100M100P100Q94635F
  • License MIT

A modern, accessible TypeScript Web Component slider supporting horizontal, vertical, and range modes with ticks, labels, tooltips, and form integration.

Package Exports

  • @3nvs/polyfront-slider

Readme

๐ŸŽ›๏ธ @3nvs/polyfront-slider (v1.1.4)

npm (scoped) license Storybook CI

The official scoped package for the Polyfront Slider Web Component โ€” built with TypeScript, accessible, framework-agnostic, and optimized for modern apps.


โœจ Overview

polyfront-slider is an open-source Web Component slider that works in React, Vue, Angular, Svelte, or plain HTML/JS.

It provides enterprise-grade configurability, theming tokens, accessibility, and form integration โ€” all in a single, dependency-free package.


๐Ÿš€ Key Features

Category Highlights
๐ŸŽจ UI/UX OKLCH color system, dark mode, hover/active/focus states, large touch targets, and elevation shadows.
๐Ÿงฉ Configurable Supports {min, max, step} or discrete arrays like [0,1500,1600,โ€ฆ]. Auto-detects step size and disables missing values.
๐Ÿงฑ Modes Single or dual-thumb (range) slider.
๐Ÿง  Smart Logic Auto GCD step detection, blocked intervals, minimum thumb distance.
โ™ฟ Accessible Full WAI-ARIA compliance, keyboard navigation, and form-associated support.
๐Ÿ–ฅ๏ธ Responsive 100 % width, mobile-friendly, fits any layout.
๐ŸŒ— Themeable Size presets (sm,md,lg), CSS tokens, and dark/light mode support.
๐Ÿงช Reliable TypeScript + Vitest + Storybook 8.6 + GitHub CI.
๐Ÿงฐ Reusable Works standalone or via npm import in any framework.

๐Ÿงฉ Installation

# Scoped (recommended)
npm install @3nvs/polyfront-slider

# or use alias (unscoped)
npm install polyfront-slider

๐Ÿง‘โ€๐Ÿ’ป Usage

๐Ÿš€ Quick Start

1๏ธโƒฃ Register the component

import { definePolyfrontSlider } from '@3nvs/polyfront-slider';
definePolyfrontSlider();

2๏ธโƒฃ Add to your HTML / JSX

<polyfront-slider id="price-slider" style="inline-size:100%;max-inline-size:480px"></polyfront-slider>

3๏ธโƒฃ Configure dynamically

const slider = document.getElementById('price-slider');
slider.setConfig({
  mode: 'range',
  orientation: 'horizontal',
  size: 'md',
  values: [0,1500,1600,1700,1800,1900,2000],
  showTicks: true,
  showLabels: true,
  showTooltip: true,
  tickEvery: 1,
  disableMissingSteps: true,
  blockedIntervals: [[1600,1699]],
  minThumbDistance: 1,
  name: 'price'
});

For easier usage across frameworks, use these helper functions:

Range Slider

import { createRangeSlider } from '@3nvs/polyfront-slider';

const priceSlider = createRangeSlider(0, 2000, 100);
document.body.appendChild(priceSlider);

Volume Control

import { createVolumeControl } from '@3nvs/polyfront-slider';

const volumeControl = createVolumeControl(100);
volumeControl.style.height = '200px';
document.body.appendChild(volumeControl);

Price Slider with Discrete Values

import { createPriceSlider } from '@3nvs/polyfront-slider';

const priceSlider = createPriceSlider([0, 1500, 1600, 1700, 1800, 1900, 2000]);
document.body.appendChild(priceSlider);

Discrete Value Slider (Sizes, Ratings, etc.)

import { createDiscreteSlider } from '@3nvs/polyfront-slider';

// Size selector
const sizeSlider = createDiscreteSlider(['XS', 'S', 'M', 'L', 'XL', 'XXL'], 'single');
document.body.appendChild(sizeSlider);

// Rating range
const ratingSlider = createDiscreteSlider([1, 2, 3, 4, 5], 'range');
document.body.appendChild(ratingSlider);

๐ŸŽจ React-Style Props

import { createSliderWithProps } from '@3nvs/polyfront-slider';

const slider = createSliderWithProps({
  mode: 'range',
  min: 0,
  max: 100,
  step: 5,
  showTooltip: true,
  onChange: (value) => console.log('Value changed:', value),
  onInput: (value) => console.log('Value input:', value),
  className: 'my-slider',
  style: { width: '100%', margin: '20px 0' },
  id: 'my-slider'
});
document.body.appendChild(slider);

๐ŸŽญ Event Handling

const slider = document.getElementById('my-slider');

// Listen for value changes
slider.addEventListener('polyfront-slider-change', (e) => {
  console.log('Final value:', e.detail.value);
});

// Listen for real-time input
slider.addEventListener('polyfront-slider-input', (e) => {
  console.log('Current value:', e.detail.value);
});

// Get current value
const currentValue = slider.getValue();
console.log('Current value:', currentValue);

// Set value programmatically
slider.setValue([20, 80]); // For range slider
slider.setValue(50); // For single slider

๐ŸŽจ Framework Integration Examples

React

import { useEffect, useRef } from 'react';
import { definePolyfrontSlider, createSliderWithProps } from '@3nvs/polyfront-slider';

// Register once
definePolyfrontSlider();

function PriceSlider({ onChange }: { onChange: (value: number[]) => void }) {
  const sliderRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (sliderRef.current) {
      const slider = createSliderWithProps({
        mode: 'range',
        min: 0,
        max: 2000,
        step: 100,
        showTooltip: true,
        onChange: onChange,
        style: { width: '100%' }
      });
      
      sliderRef.current.appendChild(slider);
      
      return () => {
        sliderRef.current?.removeChild(slider);
      };
    }
  }, [onChange]);

  return <div ref={sliderRef} />;
}

Vue 3

<template>
  <div ref="sliderContainer" />
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { definePolyfrontSlider, createSliderWithProps } from '@3nvs/polyfront-slider';

definePolyfrontSlider();

const sliderContainer = ref<HTMLElement>();
let slider: HTMLElement;

onMounted(() => {
  if (sliderContainer.value) {
    slider = createSliderWithProps({
      mode: 'range',
      min: 0,
      max: 100,
      step: 5,
      showTooltip: true,
      onChange: (value) => emit('change', value)
    });
    sliderContainer.value.appendChild(slider);
  }
});

onUnmounted(() => {
  slider?.remove();
});

const emit = defineEmits<{
  change: [value: number[]]
}>();
</script>

Angular

import { Component, ElementRef, OnInit, OnDestroy } from '@angular/core';
import { definePolyfrontSlider, createSliderWithProps } from '@3nvs/polyfront-slider';

@Component({
  selector: 'app-price-slider',
  template: '<div #sliderContainer></div>'
})
export class PriceSliderComponent implements OnInit, OnDestroy {
  @ViewChild('sliderContainer', { static: true }) container!: ElementRef;
  private slider?: HTMLElement;

  ngOnInit() {
    definePolyfrontSlider();
    
    this.slider = createSliderWithProps({
      mode: 'range',
      min: 0,
      max: 2000,
      step: 100,
      showTooltip: true,
      onChange: (value) => this.onValueChange(value)
    });
    
    this.container.nativeElement.appendChild(this.slider);
  }

  ngOnDestroy() {
    this.slider?.remove();
  }

  onValueChange(value: number[]) {
    console.log('Value changed:', value);
  }
}

Svelte

<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import { definePolyfrontSlider, createSliderWithProps } from '@3nvs/polyfront-slider';
  
  let sliderContainer: HTMLElement;
  let slider: HTMLElement;

  onMount(() => {
    definePolyfrontSlider();
    
    slider = createSliderWithProps({
      mode: 'range',
      min: 0,
      max: 100,
      step: 5,
      showTooltip: true,
      onChange: (value) => console.log('Value:', value)
    });
    
    sliderContainer.appendChild(slider);
  });

  onDestroy(() => {
    slider?.remove();
  });
</script>

<div bind:this={sliderContainer} />

โš™๏ธ Config Options

Option Type Default Description
mode 'single' | 'range' 'single' Enables range (2 thumbs) or single thumb.
orientation 'horizontal' | 'vertical' 'horizontal' Slider direction.
size 'sm' | 'md' | 'lg' 'md' Track and thumb size preset.
values Array<number | string | object> โ€” Discrete slider values.
min / max / step number โ€” Continuous slider range.
disableMissingSteps boolean true Disables non-defined steps.
blockedIntervals [number,number][] [] Disable ranges of values.
minThumbDistance number 0 Minimum thumb distance in range mode.
showTicks boolean false Displays tick marks.
showLabels boolean false Displays tick labels.
showTooltip boolean false Shows tooltips for thumb values.
tickEvery number 1 Render every N-th tick/label.
rtl boolean false Right-to-left layout support.
ariaLabel* string โ€” Accessibility labels.
name string โ€” Enables form submission via JSON value.

๐ŸŽจ Theming & Custom Styles

polyfront-slider {
  --pf-color-fill: oklch(0.63 0.21 35);
  --pf-color-fill-strong: oklch(0.56 0.22 35);
  --pf-color-thumb-border: oklch(0.63 0.21 35);
  --pf-track-size: 10px;
  --pf-thumb-size: 28px;
  --pf-focus: 0 0 0 4px color-mix(in oklab, var(--pf-color-fill) 35%, transparent);
}

โœ… Supports dark mode (prefers-color-scheme: dark) and reduced motion.


๐Ÿงช Testing

npm run test

Example:

import { PolyfrontSlider } from '@3nvs/polyfront-slider';

const el = new PolyfrontSlider();
el.setConfig({ min: 0, max: 100, step: 10, mode: 'range' });
el.setValue([20, 80]);
expect(el.getValue()).toEqual([20, 80]);

๐Ÿ“˜ Storybook Demo

Local preview:

npm run storybook

Live demo โ†’ https://nirmalsamaranayaka.github.io/polyfront-slider


๐Ÿ—๏ธ Build

npm run build

Outputs:

dist/
โ”œโ”€ index.mjs
โ”œโ”€ index.cjs
โ””โ”€ index.d.ts

โš™๏ธ CI / CD via GitHub Actions

Workflow Trigger Purpose
ci.yml Push/PR โ†’ main Type check, test, build verification
storybook.yml Push โ†’ main Deploys Storybook to GitHub Pages
release.yml Tag push (v*.*.*) Auto-publishes to npm (requires NPM_TOKEN)

๐Ÿ“ Folder Structure

polyfront-slider/
โ”œโ”€ dist/                            โ† build output (from @3nvs/polyfront-slider)
โ”œโ”€ src/
โ”‚  โ”œโ”€ index.ts
โ”‚  โ””โ”€ polyfront-slider.ts
โ”œโ”€ tests/                           โ† Vitest tests
โ”‚  โ””โ”€ polyfront-slider.test.ts
โ”œโ”€ stories/                          โ† Storybook config
โ”‚  โ””โ”€ polyfront-slider.stories.ts
โ”œโ”€ .storybook/
โ”œโ”€ .github/workflows/                โ† CI workflows (ci.yml, storybook.yml, etc.)
โ”œโ”€ tsup.config.ts
โ”œโ”€ tsconfig.json
โ”œโ”€ packages/                        โ† workspace packages
โ”‚  โ”œโ”€ slider/                       โ† canonical scoped package (@3nvs/polyfront-slider)
โ”‚  โ”‚   โ”œโ”€ CHANGELOG.md
โ”‚  โ”‚   โ””โ”€ package.json
โ”‚  โ””โ”€ slider-shim/                  โ† unscoped alias (polyfront-slider)
โ”‚      โ”œโ”€ CHANGELOG.md
โ”‚      โ”œโ”€ index.cjs
โ”‚      โ”œโ”€ index.mjs
โ”‚      โ”œโ”€ index.d.ts
โ”‚      โ””โ”€ package.json
โ”œโ”€ LICENSE
โ”œโ”€ .npmrc                           โ† optional npm scope config
โ””โ”€ package.json                     โ† workspace root (private)
โ””โ”€ README.md

๐ŸŒ Publishing to npm

npm run build
npm version patch
npm publish --access public

๐Ÿ‘จโ€๐Ÿ’ป Author

Nirmal Samaranayaka
๐Ÿ“ง nirmal.fullstack@gmail.com
๐Ÿ’ผ https://github.com/NirmalSamaranayaka


๐Ÿชช License

MIT ยฉ 2025 Nirmal Samaranayaka
See LICENSE for details.