{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "slider", "type": "registry:ui", "title": "Slider", "description": "Range input with an optional mono value readout beside its label.", "categories": [ "forms" ], "registryDependencies": [ "https://whiskeyjack.net/r/utils.json" ], "files": [ { "path": "components/ui/slider.tsx", "type": "registry:ui", "target": "components/ui/slider.tsx", "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface SliderProps\n extends Omit, \"onChange\" | \"type\" | \"value\"> {\n /** Optional label shown above the slider. */\n label?: React.ReactNode;\n value: number;\n onChange: (value: number) => void;\n /**\n * Optional formatter for the value display shown to the right of the label.\n * If `label` is present and `formatValue` is provided (or the value is a\n * finite number), the formatted value is rendered as a mono / tabular hint.\n */\n formatValue?: (value: number) => string;\n}\n\n/**\n * A thin, accent-themed range slider. Uses a native ``\n * with styling injected via Tailwind arbitrary variants for both the WebKit\n * and Firefox thumb pseudo-elements. The label + value-readout row above the\n * track follows the design-system \"field label\" pattern (small caps, mono).\n */\nconst Slider = React.forwardRef(\n ({ label, value, onChange, formatValue, className, min, max, step, id: idProp, ...props }, ref) => {\n const autoId = React.useId();\n const id = idProp ?? (label !== undefined ? autoId : undefined);\n const display = formatValue ? formatValue(value) : String(value);\n return (\n
\n {label !== undefined && (\n
\n \n {label}\n \n {formatValue && (\n \n {display}\n \n )}\n
\n )}\n onChange(Number(e.target.value))}\n className={cn(\n \"appearance-none w-full h-1.5 rounded-full cursor-pointer\",\n // Track: neutral-700 in dark (NOT neutral-800, which equals\n // --color-surface-dark #27272a -- the track would vanish on a Card).\n \"bg-[var(--color-warm-200)] dark:bg-[var(--color-neutral-700)]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-accent-500)] focus-visible:ring-offset-2\",\n // WebKit thumb\n \"[&::-webkit-slider-thumb]:appearance-none\",\n \"[&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4\",\n \"[&::-webkit-slider-thumb]:rounded-full\",\n \"[&::-webkit-slider-thumb]:bg-[var(--color-accent-500)]\",\n \"[&::-webkit-slider-thumb]:shadow-md\",\n \"[&::-webkit-slider-thumb]:transition-transform\",\n \"hover:[&::-webkit-slider-thumb]:scale-110\",\n \"active:[&::-webkit-slider-thumb]:scale-95\",\n // Firefox thumb\n \"[&::-moz-range-thumb]:appearance-none\",\n \"[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4\",\n \"[&::-moz-range-thumb]:rounded-full\",\n \"[&::-moz-range-thumb]:bg-[var(--color-accent-500)]\",\n \"[&::-moz-range-thumb]:border-0\",\n \"[&::-moz-range-thumb]:shadow-md\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\",\n )}\n {...props}\n />\n
\n );\n },\n);\nSlider.displayName = \"Slider\";\n\nexport { Slider };\n" } ], "docs": "The control for a value along a continuum: a target, a threshold, a volume. It wraps a native range input, so `min`, `max` and `step` are passed straight through and do not appear in the props table below -- they arrive via the inherited input attributes. Add `formatValue` for a live readout next to the label. It styles the native thumb across browsers and exposes aria-valuetext.", "meta": { "group": "forms", "related": [ "input" ], "exports": [ "Slider" ], "siteSlug": "slider" } }