2
React + MotionInputs
Selector de cantidad
Botones de menos y más alrededor de una cifra que sube o baja deslizándose cada vez que cambia.
Ajustes
2
12
Código
import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Minus, Plus } from "lucide-react";
interface AnimatedQuantityProps {
value?: number;
defaultValue?: number;
max?: number;
onChange?: (value: number) => void;
}
export default function AnimatedQuantity({
value,
defaultValue = 2,
max = 12,
onChange,
}: AnimatedQuantityProps) {
const [internal, setInternal] = useState(defaultValue);
const n = value ?? internal;
const set = (next: number) => {
if (value === undefined) setInternal(next);
onChange?.(next);
};
return (
<div className="flex items-center gap-5 rounded-full bg-white p-2 text-[#1d1d1f] shadow-[0_1px_2px_rgba(0,0,0,0.03),0_8px_28px_rgba(0,0,0,0.05)] dark:bg-[#1c1c1e] dark:text-[#f5f5f7]">
<button
type="button"
aria-label="Restar"
onClick={() => set(Math.max(0, n - 1))}
className="grid h-9 w-9 place-items-center rounded-full bg-black/5 dark:bg-white/10"
>
<Minus className="h-4 w-4" />
</button>
<AnimatePresence mode="popLayout" initial={false}>
<motion.strong
key={n}
initial={{ y: 12, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: -12, opacity: 0 }}
className="w-7 text-center"
>
{n}
</motion.strong>
</AnimatePresence>
<button
type="button"
aria-label="Sumar"
onClick={() => set(Math.min(max, n + 1))}
className="grid h-9 w-9 place-items-center rounded-full bg-black/5 dark:bg-white/10"
>
<Plus className="h-4 w-4" />
</button>
</div>
);
}
Prompt para IA
Pégalo en ChatGPT, Claude o Cursor y adaptará el bloque a tu proyecto con estos ajustes, aunque no uses React.
Más en Inputs
Dónde usarlo
El selector de cantidad aparece allí donde se pide algo: el carrito de una tienda online, las entradas de un concierto o las raciones de una app de comida. La cifra que se desliza hace visible cada toque, y nadie añade tres botellas de vino sin querer. Parece un control aburrido, pero se toca más que casi ningún otro.
Pon un máximo con sentido para tu caso, como el stock real o el tope de entradas por pedido. Por defecto se para en cero; si el cero no tiene sentido, por ejemplo en una línea del carrito, empieza el mínimo en uno.