Saltar a contenido

Estandares de Diseno de UI - Compulandia Integrador

Version: 1.0 Ultima actualizacion: Enero 2026


1. Filosofia de Diseno

Principio Fundamental: Simplicidad sobre Decoracion

El Integrador es una herramienta de trabajo para operadores que procesan cientos de productos diariamente. Cada elemento visual debe justificar su existencia reduciendo friccion o mejorando la comprension.

Inspiracion

  • Medusa Admin: Espacios amplios, tipografia clara, minimalismo funcional
  • shadcn/ui: Componentes neutros, bordes sutiles, estados claros
  • Linear: Densidad informativa sin sobrecarga visual

Objetivo Principal

Reducir la carga cognitiva del operador eliminando ruido visual innecesario y priorizando el contenido sobre la decoracion.

Anti-patrones a Evitar

  • Iconos decorativos en cada titulo/label
  • Cards anidadas dentro de cards
  • Multiples colores de fondo en contenedores
  • Bordes de colores llamativos (border-primary, border-warning)
  • Headers de cards con fondos de color
  • Alertas y badges excesivos

2. Paleta de Colores

Colores Primarios

/* Fondos */
--bg-page: #ffffff;
--bg-surface: #fafafa;
--bg-muted: #f5f5f5;

/* Textos */
--text-primary: #111827;
--text-secondary: #6b7280;
--text-muted: #9ca3af;

/* Bordes */
--border-default: #e5e7eb;
--border-subtle: #f3f4f6;

Colores de Acento (usar con moderacion)

/* Solo para acciones principales y estados */
--accent-primary: #3b82f6;      /* Boton primario */
--accent-success: #10b981;       /* Confirmaciones, estados activos */
--accent-warning: #f59e0b;       /* Advertencias leves */
--accent-danger: #ef4444;        /* Errores, acciones destructivas */

Reglas de Uso

