Files
Lucy 46360b6827 feat: agregar design system completo con 2 temas (Industrial + Moderno)
- Tokens CSS con variables para ambos temas (dark/light)
- 21 componentes reutilizables (buttons, cards, tables, modals, etc.)
- 10 pantallas POS (login, catálogo, POS, inventario, clientes, facturación, contabilidad, dashboard, configuración, reportes)
- Preview interactivo con selector de tema
- Generado por el equipo de Hugo (Milo-UX, Iris-UI, Zara-Frontend)
2026-04-01 01:41:04 +00:00

467 lines
16 KiB
HTML

<!DOCTYPE html>
<html lang="es" data-theme="industrial">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nexus Autoparts — Inputs</title>
<link rel="stylesheet" href="../tokens/tokens.css">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: var(--font-body);
background: var(--color-bg-base);
color: var(--color-text-primary);
padding: var(--space-8);
transition: var(--transition-normal);
}
.theme-switcher {
position: sticky; top: 0; z-index: var(--z-sticky);
display: flex; gap: var(--space-2);
padding: var(--space-3) var(--space-4);
background: var(--color-bg-elevated);
border-bottom: 1px solid var(--color-border);
margin: calc(-1 * var(--space-8)); margin-bottom: var(--space-8);
}
.theme-switcher button {
padding: var(--space-2) var(--space-4);
border: 1px solid var(--color-border);
background: var(--color-bg-base); color: var(--color-text-primary);
border-radius: var(--radius-md); cursor: pointer;
font-family: var(--font-body); font-size: var(--text-body-sm);
transition: var(--transition-fast);
}
.theme-switcher button.active {
background: var(--color-primary); color: var(--color-text-inverse);
border-color: var(--color-primary);
}
h1 { font-family: var(--font-heading); font-size: var(--text-h2);
font-weight: var(--heading-weight-primary); margin-bottom: var(--space-2);
color: var(--color-text-accent); }
.subtitle { color: var(--color-text-muted); font-size: var(--text-body); margin-bottom: var(--space-8); }
section { margin-bottom: var(--space-10); }
section h2 {
font-family: var(--font-heading); font-size: var(--text-h4);
font-weight: var(--heading-weight-secondary); color: var(--color-text-secondary);
margin-bottom: var(--space-4); padding-bottom: var(--space-2);
border-bottom: 1px solid var(--color-border);
}
.component-row {
display: flex; flex-wrap: wrap; gap: var(--space-6);
align-items: flex-start; margin-bottom: var(--space-6);
}
.label-text {
font-size: var(--text-caption); color: var(--color-text-muted);
text-transform: uppercase; letter-spacing: var(--tracking-widest);
font-weight: var(--font-weight-semibold); margin-bottom: var(--space-2);
}
/* ====== Input Base ====== */
.form-group {
display: flex; flex-direction: column; min-width: 240px;
}
.form-group label {
font-size: var(--text-body-sm); font-weight: var(--font-weight-semibold);
color: var(--color-text-secondary); margin-bottom: var(--space-1);
}
.form-group .helper {
font-size: var(--text-caption); color: var(--color-text-muted);
margin-top: var(--space-1);
}
.form-group .error-msg {
font-size: var(--text-caption); color: var(--color-error);
margin-top: var(--space-1);
}
.input {
width: 100%;
padding: var(--space-3) var(--space-4);
font-family: var(--font-body);
font-size: var(--text-body);
color: var(--color-text-primary);
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
transition: var(--transition-fast);
outline: none;
}
.input::placeholder { color: var(--color-text-muted); }
.input:hover:not(:disabled) { border-color: var(--color-border-strong); }
.input:focus { border-color: var(--color-border-focus); box-shadow: var(--shadow-focus); }
.input:disabled { opacity: 0.5; cursor: not-allowed; }
.input.input-error { border-color: var(--color-error); }
.input.input-error:focus { box-shadow: 0 0 0 3px rgba(239,68,68,0.3); }
.input.input-success { border-color: var(--color-success); }
/* Number input with mono font for prices */
.input-mono {
font-family: var(--font-mono);
font-size: var(--text-mono);
letter-spacing: var(--tracking-wide);
}
/* ====== Search Input ====== */
.search-wrapper {
position: relative; width: 100%;
}
.search-wrapper .search-icon {
position: absolute; left: var(--space-3); top: 50%; transform: translateY(-50%);
color: var(--color-text-muted); font-size: 16px; pointer-events: none;
}
.search-wrapper .input {
padding-left: var(--space-10);
}
.search-wrapper .search-clear {
position: absolute; right: var(--space-3); top: 50%; transform: translateY(-50%);
background: none; border: none; color: var(--color-text-muted);
cursor: pointer; font-size: 16px; padding: var(--space-1);
border-radius: var(--radius-full); transition: var(--transition-fast);
}
.search-wrapper .search-clear:hover { color: var(--color-text-primary); }
/* ====== Select ====== */
.select {
width: 100%;
padding: var(--space-3) var(--space-4);
padding-right: var(--space-10);
font-family: var(--font-body);
font-size: var(--text-body);
color: var(--color-text-primary);
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
transition: var(--transition-fast);
outline: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23888888' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right var(--space-3) center;
cursor: pointer;
}
.select:hover:not(:disabled) { border-color: var(--color-border-strong); }
.select:focus { border-color: var(--color-border-focus); box-shadow: var(--shadow-focus); }
.select:disabled { opacity: 0.5; cursor: not-allowed; }
/* ====== Checkbox ====== */
.checkbox-group {
display: flex; align-items: center; gap: var(--space-3); cursor: pointer;
user-select: none;
}
.checkbox-group input[type="checkbox"] {
appearance: none; width: 20px; height: 20px;
border: 2px solid var(--color-border-strong);
border-radius: var(--radius-sm); background: var(--color-bg-elevated);
cursor: pointer; transition: var(--transition-fast);
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
.checkbox-group input[type="checkbox"]:checked {
background: var(--color-primary); border-color: var(--color-primary);
}
.checkbox-group input[type="checkbox"]:checked::after {
content: '\2713'; color: var(--color-text-inverse);
font-size: 13px; font-weight: bold;
}
.checkbox-group input[type="checkbox"]:focus-visible {
box-shadow: var(--shadow-focus);
}
.checkbox-group input[type="checkbox"]:disabled {
opacity: 0.4; cursor: not-allowed;
}
.checkbox-group span {
font-size: var(--text-body); color: var(--color-text-primary);
}
/* ====== Radio ====== */
.radio-group {
display: flex; align-items: center; gap: var(--space-3); cursor: pointer;
user-select: none;
}
.radio-group input[type="radio"] {
appearance: none; width: 20px; height: 20px;
border: 2px solid var(--color-border-strong);
border-radius: var(--radius-full); background: var(--color-bg-elevated);
cursor: pointer; transition: var(--transition-fast);
flex-shrink: 0;
}
.radio-group input[type="radio"]:checked {
border-color: var(--color-primary);
background: var(--color-bg-elevated);
box-shadow: inset 0 0 0 4px var(--color-primary);
}
.radio-group input[type="radio"]:focus-visible {
box-shadow: var(--shadow-focus);
}
.radio-group input[type="radio"]:disabled {
opacity: 0.4; cursor: not-allowed;
}
.radio-group span {
font-size: var(--text-body); color: var(--color-text-primary);
}
/* ====== Toggle ====== */
.toggle {
display: flex; align-items: center; gap: var(--space-3);
cursor: pointer; user-select: none;
}
.toggle-track {
position: relative; width: 44px; height: 24px;
background: var(--color-border-strong);
border-radius: var(--radius-full);
transition: var(--transition-fast);
flex-shrink: 0;
}
.toggle-thumb {
position: absolute; top: 2px; left: 2px;
width: 20px; height: 20px;
background: white; border-radius: var(--radius-full);
transition: var(--transition-fast);
box-shadow: var(--shadow-sm);
}
.toggle input { display: none; }
.toggle input:checked + .toggle-track {
background: var(--color-primary);
}
.toggle input:checked + .toggle-track .toggle-thumb {
left: 22px;
}
.toggle-label {
font-size: var(--text-body); color: var(--color-text-primary);
}
/* ====== Input Sizes ====== */
.input-sm { padding: var(--space-2) var(--space-3); font-size: var(--text-body-sm); }
.input-lg { padding: var(--space-4) var(--space-5); font-size: var(--text-body-lg); }
</style>
</head>
<body>
<div class="theme-switcher">
<button class="active" onclick="setTheme('industrial')">Industrial Robusto</button>
<button onclick="setTheme('modern')">Tecnico Moderno</button>
</div>
<h1>Inputs</h1>
<p class="subtitle">Campos de formulario para el sistema POS. Text, number, search, select, checkbox, radio y toggle.</p>
<!-- Text Input -->
<section>
<h2>Text Input</h2>
<div class="component-row">
<div class="form-group">
<label>Nombre del cliente</label>
<input class="input" type="text" placeholder="Ej: Juan Perez">
<span class="helper">Nombre completo del cliente</span>
</div>
<div class="form-group">
<label>RFC</label>
<input class="input" type="text" placeholder="XAXX010101000" value="AAAS940812">
</div>
<div class="form-group">
<label>Email (error)</label>
<input class="input input-error" type="email" value="correo-invalido">
<span class="error-msg">Formato de email invalido</span>
</div>
</div>
<div class="component-row">
<div class="form-group">
<label>Campo deshabilitado</label>
<input class="input" type="text" value="No editable" disabled>
</div>
<div class="form-group">
<label>Campo valido</label>
<input class="input input-success" type="text" value="Dato correcto">
</div>
</div>
</section>
<!-- Number Input -->
<section>
<h2>Number Input (Precios / Cantidades)</h2>
<div class="component-row">
<div class="form-group">
<label>Precio unitario</label>
<input class="input input-mono" type="text" value="$1,250.00" placeholder="$0.00">
</div>
<div class="form-group">
<label>Cantidad</label>
<input class="input input-mono" type="number" value="5" min="1" max="999" style="width: 120px;">
</div>
<div class="form-group">
<label>SKU / Numero de parte</label>
<input class="input input-mono" type="text" placeholder="ACM-BRK-001" value="MOT-OIL-5W30">
</div>
</div>
</section>
<!-- Search Input -->
<section>
<h2>Search Input</h2>
<div class="component-row">
<div class="form-group" style="min-width: 400px;">
<label>Buscar producto</label>
<div class="search-wrapper">
<span class="search-icon">&#128269;</span>
<input class="input" type="text" placeholder="Buscar por nombre, SKU o numero OEM...">
</div>
</div>
</div>
<div class="component-row">
<div class="form-group" style="min-width: 400px;">
<label>Busqueda con valor</label>
<div class="search-wrapper">
<span class="search-icon">&#128269;</span>
<input class="input" type="text" value="Balata ceramica Brembo">
<button class="search-clear" title="Limpiar">&#10005;</button>
</div>
</div>
</div>
</section>
<!-- Select -->
<section>
<h2>Select</h2>
<div class="component-row">
<div class="form-group">
<label>Marca del vehiculo</label>
<select class="select">
<option value="">Selecciona marca...</option>
<option>Chevrolet</option>
<option>Ford</option>
<option>Nissan</option>
<option>Toyota</option>
<option>Volkswagen</option>
<option>Honda</option>
</select>
</div>
<div class="form-group">
<label>Ano del modelo</label>
<select class="select">
<option value="">Selecciona ano...</option>
<option>2026</option>
<option>2025</option>
<option>2024</option>
<option>2023</option>
<option>2022</option>
</select>
</div>
<div class="form-group">
<label>Metodo de pago</label>
<select class="select">
<option>Efectivo</option>
<option>Tarjeta</option>
<option>Transferencia</option>
<option>Credito</option>
</select>
</div>
</div>
<div class="component-row">
<div class="form-group">
<label>Select deshabilitado</label>
<select class="select" disabled>
<option>No disponible</option>
</select>
</div>
</div>
</section>
<!-- Checkbox -->
<section>
<h2>Checkbox</h2>
<div class="component-row" style="flex-direction: column; gap: var(--space-3);">
<label class="checkbox-group">
<input type="checkbox" checked> <span>Requiere factura (CFDI)</span>
</label>
<label class="checkbox-group">
<input type="checkbox"> <span>Aplicar descuento por volumen</span>
</label>
<label class="checkbox-group">
<input type="checkbox" checked> <span>Enviar ticket por WhatsApp</span>
</label>
<label class="checkbox-group">
<input type="checkbox" disabled> <span>Opcion deshabilitada</span>
</label>
</div>
</section>
<!-- Radio -->
<section>
<h2>Radio</h2>
<div class="component-row" style="flex-direction: column; gap: var(--space-3);">
<label class="radio-group">
<input type="radio" name="tipo-venta" checked> <span>Venta de mostrador</span>
</label>
<label class="radio-group">
<input type="radio" name="tipo-venta"> <span>Venta a taller</span>
</label>
<label class="radio-group">
<input type="radio" name="tipo-venta"> <span>Venta mayoreo</span>
</label>
<label class="radio-group">
<input type="radio" name="tipo-venta" disabled> <span>No disponible</span>
</label>
</div>
</section>
<!-- Toggle -->
<section>
<h2>Toggle</h2>
<div class="component-row" style="flex-direction: column; gap: var(--space-4);">
<label class="toggle">
<input type="checkbox" checked>
<div class="toggle-track"><div class="toggle-thumb"></div></div>
<span class="toggle-label">Modo oscuro</span>
</label>
<label class="toggle">
<input type="checkbox">
<div class="toggle-track"><div class="toggle-thumb"></div></div>
<span class="toggle-label">Notificaciones de stock bajo</span>
</label>
<label class="toggle">
<input type="checkbox" checked>
<div class="toggle-track"><div class="toggle-thumb"></div></div>
<span class="toggle-label">Imprimir ticket automaticamente</span>
</label>
</div>
</section>
<!-- Input Sizes -->
<section>
<h2>Tamanos</h2>
<div class="component-row">
<div class="form-group">
<label>Pequeno</label>
<input class="input input-sm" type="text" placeholder="Input sm">
</div>
<div class="form-group">
<label>Normal</label>
<input class="input" type="text" placeholder="Input normal">
</div>
<div class="form-group">
<label>Grande</label>
<input class="input input-lg" type="text" placeholder="Input lg">
</div>
</div>
</section>
<script>
function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
document.querySelectorAll('.theme-switcher button').forEach(btn => {
btn.classList.toggle('active', btn.textContent.toLowerCase().includes(theme === 'industrial' ? 'industrial' : 'tecnico'));
});
}
// Toggle functionality
document.querySelectorAll('.toggle input').forEach(input => {
input.addEventListener('change', function() {
// Toggle already handled by CSS
});
});
</script>
</body>
</html>