Files
Autoparts-DB/docs/design/design-system/components/arbol-colapsable.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

606 lines
24 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 — Árbol Colapsable</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);
}
/* Tree controls */
.tree-controls {
display: flex;
gap: var(--space-2);
margin-bottom: var(--space-4);
}
.tree-controls button {
padding: var(--space-2) var(--space-4);
font-family: var(--font-body);
font-size: var(--text-body-sm);
font-weight: var(--font-weight-semibold);
background: var(--btn-ghost-bg);
color: var(--btn-ghost-text);
border: 1px solid var(--btn-ghost-border);
border-radius: var(--radius-md);
cursor: pointer;
transition: var(--transition-fast);
}
.tree-controls button:hover {
background: var(--color-surface-2);
color: var(--color-text-primary);
}
/* Tree container */
.tree-container {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
overflow: hidden;
}
/* Tree header */
.tree-header {
display: flex;
justify-content: space-between;
padding: var(--space-3) var(--space-5);
background: var(--color-surface-1);
border-bottom: 1px solid var(--color-border);
font-size: var(--text-caption);
font-weight: var(--font-weight-semibold);
color: var(--color-text-muted);
text-transform: uppercase;
letter-spacing: var(--tracking-wider);
}
/* Tree node */
.tree-node {
border-bottom: 1px solid var(--color-border);
}
.tree-node:last-child { border-bottom: none; }
.tree-row {
display: flex;
align-items: center;
padding: var(--space-3) var(--space-4);
cursor: pointer;
transition: var(--transition-fast);
gap: var(--space-2);
}
.tree-row:hover {
background: var(--color-primary-muted);
}
.tree-row.selected {
background: var(--color-primary-muted);
border-left: 3px solid var(--color-primary);
}
/* Arrow */
.tree-arrow {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 12px;
color: var(--color-text-muted);
transition: transform var(--duration-fast) var(--ease-out);
border-radius: var(--radius-sm);
}
.tree-arrow:hover {
background: var(--color-surface-3);
color: var(--color-text-primary);
}
.tree-arrow.expanded {
transform: rotate(90deg);
}
.tree-arrow.leaf {
visibility: hidden;
}
/* Account code */
.tree-code {
font-family: var(--font-mono);
font-size: var(--text-body-sm);
font-weight: var(--font-weight-semibold);
color: var(--color-text-accent);
min-width: 50px;
flex-shrink: 0;
}
/* Account name */
.tree-name {
flex: 1;
font-size: var(--text-body-sm);
color: var(--color-text-primary);
}
.tree-row.level-0 .tree-name {
font-weight: var(--font-weight-bold);
font-size: var(--text-body);
}
.tree-row.level-1 .tree-name {
font-weight: var(--font-weight-semibold);
}
/* Balance */
.tree-balance {
font-family: var(--font-mono);
font-size: var(--text-body-sm);
font-weight: var(--font-weight-semibold);
color: var(--color-text-secondary);
text-align: right;
min-width: 120px;
flex-shrink: 0;
}
.tree-row.level-0 .tree-balance {
font-weight: var(--font-weight-bold);
color: var(--color-text-primary);
font-size: var(--text-body);
}
/* Children container */
.tree-children {
overflow: hidden;
max-height: 0;
transition: max-height var(--duration-normal) var(--ease-out);
}
.tree-children.expanded {
max-height: 2000px;
}
/* Indentation */
.tree-row.level-0 { padding-left: var(--space-4); }
.tree-row.level-1 { padding-left: calc(var(--space-4) + var(--space-6)); }
.tree-row.level-2 { padding-left: calc(var(--space-4) + var(--space-6) * 2); }
/* Level-specific styling */
.tree-node.level-0 > .tree-row {
background: var(--color-surface-1);
}
.tree-node.level-0 > .tree-row:hover {
background: var(--color-primary-muted);
}
/* Summary row */
.tree-summary {
display: flex;
justify-content: space-between;
padding: var(--space-4) var(--space-5);
background: var(--color-surface-2);
border-top: 2px solid var(--color-border-accent);
font-weight: var(--font-weight-bold);
}
.tree-summary .label {
font-family: var(--font-heading);
font-size: var(--text-body);
color: var(--color-text-primary);
text-transform: uppercase;
letter-spacing: var(--tracking-wide);
}
.tree-summary .total {
font-family: var(--font-mono);
font-size: var(--text-body);
color: var(--color-text-accent);
}
/* Count badge */
.child-count {
font-size: var(--text-caption);
color: var(--color-text-disabled);
font-family: var(--font-mono);
margin-left: var(--space-1);
}
</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>Árbol Colapsable</h1>
<p class="subtitle">Catálogo de cuentas SAT con estructura jerárquica colapsable</p>
<section>
<h2>Catálogo de Cuentas</h2>
<div class="tree-controls">
<button onclick="expandAll()">Expandir Todo</button>
<button onclick="collapseAll()">Colapsar Todo</button>
</div>
<div class="tree-container" id="accountTree">
<div class="tree-header">
<span>Cuenta</span>
<span>Saldo</span>
</div>
<!-- 1000 Activo -->
<div class="tree-node level-0" data-code="1000">
<div class="tree-row level-0" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">1000</span>
<span class="tree-name">Activo <span class="child-count">(3)</span></span>
<span class="tree-balance">$1,245,800.00</span>
</div>
<div class="tree-children">
<!-- 1100 Bancos -->
<div class="tree-node level-1" data-code="1100">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">1100</span>
<span class="tree-name">Bancos <span class="child-count">(3)</span></span>
<span class="tree-balance">$485,320.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">1101</span>
<span class="tree-name">Banamex Cta. 7845</span>
<span class="tree-balance">$198,450.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">1102</span>
<span class="tree-name">BBVA Cta. 3021</span>
<span class="tree-balance">$245,870.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">1103</span>
<span class="tree-name">Banorte Cta. 5590</span>
<span class="tree-balance">$41,000.00</span>
</div>
</div>
</div>
</div>
<!-- 1200 Inventarios -->
<div class="tree-node level-1" data-code="1200">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">1200</span>
<span class="tree-name">Inventarios <span class="child-count">(2)</span></span>
<span class="tree-balance">$628,480.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">1201</span>
<span class="tree-name">Almacén General</span>
<span class="tree-balance">$520,300.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">1202</span>
<span class="tree-name">Mercancía en Tránsito</span>
<span class="tree-balance">$108,180.00</span>
</div>
</div>
</div>
</div>
<!-- 1300 Cuentas por Cobrar -->
<div class="tree-node level-1" data-code="1300">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">1300</span>
<span class="tree-name">Cuentas por Cobrar <span class="child-count">(2)</span></span>
<span class="tree-balance">$132,000.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">1301</span>
<span class="tree-name">Clientes Nacionales</span>
<span class="tree-balance">$118,500.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">1302</span>
<span class="tree-name">Deudores Diversos</span>
<span class="tree-balance">$13,500.00</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 2000 Pasivo -->
<div class="tree-node level-0" data-code="2000">
<div class="tree-row level-0" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">2000</span>
<span class="tree-name">Pasivo <span class="child-count">(2)</span></span>
<span class="tree-balance">$389,200.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-1" data-code="2100">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">2100</span>
<span class="tree-name">Proveedores <span class="child-count">(2)</span></span>
<span class="tree-balance">$285,000.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">2101</span>
<span class="tree-name">Proveedores Nacionales</span>
<span class="tree-balance">$245,000.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">2102</span>
<span class="tree-name">Proveedores Extranjeros</span>
<span class="tree-balance">$40,000.00</span>
</div>
</div>
</div>
</div>
<div class="tree-node level-1" data-code="2200">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">2200</span>
<span class="tree-name">Impuestos por Pagar <span class="child-count">(2)</span></span>
<span class="tree-balance">$104,200.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">2201</span>
<span class="tree-name">IVA Trasladado</span>
<span class="tree-balance">$72,200.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">2202</span>
<span class="tree-name">ISR por Pagar</span>
<span class="tree-balance">$32,000.00</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 3000 Capital -->
<div class="tree-node level-0" data-code="3000">
<div class="tree-row level-0" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">3000</span>
<span class="tree-name">Capital <span class="child-count">(2)</span></span>
<span class="tree-balance">$500,000.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-1">
<div class="tree-row level-1" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">3100</span>
<span class="tree-name">Capital Social</span>
<span class="tree-balance">$350,000.00</span>
</div>
</div>
<div class="tree-node level-1">
<div class="tree-row level-1" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">3200</span>
<span class="tree-name">Utilidades Acumuladas</span>
<span class="tree-balance">$150,000.00</span>
</div>
</div>
</div>
</div>
<!-- 4000 Ingresos -->
<div class="tree-node level-0" data-code="4000">
<div class="tree-row level-0" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">4000</span>
<span class="tree-name">Ingresos <span class="child-count">(2)</span></span>
<span class="tree-balance">$892,450.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-1" data-code="4100">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">4100</span>
<span class="tree-name">Ventas <span class="child-count">(2)</span></span>
<span class="tree-balance">$845,200.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">4101</span>
<span class="tree-name">Ventas Mostrador</span>
<span class="tree-balance">$562,800.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">4102</span>
<span class="tree-name">Ventas a Crédito</span>
<span class="tree-balance">$282,400.00</span>
</div>
</div>
</div>
</div>
<div class="tree-node level-1">
<div class="tree-row level-1" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">4200</span>
<span class="tree-name">Otros Ingresos</span>
<span class="tree-balance">$47,250.00</span>
</div>
</div>
</div>
</div>
<!-- 5000 Gastos -->
<div class="tree-node level-0" data-code="5000">
<div class="tree-row level-0" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">5000</span>
<span class="tree-name">Gastos <span class="child-count">(2)</span></span>
<span class="tree-balance">$536,050.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-1" data-code="5100">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">5100</span>
<span class="tree-name">Costo de Ventas <span class="child-count">(1)</span></span>
<span class="tree-balance">$421,500.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">5101</span>
<span class="tree-name">Costo Mercancía Vendida</span>
<span class="tree-balance">$421,500.00</span>
</div>
</div>
</div>
</div>
<div class="tree-node level-1" data-code="5200">
<div class="tree-row level-1" onclick="toggleNode(this)">
<span class="tree-arrow">&#9654;</span>
<span class="tree-code">5200</span>
<span class="tree-name">Gastos de Operación <span class="child-count">(3)</span></span>
<span class="tree-balance">$114,550.00</span>
</div>
<div class="tree-children">
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">5201</span>
<span class="tree-name">Sueldos y Salarios</span>
<span class="tree-balance">$68,000.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">5202</span>
<span class="tree-name">Renta Local</span>
<span class="tree-balance">$28,000.00</span>
</div>
</div>
<div class="tree-node level-2">
<div class="tree-row level-2" onclick="selectNode(this)">
<span class="tree-arrow leaf">&#9654;</span>
<span class="tree-code">5203</span>
<span class="tree-name">Servicios (Luz, Tel, Internet)</span>
<span class="tree-balance">$18,550.00</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Summary -->
<div class="tree-summary">
<span class="label">Total Activos - Pasivos</span>
<span class="total">$856,600.00</span>
</div>
</div>
</section>
<script>
function toggleNode(rowEl) {
const node = rowEl.parentElement;
const children = node.querySelector('.tree-children');
const arrow = rowEl.querySelector('.tree-arrow');
if (!children) {
selectNode(rowEl);
return;
}
const isExpanded = children.classList.contains('expanded');
if (isExpanded) {
children.classList.remove('expanded');
arrow.classList.remove('expanded');
} else {
children.classList.add('expanded');
arrow.classList.add('expanded');
}
selectNode(rowEl);
}
function selectNode(rowEl) {
// Remove previous selection
document.querySelectorAll('.tree-row.selected').forEach(el => el.classList.remove('selected'));
rowEl.classList.add('selected');
}
function expandAll() {
document.querySelectorAll('.tree-children').forEach(el => el.classList.add('expanded'));
document.querySelectorAll('.tree-arrow:not(.leaf)').forEach(el => el.classList.add('expanded'));
}
function collapseAll() {
document.querySelectorAll('.tree-children').forEach(el => el.classList.remove('expanded'));
document.querySelectorAll('.tree-arrow').forEach(el => el.classList.remove('expanded'));
}
</script>
</body>
</html>