diff --git a/src/components/slider/Example.tsx b/src/components/slider/Example.tsx
new file mode 100644
index 0000000..7835a5a
--- /dev/null
+++ b/src/components/slider/Example.tsx
@@ -0,0 +1,99 @@
+import { useState } from "react";
+import { Slider } from "./Slider";
+
+export function SliderExamples() {
+ const [continuousValue, setContinuousValue] = useState(50);
+ const [discreteValue, setDiscreteValue] = useState(5);
+ const [intensityValue, setIntensityValue] = useState(7);
+ const [weightValue, setWeightValue] = useState(70);
+
+ return (
+
+ {/* Example 1: Basic Continuous Slider */}
+
+
+ Selected: {continuousValue.toFixed(1)}
+
+
+ {/* Example 2: Discrete Slider */}
+
+
+ Selected: {discreteValue}
+
+
+ {/* Example 3: Small Size */}
+
+
+ {/* Example 4: Large Size */}
+
+
+ );
+}
+
+/**
+ * COMMON USE CASES IN PEAKFIT:
+ *
+ * 1. Workout Intensity Selection
+ * - 1-10 scale for perceived exertion
+ *
+ * 2. Rep/Set Ranges
+ * - Set target reps for exercises
+ *
+ * 3. Weight Selection
+ * - Choose working weight for exercises
+ *
+ * 4. Rest Time
+ * - Set rest periods between sets
+ *
+ * 5. Progress Tracking
+ * - Visual representation of goal completion
+ *
+ * 6. Nutrition Macros
+ * - Adjust protein/carb/fat ratios
+ */
+
+export default SliderExamples;
diff --git a/src/components/slider/Slider.module.css b/src/components/slider/Slider.module.css
new file mode 100644
index 0000000..5c82e7a
--- /dev/null
+++ b/src/components/slider/Slider.module.css
@@ -0,0 +1,262 @@
+/* Slider.module.css - Uses PeakFit Theme System */
+
+.container {
+ width: 100%;
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ -khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Old versions of Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none; /* Non-prefixed version, currently
+ supported by Chrome, Edge, Opera and Firefox */
+}
+
+.label {
+ display: block;
+ margin-bottom: 1rem;
+ color: var(--text-primary);
+}
+
+.sliderWrapper {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.value {
+ font-family: var(--font-ui);
+ font-size: 0.875rem;
+ font-weight: 500;
+ color: var(--text-secondary);
+ min-width: 2.5rem;
+ text-align: center;
+}
+
+.minValue {
+ text-align: right;
+}
+
+.maxValue {
+ text-align: left;
+}
+
+/* ===============================
+ Slider Track
+ =============================== */
+.sliderTrack {
+ position: relative;
+ flex: 1;
+ background: var(--surface-tertiary);
+ border: 1px solid var(--border-default);
+ width: 100px;
+ border-radius: 100px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+/* Sizes */
+.sliderTrack.small {
+ height: 8px;
+}
+
+.sliderTrack.medium {
+ height: 12px;
+}
+
+.sliderTrack.large {
+ height: 16px;
+}
+
+.sliderTrack:hover {
+ background: var(--surface-hover);
+}
+
+.sliderTrack.disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.sliderTrack.disabled:hover {
+ background: var(--surface-tertiary);
+}
+
+/* ===============================
+ Filled Track
+ =============================== */
+.sliderFill {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background: var(--gradient-primary);
+ border-radius: 100px;
+ pointer-events: none;
+ /* No transition - instant response */
+}
+
+/* ===============================
+ Thumb
+ =============================== */
+.thumb {
+ position: absolute;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ background: var(--surface-primary);
+ border: 3px solid var(--primary-500);
+ border-radius: 50%;
+ box-shadow: var(--shadow-md);
+ transition: all 0.2s ease;
+ z-index: 2;
+}
+
+/* Thumb sizes based on track size */
+.small .thumb {
+ width: 18px;
+ height: 18px;
+}
+
+.medium .thumb {
+ width: 22px;
+ height: 22px;
+}
+
+.large .thumb {
+ width: 26px;
+ height: 26px;
+}
+
+.thumb:hover {
+ transform: translate(-50%, -50%) scale(1.1);
+ box-shadow: var(--shadow-glow-primary);
+}
+
+/* Disable the width transition while dragging */
+.sliderFill.dragging {
+ transition: none;
+}
+
+/* Update your existing .thumb.dragging class */
+.thumb.dragging {
+ transform: translate(-50%, -50%) scale(1.15);
+ box-shadow: var(--shadow-glow-primary);
+ /* Override 'transition: all' so 'left' updates instantly,
+ but keep the smooth scale and glow effect */
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+}
+
+.disabled .thumb {
+ cursor: not-allowed;
+}
+
+.disabled .thumb:hover {
+ transform: translate(-50%, -50%);
+ box-shadow: var(--shadow-md);
+}
+
+/* ===============================
+ Tooltip
+ =============================== */
+.tooltip {
+ position: absolute;
+ bottom: calc(100% + 12px);
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 0.375rem 0.75rem;
+ background: var(--surface-secondary);
+ border: 1px solid var(--border-strong);
+ border-radius: 8px;
+ color: var(--text-primary);
+ font-family: var(--font-ui);
+ font-size: 0.875rem;
+ font-weight: 600;
+ white-space: nowrap;
+ box-shadow: var(--shadow-lg);
+ pointer-events: none;
+ animation: tooltipFadeIn 0.2s ease-out;
+ z-index: 10;
+}
+
+.tooltip::after {
+ content: "";
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 0;
+ height: 0;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-top: 6px solid var(--surface-secondary);
+}
+
+@keyframes tooltipFadeIn {
+ from {
+ opacity: 0;
+ transform: translateX(-50%) translateY(-4px);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+ }
+}
+
+/* ===============================
+ Discrete Steps
+ =============================== */
+.stepsContainer {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.stepsSubContainer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 98%;
+ height: 100%;
+}
+
+.stepMarker {
+ width: 4px;
+ height: 4px;
+ background: var(--surface-hover);
+ border-radius: 50%;
+ transition: all 0.2s ease;
+ background: var(--primary-400);
+}
+
+.stepMarker.active {
+ background: var(--primary-100);
+}
+
+/* Hide step markers on small size for cleaner look */
+.small .stepMarker {
+ width: 3px;
+ height: 3px;
+}
+
+/* ===============================
+ Responsive
+ =============================== */
+@media (max-width: 640px) {
+ .sliderWrapper {
+ gap: 0.75rem;
+ }
+
+ .value {
+ font-size: 0.75rem;
+ min-width: 2rem;
+ }
+
+ .tooltip {
+ font-size: 0.75rem;
+ padding: 0.25rem 0.5rem;
+ }
+}
diff --git a/src/components/slider/Slider.tsx b/src/components/slider/Slider.tsx
new file mode 100644
index 0000000..97884c2
--- /dev/null
+++ b/src/components/slider/Slider.tsx
@@ -0,0 +1,188 @@
+import React, { useState, useRef, useEffect } from "react";
+import classes from "./Slider.module.css";
+
+type SliderSize = "small" | "medium" | "large";
+type SliderType = "continuous" | "discrete";
+
+interface SliderProps {
+ min: number;
+ max: number;
+ value: number;
+ onChange: (value: number) => void;
+ type?: SliderType;
+ step?: number;
+ size?: SliderSize;
+ label?: string;
+ disabled?: boolean;
+ showMinMax?: boolean;
+ className?: string;
+}
+
+export const Slider: React.FC = ({
+ min,
+ max,
+ value,
+ onChange,
+ type = "continuous",
+ step = 1,
+ size = "medium",
+ label,
+ disabled = false,
+ showMinMax = true,
+ className = "",
+}) => {
+ const [showTooltip, setShowTooltip] = useState(false);
+ const [isDragging, setIsDragging] = useState(false);
+ const sliderRef = useRef(null);
+
+ // Calculate percentage from value
+ const percentage = ((value - min) / (max - min)) * 100;
+
+ // Handle value calculation and update
+ const updateValue = (clientX: number) => {
+ if (!sliderRef.current || disabled) return;
+
+ const rect = sliderRef.current.getBoundingClientRect();
+ const offsetX = Math.max(0, Math.min(clientX - rect.left, rect.width));
+ const percent = offsetX / rect.width;
+
+ let newValue = min + percent * (max - min);
+
+ // Snap to step
+ const actualStep = type === "discrete" ? step : 1;
+ newValue = Math.round(newValue / actualStep) * actualStep;
+ newValue = Math.max(min, Math.min(max, newValue));
+
+ if (newValue !== value) {
+ onChange(newValue);
+ }
+ };
+
+ // Mouse handlers
+ const handleMouseDown = (e: React.MouseEvent) => {
+ if (disabled) return;
+ e.preventDefault();
+ setIsDragging(true);
+ updateValue(e.clientX);
+ };
+
+ // Touch handlers
+ const handleTouchStart = (e: React.TouchEvent) => {
+ if (disabled) return;
+ setIsDragging(true);
+ updateValue(e.touches[0].clientX);
+ };
+
+ // Effect for drag events
+ useEffect(() => {
+ if (!isDragging) return;
+
+ const handleMouseMove = (e: MouseEvent) => {
+ updateValue(e.clientX);
+ };
+
+ const handleTouchMove = (e: TouchEvent) => {
+ e.preventDefault();
+ updateValue(e.touches[0].clientX);
+ };
+
+ const handleEnd = () => {
+ setIsDragging(false);
+ };
+
+ document.addEventListener("mousemove", handleMouseMove);
+ document.addEventListener("mouseup", handleEnd);
+ document.addEventListener("touchmove", handleTouchMove, { passive: false });
+ document.addEventListener("touchend", handleEnd);
+
+ return () => {
+ document.removeEventListener("mousemove", handleMouseMove);
+ document.removeEventListener("mouseup", handleEnd);
+ document.removeEventListener("touchmove", handleTouchMove);
+ document.removeEventListener("touchend", handleEnd);
+ };
+ }, [isDragging, value, min, max, step, type, disabled]);
+
+ // Format value for display
+ const formatValue = (val: number): string => {
+ return val.toFixed(0);
+ };
+
+ // Generate step markers for discrete mode
+ const generateSteps = () => {
+ const steps = [];
+ for (let i = min; i <= max; i += step) {
+ steps.push({
+ value: i,
+ isActive: i <= value,
+ });
+ }
+ return steps;
+ };
+
+ return (
+
+ {label &&
}
+
+
+ {/* Min value */}
+ {showMinMax && (
+
+ {formatValue(min)}
+
+ )}
+
+ {/* Slider track */}
+
+ {/* Filled track */}
+
+
+ {/* Discrete step markers */}
+ {type === "discrete" && (
+
+
+ {generateSteps().map((step, i) => (
+
+ ))}
+
+
+ )}
+
+ {/* Thumb */}
+
setShowTooltip(true)}
+ onMouseLeave={() => !isDragging && setShowTooltip(false)}
+ >
+ {/* Tooltip */}
+ {(showTooltip || isDragging) && (
+
{formatValue(value)}
+ )}
+
+
+
+ {/* Max value */}
+ {showMinMax && (
+
+ {formatValue(max)}
+
+ )}
+
+
+ );
+};