Contexto Color Permitido
Fondo de pagina Blanco (#fff)
Fondo de card Blanco o gris muy claro (#fafafa)
Headers de card Sin fondo de color (solo texto)
Bordes de card Gris sutil (#e5e7eb) o ninguno
Texto de titulos Negro/gris oscuro (#111827)
Iconos en labels Evitar salvo navegacion
Botones primarios Azul (#3b82f6) - solo accion principal
Botones secundarios Gris/outline

Ejemplo: Antes vs Despues

Antes (evitar):

<div class="card border-primary shadow-sm">
    <div class="card-header bg-primary bg-opacity-10">
        <strong><i class="fas fa-fingerprint me-2"></i>Identificadores</strong>
    </div>
    ...
</div>

Despues (preferir):

<div class="space-y-4">
    <h3 class="text-sm font-medium text-gray-700">Identificadores</h3>
    ...
</div>


3. Contenedores y Cards

Principio: Separacion por Espaciado, no por Bordes

El espaciado vertical y horizontal debe ser suficiente para agrupar contenido relacionado sin necesidad de bordes o fondos.

Cuando Usar Cards

  • Para agrupar contenido semanticamente relacionado (ej: datos del proveedor)
  • Para secciones que pueden expandirse/colapsarse
  • Para items en listas donde cada uno es una unidad independiente

Cuando NO Usar Cards

  • Para subdividir formularios
  • Para agrupar campos de input
  • Dentro de otras cards (evitar anidamiento)

Estilos de Card Permitidos

<!-- Card simple (preferido) -->
<div class="bg-white rounded-lg border border-gray-200">
    <div class="p-4">
        <!-- contenido -->
    </div>
</div>

<!-- Card con titulo -->
<div class="bg-white rounded-lg border border-gray-200">
    <div class="px-4 py-3 border-b border-gray-100">
        <h3 class="text-sm font-medium text-gray-900">Titulo</h3>
    </div>
    <div class="p-4">
        <!-- contenido -->
    </div>
</div>

Evitar

<!-- NO: Card con borde de color -->
<div class="card border-primary">...</div>

<!-- NO: Card con header coloreado -->
<div class="card-header bg-warning bg-opacity-10">...</div>

<!-- NO: Cards anidadas -->
<div class="card">
    <div class="card">...</div> <!-- Nunca anidar -->
</div>

Escala de Bordes

/* Sutil (preferido) */
border: 1px solid #e5e7eb;

/* Muy sutil */
border: 1px solid #f3f4f6;

/* Sin borde (usar shadow sutil si es necesario) */
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);

4. Tipografia y Labels

Jerarquia de Titulos

<!-- Titulo de pagina -->
<h1 class="text-xl font-semibold text-gray-900">Titulo Principal</h1>

<!-- Titulo de seccion -->
<h2 class="text-lg font-medium text-gray-900">Seccion</h2>

<!-- Titulo de subseccion -->
<h3 class="text-sm font-medium text-gray-700">Subseccion</h3>

<!-- Label de campo -->
<label class="text-sm text-gray-600">Nombre del Campo</label>

Reglas para Titulos

  1. Sin iconos decorativos: Los iconos solo se usan para navegacion o acciones
  2. Sin ":" al final: Los titulos no terminan en dos puntos
  3. Capitalizacion: Primera letra mayuscula, resto minusculas
  4. Longitud: Breves y descriptivos

Ejemplo: Labels de Formulario

Antes (evitar):

<label class="form-label fw-bold">
    <i class="fas fa-tag text-primary me-1"></i>
    Categoria del Producto:
</label>

Despues (preferir):

<label class="text-sm text-gray-600">Categoria</label>

Texto de Ayuda

<label class="text-sm text-gray-600">Nombre del producto</label>
<input type="text" class="..." />
<p class="mt-1 text-xs text-gray-500">Maximo 100 caracteres</p>

5. Formularios

Estructura General

<form class="space-y-6">
    <!-- Seccion agrupada por proximidad, sin card -->
    <div class="space-y-4">
        <h3 class="text-sm font-medium text-gray-700">Datos basicos</h3>

        <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
                <label class="text-sm text-gray-600">Campo 1</label>
                <input type="text" class="..." />
            </div>
            <div>
                <label class="text-sm text-gray-600">Campo 2</label>
                <input type="text" class="..." />
            </div>
        </div>
    </div>

    <!-- Separador visual (espaciado) -->
    <div class="border-t border-gray-100 pt-6">
        <h3 class="text-sm font-medium text-gray-700">Otra seccion</h3>
        <!-- ... -->
    </div>
</form>

Estilos de Input

<!-- Input estandar -->
<input type="text"
       class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md
              focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500
              disabled:bg-gray-50 disabled:text-gray-500" />

<!-- Input con error -->
<input type="text"
       class="w-full px-3 py-2 text-sm border border-red-300 rounded-md
              focus:outline-none focus:ring-1 focus:ring-red-500" />
<p class="mt-1 text-xs text-red-600">Mensaje de error</p>

Botones en Formularios

<!-- Footer de formulario -->
<div class="flex justify-end gap-3 pt-6 border-t border-gray-100">
    <button type="button" class="px-4 py-2 text-sm text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50">
        Cancelar
    </button>
    <button type="submit" class="px-4 py-2 text-sm text-white bg-blue-600 rounded-md hover:bg-blue-700">
        Guardar
    </button>
</div>

Reglas de Botones

Tipo Uso Estilo
Primario Una sola accion principal por vista bg-blue-600 text-white
Secundario Acciones alternativas bg-white border text-gray-700
Peligro Acciones destructivas bg-red-600 text-white
Ghost Acciones terciarias text-gray-600 hover:text-gray-900

6. Listas y Seleccion

Listas de Items Seleccionables

Antes (evitar):

<div class="list-group">
    <label class="list-group-item list-group-item-action d-flex align-items-center
                  cursor-pointer active border-success">
        <input type="checkbox" class="form-check-input me-3">
        <div>
            <i class="fas fa-plus-circle me-2 text-success"></i>
            <strong>Opcion seleccionada</strong>
        </div>
    </label>
</div>

Despues (preferir):

<div class="space-y-2">
    <label class="flex items-center gap-3 p-3 rounded-md cursor-pointer
                  hover:bg-gray-50 [&:has(input:checked)]:bg-blue-50
                  [&:has(input:checked)]:ring-1 [&:has(input:checked)]:ring-blue-200">
        <input type="checkbox" class="w-4 h-4 text-blue-600 rounded border-gray-300">
        <span class="text-sm text-gray-900">Opcion</span>
    </label>
</div>

Estados de Seleccion

Estado Estilo
Normal bg-white
Hover bg-gray-50
Seleccionado bg-blue-50 ring-1 ring-blue-200
Deshabilitado opacity-50 cursor-not-allowed

7. Modales

Estructura Basica

<div class="fixed inset-0 z-50 flex items-center justify-center">
    <!-- Backdrop -->
    <div class="absolute inset-0 bg-black/50"></div>

    <!-- Modal -->
    <div class="relative bg-white rounded-lg shadow-xl max-w-lg w-full mx-4">
        <!-- Header (simple, sin fondo de color) -->
        <div class="px-6 py-4 border-b border-gray-100">
            <h2 class="text-lg font-medium text-gray-900">Titulo del Modal</h2>
            <p class="mt-1 text-sm text-gray-500">Descripcion opcional</p>
        </div>

        <!-- Body -->
        <div class="px-6 py-4">
            <!-- contenido -->
        </div>

        <!-- Footer -->
        <div class="px-6 py-4 border-t border-gray-100 flex justify-end gap-3">
            <button class="px-4 py-2 text-sm text-gray-700 bg-white border rounded-md">
                Cancelar
            </button>
            <button class="px-4 py-2 text-sm text-white bg-blue-600 rounded-md">
                Confirmar
            </button>
        </div>
    </div>
</div>

Reglas para Modales

  1. Header sin color de fondo: Solo texto
  2. Boton de cerrar: x en esquina superior derecha, sutil
  3. Acciones alineadas a la derecha: Cancelar primero, accion principal ultima
  4. Contenido directo: Evitar cards dentro del modal
  5. Ancho adecuado: max-w-sm para confirmaciones, max-w-lg para formularios, max-w-xl para contenido complejo

8. Estados y Feedback

Mensajes de Estado

Preferir texto sobre bloques de color:

<!-- Exito -->
<p class="text-sm text-green-600">Guardado correctamente</p>

<!-- Error -->
<p class="text-sm text-red-600">Error al procesar</p>

<!-- Advertencia -->
<p class="text-sm text-amber-600">Revisa los campos marcados</p>

<!-- Info -->
<p class="text-sm text-blue-600">Procesando...</p>

Cuando usar alertas con fondo (solo para mensajes importantes):

<div class="p-3 text-sm text-red-700 bg-red-50 rounded-md">
    Error critico que requiere atencion inmediata
</div>

Loading States

<!-- Spinner sutil -->
<div class="flex items-center gap-2 text-sm text-gray-500">
    <svg class="w-4 h-4 animate-spin" viewBox="0 0 24 24">...</svg>
    <span>Cargando...</span>
</div>

<!-- Skeleton (para contenido) -->
<div class="animate-pulse space-y-2">
    <div class="h-4 bg-gray-200 rounded w-3/4"></div>
    <div class="h-4 bg-gray-200 rounded w-1/2"></div>
</div>

Empty States

<div class="py-12 text-center">
    <p class="text-sm text-gray-500">No hay productos que mostrar</p>
    <button class="mt-4 text-sm text-blue-600 hover:text-blue-700">
        Agregar primer producto
    </button>
</div>

Badges y Tags

<!-- Badge simple -->
<span class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-100 rounded">
    Pendiente
</span>

<!-- Badge con estado -->
<span class="px-2 py-1 text-xs font-medium text-green-700 bg-green-100 rounded">
    Activo
</span>

9. Espaciado

Escala Base (4px)

/* Espaciado */
--space-1: 0.25rem;  /* 4px */
--space-2: 0.5rem;   /* 8px */
--space-3: 0.75rem;  /* 12px */
--space-4: 1rem;     /* 16px */
--space-6: 1.5rem;   /* 24px */
--space-8: 2rem;     /* 32px */
--space-12: 3rem;    /* 48px */

Uso por Contexto

Contexto Espaciado
Entre elementos de lista space-y-2 (8px)
Entre campos de formulario space-y-4 (16px)
Entre secciones space-y-6 (24px) o space-y-8 (32px)
Padding interno de card p-4 (16px) o p-6 (24px)
Gap en grids gap-4 (16px)

Separadores

Preferir espaciado sobre lineas:

<!-- Con espaciado (preferido) -->
<div class="space-y-8">
    <section>...</section>
    <section>...</section>
</div>

<!-- Con linea sutil (cuando es necesario) -->
<div class="space-y-6">
    <section>...</section>
    <div class="border-t border-gray-100"></div>
    <section>...</section>
</div>

10. Ejemplos Comparativos

Ejemplo 1: Card de Informacion

Antes:

<div class="card border-primary shadow-sm mb-2">
    <div class="card-header bg-primary bg-opacity-10">
        <strong><i class="fas fa-box me-2"></i>Producto del Proveedor</strong>
    </div>
    <div class="card-body">
        <div class="row">
            <div class="col-md-4">
                <strong>SKU:</strong> ABC123
            </div>
        </div>
    </div>
</div>

Despues:

<div class="bg-white rounded-lg border border-gray-200 p-4">
    <h3 class="text-sm font-medium text-gray-900 mb-3">Producto del proveedor</h3>
    <dl class="grid grid-cols-3 gap-4 text-sm">
        <div>
            <dt class="text-gray-500">SKU</dt>
            <dd class="font-medium text-gray-900">ABC123</dd>
        </div>
    </dl>
</div>

Ejemplo 2: Seccion de Formulario

Antes:

<div class="card border-primary shadow-sm mb-2">
    <div class="card-body p-2">
        <h6 class="card-title text-primary mb-2 fs-6">
            <i class="fas fa-fingerprint me-1"></i> Identificadores
        </h6>
        <div class="row g-1">
            <div class="col-md-3">
                <label class="form-label"><i class="fas fa-barcode"></i> SKU</label>
                <input type="text" class="form-control form-control-sm">
            </div>
        </div>
    </div>
</div>

Despues:

<div class="space-y-4">
    <h3 class="text-sm font-medium text-gray-700">Identificadores</h3>
    <div class="grid grid-cols-4 gap-4">
        <div>
            <label class="block text-sm text-gray-600 mb-1">SKU</label>
            <input type="text" class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md">
        </div>
    </div>
</div>

Ejemplo 3: Header de Modal

Antes:

<div class="modal-header bg-light">
    <div class="d-flex flex-column">
        <h5 class="modal-title mb-1">
            <i class="fas fa-box-open me-2"></i>
            Confirmar Producto Pendiente
        </h5>
        <small class="text-muted">Paso 1 de 5</small>
    </div>
    <button type="button" class="btn-close"></button>
</div>

Despues:

<div class="px-6 py-4 border-b border-gray-100">
    <div class="flex items-start justify-between">
        <div>
            <h2 class="text-lg font-medium text-gray-900">Confirmar producto pendiente</h2>
            <p class="mt-1 text-sm text-gray-500">Paso 1 de 5</p>
        </div>
        <button class="p-1 text-gray-400 hover:text-gray-600 rounded">
            <svg class="w-5 h-5">...</svg>
        </button>
    </div>
</div>


11. Checklist de Revision

Antes de hacer merge de un PR con cambios de UI, verificar:

Colores

  • [ ] No hay border-primary, border-warning, etc. en cards
  • [ ] No hay bg-*-opacity-10 en headers
  • [ ] Los fondos son blanco o gris muy claro
  • [ ] Los colores de acento solo se usan para acciones y estados

Estructura

  • [ ] No hay cards anidadas
  • [ ] Las secciones se separan por espaciado, no por bordes
  • [ ] Los formularios no estan subdivididos en cards

Tipografia

  • [ ] Los titulos no tienen iconos decorativos
  • [ ] Los labels son simples (sin iconos, sin ":")
  • [ ] Se respeta la jerarquia de tamanos

Componentes

  • [ ] Solo hay un boton primario por vista/modal
  • [ ] Los modales tienen header simple (sin fondo)
  • [ ] Las listas seleccionables no usan cards individuales

Espaciado

  • [ ] Se usa la escala de 4px
  • [ ] El espaciado es consistente entre secciones
  • [ ] No hay separadores visuales innecesarios

12. Migracion Gradual

Este documento establece el estandar para nuevos desarrollos. La migracion de componentes existentes se hara de forma gradual siguiendo estas prioridades:

  1. Alta prioridad: Modales y formularios de uso frecuente
  2. Media prioridad: Vistas de listado y detalle
  3. Baja prioridad: Vistas administrativas de uso ocasional

Al modificar un componente existente por cualquier razon, aprovechar para alinearlo con estos estandares.


Referencias