Deslizador neumorfismo
Canal hundido con relleno azul y perilla en relieve que se hunde al arrastrar; input range nativo.
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
"use client";
import { useId, useState, type CSSProperties } from "react";
/** Deslizador neumorfismo: canal hundido, perilla en relieve y valor en vivo. Usa input range nativo, así que conserva teclado y lectores de pantalla. React + TypeScript, sin dependencias. */
export type DeslizadorNeumorficoProps = {
label?: string;
min?: number;
max?: number;
step?: number;
value?: number;
defaultValue?: number;
unit?: string;
onChange?: (value: number) => void;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gcdsn-root { box-sizing: border-box; display: block; width: 100%; max-width: 360px; padding: 22px 24px; border-radius: 24px; background: #e0e5ec; color: #4b5563; font: 600 14px/1.3 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; box-shadow: 9px 9px 18px #a3b1c6, -9px -9px 18px #fff; }
.gcdsn-root *, .gcdsn-root *::before, .gcdsn-root *::after { box-sizing: border-box; }
@media (prefers-reduced-motion: reduce) { .gcdsn-root *, .gcdsn-root *::before, .gcdsn-root *::after { transition-duration: .01ms !important; } }
.gcdsn-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 16px; }
.gcdsn-value { font-size: 22px; font-weight: 800; color: #3b4658; font-variant-numeric: tabular-nums; }
.gcdsn-input { --p: 50%; -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 14px; margin: 0; border-radius: 999px; background: linear-gradient(90deg, #5b8def var(--p), transparent var(--p)), #e0e5ec; box-shadow: inset 4px 4px 8px #a3b1c6, inset -4px -4px 8px #fff; cursor: pointer; outline: 0; }
.gcdsn-input::-webkit-slider-thumb { -webkit-appearance: none; width: 34px; height: 34px; border-radius: 50%; background: linear-gradient(145deg, #f0f4fa, #d3d9e3); box-shadow: 5px 5px 10px #a3b1c6, -5px -5px 10px #fff; border: 0; transition: transform .15s; }
.gcdsn-input::-moz-range-thumb { width: 34px; height: 34px; border-radius: 50%; background: linear-gradient(145deg, #f0f4fa, #d3d9e3); box-shadow: 5px 5px 10px #a3b1c6, -5px -5px 10px #fff; border: 0; }
.gcdsn-input:active::-webkit-slider-thumb { transform: scale(.94); box-shadow: 2px 2px 5px #a3b1c6, -2px -2px 5px #fff; }
.gcdsn-input:focus-visible::-webkit-slider-thumb { outline: 3px solid #5b8def; outline-offset: 3px; }
.gcdsn-input:focus-visible::-moz-range-thumb { outline: 3px solid #5b8def; outline-offset: 3px; }`;
export function DeslizadorNeumorfico({ label = "Volumen", min = 0, max = 100, step = 1, value, defaultValue = 64, unit = "%", onChange, className = "", style }: DeslizadorNeumorficoProps) {
const id = useId();
const [inner, setInner] = useState(defaultValue);
const current = value ?? inner;
const pct = ((current - min) / (max - min)) * 100;
return (
<div className={`gcdsn-root ${className}`} style={style}>
<style>{CSS}</style>
<div className="gcdsn-head">
<label htmlFor={id}>{label}</label>
<output className="gcdsn-value" htmlFor={id}>
{current}
{unit}
</output>
</div>
<input
id={id}
className="gcdsn-input"
type="range"
min={min}
max={max}
step={step}
value={current}
style={{ "--p": `${pct}%` } as CSSProperties}
onChange={(event) => {
const next = Number(event.target.value);
setInner(next);
onChange?.(next);
}}
/>
</div>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/deslizador-neumorficoEjemplo de uso de Deslizador neumorfismo
Después de copiar deslizador-neumorfico.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { DeslizadorNeumorfico } from "./deslizador-neumorfico";
export default function Ejemplo() {
return <DeslizadorNeumorfico label="Ejemplo" />;
}Propiedades de DeslizadorNeumorfico
DeslizadorNeumorfico acepta 10 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
label? | string | Opcional. |
min? | number | Opcional. |
max? | number | Opcional. |
step? | number | Opcional. |
value? | number | Opcional. |
defaultValue? | number | Opcional. |
unit? | string | Opcional. |
onChange? | (value: number) => void | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Accesibilidad y rendimiento
El archivo tiene 65 líneas (3 KB) y no necesita @keyframes. Esto es lo que hace Deslizador neumorfismo por quien lo usa:
- Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
- Muestra un anillo de foco visible al navegar con teclado (:focus-visible).
- Es un componente de cliente de Next.js: incluye la directiva "use client".