Files
Autoparts-DB/docs/design/design-system/components/modal-confirmacion.html
Lucy ccd3962458 feat(design): add 16 new components + update 5 pages (ronda 2)
Bloqueantes POS: modal-pago, ticket-termico, banner-cliente, fkeys-footer, columnas-costo-margen
Componentes nuevos: calculadora-cambio, panel-deslizante, badge-cfdi, arbol-colapsable, tarjeta-metrica, grafica-barras, selector-periodo, etiqueta-codigo-barras
Estados: estado-vacio, banner-offline, modal-confirmacion
Páginas actualizadas: facturación, contabilidad, dashboard, configuración, reportes
2026-04-01 07:06:34 +00:00

478 lines
17 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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 — Modal de Confirmación</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: calc(var(--z-modal) + 10);
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);
}
/* === Modal Component === */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes scaleIn {
from { opacity: 0; transform: translate(-50%, -50%) scale(0.92); }
to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes scaleOut {
from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
to { opacity: 0; transform: translate(-50%, -50%) scale(0.92); }
}
.modal-overlay {
position: fixed;
inset: 0;
background: var(--overlay-backdrop, rgba(0, 0, 0, 0.6));
z-index: var(--z-modal, 1000);
display: none;
animation: fadeIn 0.2s ease-out forwards;
}
.modal-overlay.active {
display: block;
}
.modal-overlay.closing {
animation: fadeOut 0.2s ease-in forwards;
}
.modal-dialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: calc(var(--z-modal, 1000) + 1);
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-xl);
width: 90%;
max-width: 420px;
padding: var(--space-6);
text-align: center;
display: none;
animation: scaleIn 0.25s ease-out forwards;
}
.modal-dialog.active {
display: block;
}
.modal-dialog.closing {
animation: scaleOut 0.2s ease-in forwards;
}
.modal__icon {
width: 56px;
height: 56px;
border-radius: var(--radius-full);
display: flex;
align-items: center;
justify-content: center;
font-size: 26px;
margin: 0 auto var(--space-4);
}
.modal__icon--warning {
background: var(--color-warning-light);
}
.modal__icon--info {
background: var(--color-primary-muted);
}
.modal__icon--danger {
background: var(--color-error-light);
}
.modal__title {
font-family: var(--font-heading);
font-size: var(--text-h4);
font-weight: var(--heading-weight-primary);
color: var(--color-text-primary);
margin-bottom: var(--space-2);
}
.modal__desc {
font-size: var(--text-body-sm);
color: var(--color-text-muted);
line-height: 1.6;
margin-bottom: var(--space-6);
padding: 0 var(--space-2);
}
.modal__actions {
display: flex;
gap: var(--space-3);
justify-content: center;
}
.modal__btn {
flex: 1;
max-width: 180px;
padding: var(--space-3) var(--space-4);
font-family: var(--font-body);
font-size: var(--text-body-sm);
font-weight: 600;
border-radius: var(--radius-md);
cursor: pointer;
transition: var(--transition-fast);
border: 1px solid transparent;
}
.modal__btn--secondary {
background: var(--btn-secondary-bg);
color: var(--btn-secondary-text);
border-color: var(--btn-secondary-border);
}
.modal__btn--secondary:hover {
background: var(--btn-secondary-bg-hover);
}
.modal__btn--primary {
background: var(--btn-primary-bg);
color: var(--btn-primary-text);
border-color: var(--btn-primary-border);
}
.modal__btn--primary:hover {
background: var(--btn-primary-bg-hover);
box-shadow: var(--shadow-sm);
}
.modal__btn--danger {
background: var(--btn-danger-bg);
color: var(--btn-danger-text);
border-color: var(--btn-danger-bg);
}
.modal__btn--danger:hover {
opacity: 0.9;
box-shadow: var(--shadow-sm);
}
/* === Demo trigger buttons === */
.trigger-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: var(--space-4);
}
.trigger-card {
background: var(--color-surface-1);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
padding: var(--space-5);
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-3);
}
.trigger-card__label {
font-family: var(--font-mono);
font-size: var(--text-body-sm);
color: var(--color-text-muted);
background: var(--color-bg-overlay);
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-full);
}
.trigger-card__desc {
font-size: var(--text-body-sm);
color: var(--color-text-muted);
text-align: center;
line-height: 1.5;
}
.trigger-btn {
padding: var(--space-3) var(--space-5);
font-family: var(--font-body);
font-size: var(--text-body-sm);
font-weight: 600;
border-radius: var(--radius-md);
cursor: pointer;
transition: var(--transition-fast);
border: 1px solid var(--color-border);
background: var(--color-bg-elevated);
color: var(--color-text-primary);
}
.trigger-btn:hover {
background: var(--color-surface-2);
box-shadow: var(--shadow-sm);
}
.trigger-btn--warning { border-color: var(--color-warning); }
.trigger-btn--primary { border-color: var(--color-primary); }
.trigger-btn--danger { border-color: var(--color-error); }
/* === Static previews === */
.static-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
gap: var(--space-6);
}
.static-preview {
background: var(--color-surface-1);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
padding: var(--space-5);
}
.static-preview .variant-label {
font-family: var(--font-mono);
font-size: var(--text-body-sm);
color: var(--color-text-muted);
background: var(--color-bg-overlay);
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-full);
display: inline-block;
margin-bottom: var(--space-4);
}
.static-modal {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-lg);
padding: var(--space-6);
text-align: center;
}
</style>
</head>
<body>
<div class="theme-switcher">
<button class="active" onclick="document.documentElement.dataset.theme='industrial'; this.classList.add('active'); this.nextElementSibling.classList.remove('active')">🔧 Industrial</button>
<button onclick="document.documentElement.dataset.theme='modern'; this.classList.add('active'); this.previousElementSibling.classList.remove('active')">⚡ Moderno</button>
</div>
<h1>Modal de Confirmación</h1>
<p class="subtitle">Diálogos modales para confirmar acciones destructivas o importantes del sistema POS.</p>
<!-- ========== Interactive triggers ========== -->
<section>
<h2>Demo interactivo — Abrir modales</h2>
<div class="trigger-grid">
<div class="trigger-card">
<span class="trigger-card__label">a) Cancelar venta</span>
<p class="trigger-card__desc">Confirma antes de descartar una venta en curso</p>
<button class="trigger-btn trigger-btn--warning" onclick="openModal('cancelar-venta')">Abrir modal</button>
</div>
<div class="trigger-card">
<span class="trigger-card__label">b) Cerrar caja</span>
<p class="trigger-card__desc">Genera corte de caja al final del turno</p>
<button class="trigger-btn trigger-btn--primary" onclick="openModal('cerrar-caja')">Abrir modal</button>
</div>
<div class="trigger-card">
<span class="trigger-card__label">c) Ajustar stock</span>
<p class="trigger-card__desc">Ajusta inventario de múltiples artículos</p>
<button class="trigger-btn trigger-btn--warning" onclick="openModal('ajustar-stock')">Abrir modal</button>
</div>
<div class="trigger-card">
<span class="trigger-card__label">d) Cerrar periodo</span>
<p class="trigger-card__desc">Cierra periodo fiscal contable</p>
<button class="trigger-btn trigger-btn--danger" onclick="openModal('cerrar-periodo')">Abrir modal</button>
</div>
</div>
</section>
<!-- ========== Static previews ========== -->
<section>
<h2>Variantes estáticas</h2>
<div class="static-grid">
<div class="static-preview">
<span class="variant-label">a) Cancelar venta</span>
<div class="static-modal">
<div class="modal__icon modal__icon--warning">⚠️</div>
<div class="modal__title">¿Cancelar venta?</div>
<div class="modal__desc">Se perderán los artículos agregados al ticket actual.</div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary">No, continuar</button>
<button class="modal__btn modal__btn--danger">Sí, cancelar</button>
</div>
</div>
</div>
<div class="static-preview">
<span class="variant-label">b) Cerrar caja</span>
<div class="static-modal">
<div class="modal__icon modal__icon--info"></div>
<div class="modal__title">¿Cerrar caja?</div>
<div class="modal__desc">Se generará el corte de caja con total <strong style="color: var(--color-text-primary);">$15,800.00</strong></div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary">Cancelar</button>
<button class="modal__btn modal__btn--primary">Cerrar caja</button>
</div>
</div>
</div>
<div class="static-preview">
<span class="variant-label">c) Ajustar stock</span>
<div class="static-modal">
<div class="modal__icon modal__icon--warning">⚠️</div>
<div class="modal__title">¿Ajustar stock?</div>
<div class="modal__desc">Se ajustarán <strong style="color: var(--color-text-primary);">5 artículos</strong> del inventario. Esta acción no se puede deshacer.</div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary">Cancelar</button>
<button class="modal__btn modal__btn--primary">Ajustar</button>
</div>
</div>
</div>
<div class="static-preview">
<span class="variant-label">d) Cerrar periodo fiscal</span>
<div class="static-modal">
<div class="modal__icon modal__icon--danger">🛑</div>
<div class="modal__title">¿Cerrar periodo fiscal?</div>
<div class="modal__desc">Se cerrará el periodo <strong style="color: var(--color-text-primary);">Marzo 2026</strong>. No podrás registrar pólizas en este periodo.</div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary">Cancelar</button>
<button class="modal__btn modal__btn--danger">Cerrar periodo</button>
</div>
</div>
</div>
</div>
</section>
<!-- ========== Actual Modal Overlays (hidden by default) ========== -->
<!-- a) Cancelar venta -->
<div class="modal-overlay" id="overlay-cancelar-venta" onclick="if(event.target===this) closeModal('cancelar-venta')"></div>
<div class="modal-dialog" id="modal-cancelar-venta">
<div class="modal__icon modal__icon--warning">⚠️</div>
<div class="modal__title">¿Cancelar venta?</div>
<div class="modal__desc">Se perderán los artículos agregados al ticket actual.</div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary" onclick="closeModal('cancelar-venta')">No, continuar</button>
<button class="modal__btn modal__btn--danger" onclick="closeModal('cancelar-venta')">Sí, cancelar</button>
</div>
</div>
<!-- b) Cerrar caja -->
<div class="modal-overlay" id="overlay-cerrar-caja" onclick="if(event.target===this) closeModal('cerrar-caja')"></div>
<div class="modal-dialog" id="modal-cerrar-caja">
<div class="modal__icon modal__icon--info"></div>
<div class="modal__title">¿Cerrar caja?</div>
<div class="modal__desc">Se generará el corte de caja con total <strong style="color: var(--color-text-primary);">$15,800.00</strong></div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary" onclick="closeModal('cerrar-caja')">Cancelar</button>
<button class="modal__btn modal__btn--primary" onclick="closeModal('cerrar-caja')">Cerrar caja</button>
</div>
</div>
<!-- c) Ajustar stock -->
<div class="modal-overlay" id="overlay-ajustar-stock" onclick="if(event.target===this) closeModal('ajustar-stock')"></div>
<div class="modal-dialog" id="modal-ajustar-stock">
<div class="modal__icon modal__icon--warning">⚠️</div>
<div class="modal__title">¿Ajustar stock?</div>
<div class="modal__desc">Se ajustarán <strong style="color: var(--color-text-primary);">5 artículos</strong> del inventario. Esta acción no se puede deshacer.</div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary" onclick="closeModal('ajustar-stock')">Cancelar</button>
<button class="modal__btn modal__btn--primary" onclick="closeModal('ajustar-stock')">Ajustar</button>
</div>
</div>
<!-- d) Cerrar periodo fiscal -->
<div class="modal-overlay" id="overlay-cerrar-periodo" onclick="if(event.target===this) closeModal('cerrar-periodo')"></div>
<div class="modal-dialog" id="modal-cerrar-periodo">
<div class="modal__icon modal__icon--danger">🛑</div>
<div class="modal__title">¿Cerrar periodo fiscal?</div>
<div class="modal__desc">Se cerrará el periodo <strong style="color: var(--color-text-primary);">Marzo 2026</strong>. No podrás registrar pólizas en este periodo.</div>
<div class="modal__actions">
<button class="modal__btn modal__btn--secondary" onclick="closeModal('cerrar-periodo')">Cancelar</button>
<button class="modal__btn modal__btn--danger" onclick="closeModal('cerrar-periodo')">Cerrar periodo</button>
</div>
</div>
<script>
function openModal(id) {
const overlay = document.getElementById('overlay-' + id);
const dialog = document.getElementById('modal-' + id);
overlay.classList.remove('closing');
dialog.classList.remove('closing');
overlay.classList.add('active');
dialog.classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeModal(id) {
const overlay = document.getElementById('overlay-' + id);
const dialog = document.getElementById('modal-' + id);
overlay.classList.add('closing');
dialog.classList.add('closing');
setTimeout(() => {
overlay.classList.remove('active', 'closing');
dialog.classList.remove('active', 'closing');
document.body.style.overflow = '';
}, 200);
}
// Close on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
document.querySelectorAll('.modal-overlay.active').forEach(overlay => {
const id = overlay.id.replace('overlay-', '');
closeModal(id);
});
}
});
</script>
</body>
</html>