Formulariosinputstepper
Numeric Stepper
Selector numérico con botones más/menos para ajustar cantidades y unidades.
Vista Previa en Vivo
Uso
Copia y pega este código directamente en tu componente React:
tsx
import { StepperInput } from 'react-component-kit-ui/forms';
<StepperInput id="qty" label="Quantity" value={1} min={1} max={10} />Instalación Manual
Si no estás usando el paquete npm, crea un archivo nuevo y pega el siguiente código: src/components/StepperInput.tsx + StepperInput.css:
StepperInput.tsx
'use client';
import { useEffect, useRef } from 'react';
import './StepperInput.css';
/**
* StepperInput — A numeric input with increment and decrement buttons for precise control.
*
* @param {string} label - Optional input label.
* @param {string} id - HTML ID for the number input.
* @param {string} name - HTML name binding.
* @param {number} value - Initial default value. Default is 1.
* @param {number} min - Minimum allowed value.
* @param {number} max - Maximum allowed value.
* @param {number} step - Numeric increment step. Default is 1.
*/
export interface StepperInputProps {
label?: string;
id: string;
name?: string;
value?: number;
min?: number;
max?: number;
step?: number;
}
export function StepperInput({ label, id, name, value = 1, min, max, step = 1 }: StepperInputProps) {
// Ported from the Astro <script>: runs once after mount (DOM logic kept as in the Astro kit).
const mounted = useRef(false);
useEffect(() => {
if (mounted.current) return;
mounted.current = true;
document.querySelectorAll('[data-stepper]').forEach(wrapper => {
const input = wrapper.querySelector('[data-step-input]') as HTMLInputElement;
const minus = wrapper.querySelector('[data-step-minus]');
const plus = wrapper.querySelector('[data-step-plus]');
if (!input || !minus || !plus) return;
const step = parseFloat(input.step) || 1;
const min = input.min !== "" ? parseFloat(input.min) : -Infinity;
const max = input.max !== "" ? parseFloat(input.max) : Infinity;
minus.addEventListener('click', () => {
const current = parseFloat(input.value) || 0;
if (current - step >= min) input.value = (current - step).toString();
});
plus.addEventListener('click', () => {
const current = parseFloat(input.value) || 0;
if (current + step <= max) input.value = (current + step).toString();
});
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<>
<div className="stepper-container" data-rk-dbf2a1="">
{label && <label className="stepper-label" htmlFor={id} data-rk-dbf2a1="">{label}</label>}
<div className="stepper" data-stepper data-rk-dbf2a1="">
<button type="button" className="stepper-btn stepper-btn--minus" data-step-minus aria-label="Decrease value" data-rk-dbf2a1="">−</button>
<input type="number" id={id} name={name} min={min} max={max} step={step} defaultValue={value} className="stepper-input" data-step-input data-rk-dbf2a1="" />
<button type="button" className="stepper-btn stepper-btn--plus" data-step-plus aria-label="Increase value" data-rk-dbf2a1="">+</button>
</div>
</div>
</>
);
}
export default StepperInput;StepperInput.css
/* StepperInput — ported from astro-component-kit (forms/StepperInput.astro) */
.stepper-container:where([data-rk-dbf2a1]) { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); }
.stepper-label:where([data-rk-dbf2a1]) { font-size: 0.85rem; font-weight: 600; color: var(--c-text-2, #94a3b8); margin-left: 0.5rem; }
.stepper:where([data-rk-dbf2a1]) {
display: flex; align-items: center;
background: var(--c-bg-elev, rgba(255,255,255,0.05));
border-radius: var(--r-md, 12px);
border: 1px solid var(--c-border, rgba(255,255,255,0.1));
overflow: hidden;
width: fit-content;
}
.stepper-btn:where([data-rk-dbf2a1]) {
width: 40px; height: 40px;
background: var(--c-primary, #6366f1);
border: none; color: #fff;
font-size: 1.25rem; font-weight: 600;
cursor: pointer; transition: all 0.2s;
display: grid; place-items: center;
}
.stepper-btn:hover:where([data-rk-dbf2a1]) { background: var(--c-primary-light, #818cf8); }
.stepper-btn:active:where([data-rk-dbf2a1]) { transform: scale(0.95); }
.stepper-input:where([data-rk-dbf2a1]) {
width: 60px; height: 40px;
background: transparent;
border: none; text-align: center;
color: var(--c-text-1, #fff);
font-size: 1rem; font-weight: 700;
outline: none; -moz-appearance: textfield;
font-family: inherit;
}
.stepper-input:where([data-rk-dbf2a1])::-webkit-inner-spin-button,
.stepper-input:where([data-rk-dbf2a1])::-webkit-outer-spin-button { display: none; }Información Rápida
- Categoría
- Formularios
- Nombre de archivo
StepperInput.tsx- Dependencias
- Ninguna — React + CSS puro
- Etiquetas
- inputstepper