diff --git a/components/slider/react/discrete-slider/README.md b/components/slider/react/discrete-slider/README.md new file mode 100644 index 0000000..ea2d262 --- /dev/null +++ b/components/slider/react/discrete-slider/README.md @@ -0,0 +1,48 @@ +# React Discrete Slider + +A clean, accessible, and step-based **Discrete Slider** for React applications. +Ideal for selecting values at fixed intervals like ratings, levels, or difficulty settings. + +**Author:** [@SachinK.C.](https://github.com/sachinxmpl) + +--- + +## ✨ Features + +- **Step-based Control:** Moves between fixed increments. +- **Responsive & Accessible:** Works on all devices with keyboard navigation support. +- **Dynamic Marks:** Automatically generates marks based on step size. +- **Lightweight:** Perfect for UI component libraries. + +--- + +## 🧾 Props + +| Prop | Type | Default | Description | +|------|------|----------|-------------| +| `min` | `number` | `0` | Minimum slider value | +| `max` | `number` | `100` | Maximum slider value | +| `step` | `number` | `10` | Step size for discrete intervals | +| `defaultValue` | `number` | `50` | Starting slider value | +| `onChange` | `(value: number) => void` | `null` | Callback triggered when value changes | +--- + + + +## Usage + +```jsx +import DiscreteSlider from "./DiscreteSlider"; + +export default function Example() { + const handleValueChange = (val) => { + console.log("Slider value:", val); + }; + + return ( +
+

Volume Control

+ +
+ ); +} \ No newline at end of file diff --git a/components/slider/react/discrete-slider/component.json b/components/slider/react/discrete-slider/component.json new file mode 100644 index 0000000..5fbb817 --- /dev/null +++ b/components/slider/react/discrete-slider/component.json @@ -0,0 +1,42 @@ +{ + "name": "discrete-slider", + "category": "slider", + "framework": "react", + "tags": ["slider", "discrete", "range", "step", "ui component", "react", "tailwind", "responsive"], + "author": "Sachin K.C.", + "license": "MIT", + "version": "1.1.0", + "preview": "A responsive, Tailwind CSS-based discrete range slider component for React.", + "props": [ + { + "name": "min", + "type": "number", + "description": "The minimum selectable value of the slider.", + "default": 0 + }, + { + "name": "max", + "type": "number", + "description": "The maximum selectable value of the slider.", + "default": 100 + }, + { + "name": "step", + "type": "number", + "description": "The step interval between slider positions.", + "default": 10 + }, + { + "name": "defaultValue", + "type": "number", + "description": "The default value displayed when the slider is initialized.", + "default": 40 + }, + { + "name": "onChange", + "type": "(value: number) => void", + "description": "Callback triggered when the slider value changes.", + "default": null + } + ] +} diff --git a/components/slider/react/discrete-slider/discrete_slider.jsx b/components/slider/react/discrete-slider/discrete_slider.jsx new file mode 100644 index 0000000..e44c6a3 --- /dev/null +++ b/components/slider/react/discrete-slider/discrete_slider.jsx @@ -0,0 +1,84 @@ +"use client"; +import React, { useState } from "react"; + +const DiscreteSlider = ({ + min = 0, + max = 100, + step = 10, + defaultValue = 40, + onChange = null, +}) => { + const [value, setValue] = useState(defaultValue); + const [hover, setHover] = useState(false); + + const handleChange = (e) => { + const val = Number(e.target.value); + setValue(val); + if (onChange) onChange(val); + }; + + const percent = ((value - min) / (max - min)) * 100; + const tooltipPosition = Math.min(Math.max(percent, 0), 100); + + return ( +
+ setHover(true)} + onMouseLeave={() => setHover(false)} + aria-label="Discrete slider" + aria-valuenow={value} + className="w-full h-[6px] appearance-none rounded-md outline-none bg-gray-300" + style={{ + background: `linear-gradient(to right, #0ea5e9 ${percent}%, #cdd6e0 ${percent}%)`, + }} + /> + +
+ {value} +
+ + {/* Custom thumb (WebKit / Firefox) */} + +
+ ); +}; + +export default DiscreteSlider;