Files
roi-theme/_planificacion/01-design-system/15-EJEMPLOS-COMPLETOS.md
FrankZamora 0f6387ab46 refactor: reorganizar openspec y planificacion con spec recaptcha
- renombrar openspec/ a _openspec/ (carpeta auxiliar)
- mover specs de features a changes/
- crear specs base: arquitectura-limpia, estandares-codigo, nomenclatura
- migrar _planificacion/ con design-system y roi-theme-template
- agregar especificacion recaptcha anti-spam (proposal, tasks, spec)
- corregir rutas y referencias en todas las specs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 15:30:45 -06:00

13 KiB

📦 EJEMPLOS COMPLETOS Y RECURSOS

Ejemplo 1: Campo de Color con Valor Hex

<div class="col-6">
    <label for="primaryColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
        <i class="bi bi-paint-bucket me-1" style="color: #FF8600;"></i>
        Color Primario
    </label>
    <input type="color" id="primaryColor"
           class="form-control form-control-color w-100"
           value="#0E2337"
           title="Seleccionar color primario">
    <small class="text-muted d-block mt-1" id="primaryColorValue">#0E2337</small>
</div>

<script>
const colorInput = document.getElementById('primaryColor');
const colorValue = document.getElementById('primaryColorValue');

colorInput.addEventListener('input', function() {
    colorValue.textContent = this.value.toUpperCase();
    updatePreview();
});
</script>

Ejemplo 2: Campo de Texto con Icono de Bootstrap

<div class="mb-2">
    <label for="iconClass" class="form-label small mb-1 fw-semibold" style="color: #495057;">
        <i class="bi bi-emoji-smile me-1" style="color: #FF8600;"></i>
        Clase del icono
        <span class="badge bg-secondary" style="font-size: 0.65rem;">Bootstrap Icons</span>
    </label>
    <input type="text" id="iconClass"
           class="form-control form-control-sm"
           placeholder="bi bi-star-fill"
           value="bi bi-megaphone-fill"
           maxlength="50">
    <small class="text-muted d-block mt-1">
        <i class="bi bi-info-circle me-1"></i>
        Ver: <a href="https://icons.getbootstrap.com/" target="_blank"
                class="text-decoration-none" style="color: #FF8600;">
            Bootstrap Icons <i class="bi bi-box-arrow-up-right"></i>
        </a>
    </small>
</div>

Ejemplo 3: Textarea con Contador y Progress Bar

<div class="mb-2">
    <label for="description" class="form-label small mb-1 fw-semibold" style="color: #495057;">
        <i class="bi bi-chat-left-text me-1" style="color: #FF8600;"></i>
        Descripción <span class="text-danger">*</span>
        <span class="float-end text-muted">
            <span id="descriptionCount" class="fw-bold">0</span>/250
        </span>
    </label>
    <textarea id="description"
              class="form-control form-control-sm"
              rows="3"
              maxlength="250"
              placeholder="Escribe una descripción atractiva..."
              required></textarea>
    <div class="progress mt-1" style="height: 3px;">
        <div id="descriptionProgress"
             class="progress-bar"
             role="progressbar"
             style="width: 0%; background-color: #FF8600;"
             aria-valuenow="0"
             aria-valuemin="0"
             aria-valuemax="250"></div>
    </div>
</div>

<script>
const textarea = document.getElementById('description');
const counter = document.getElementById('descriptionCount');
const progress = document.getElementById('descriptionProgress');

textarea.addEventListener('input', function() {
    const length = this.value.length;
    const maxLength = 250;
    const percentage = (length / maxLength * 100);

    counter.textContent = length;
    progress.style.width = percentage + '%';
    progress.setAttribute('aria-valuenow', length);

    // Cambiar color según el uso
    if (percentage > 90) {
        progress.style.backgroundColor = '#dc3545'; // Rojo
    } else if (percentage > 75) {
        progress.style.backgroundColor = '#ffc107'; // Amarillo
    } else {
        progress.style.backgroundColor = '#FF8600'; // Orange
    }

    updatePreview();
});
</script>

Template Básico Completo

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Admin: [Component Name]</title>

    <!-- Bootstrap 5.3.2 -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/Css/bootstrap.min.css" rel="stylesheet">

    <!-- Bootstrap Icons -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/Font/bootstrap-icons.min.css">

    <!-- Poppins Font -->
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">

    <!-- CSS del proyecto principal -->
    <link rel="stylesheet" href="../../Css/style.css">

    <style>
    body {
        font-family: 'Poppins', sans-serif;
        background-color: #f8f9fa;
    }

    /* Fix WordPress .card max-width */
    body .card {
        max-width: none !important;
    }

    /* Fix WordPress switches */
    body .form-switch .form-check-input[type="checkbox"]::before,
    body .form-switch .form-check-input[type="checkbox"]::after {
        content: none !important;
        display: none !important;
    }

    body .form-switch .form-check-input[type="checkbox"] {
        background-size: contain !important;
        background-repeat: no-repeat !important;
        background-position: left center !important;
    }

    body .form-switch .form-check-input[type="checkbox"]:checked {
        background-position: right center !important;
    }

    /* Fix alineación vertical switches */
    .form-check.form-switch {
        display: flex !important;
        align-items: center !important;
    }

    .form-switch .form-check-label {
        line-height: 16px !important;
        margin-top: 0 !important;
    }

    /* Responsive */
    @media (max-width: 991px) {
        .tab-header { padding: 0.75rem; }
    }
    </style>
</head>
<body>
    <div class="container-fluid py-4" style="max-width: 1400px;">
        <!-- Header del Tab -->
        <div class="rounded p-4 mb-4 shadow text-white"
             style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%);
                    border-left: 4px solid #FF8600;">
            <div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
                <div>
                    <h3 class="h4 mb-1 fw-bold">
                        <i class="bi bi-[icon] me-2" style="color: #FF8600;"></i>
                        Configuración de [Component]
                    </h3>
                    <p class="mb-0 small" style="opacity: 0.85;">
                        [Descripción del componente]
                    </p>
                </div>
                <button type="button" class="btn btn-sm btn-outline-light" id="resetDefaults">
                    <i class="bi bi-arrow-counterclockwise me-1"></i>
                    Restaurar valores por defecto
                </button>
            </div>
        </div>

        <!-- Grid de Contenido -->
        <div class="row g-3">
            <!-- Columna Izquierda -->
            <div class="col-lg-6">
                <div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
                    <div class="card-body">
                        <h5 class="fw-bold mb-3" style="color: #1e3a5f;">
                            <i class="bi bi-palette me-2" style="color: #FF8600;"></i>
                            Sección 1
                        </h5>
                        <!-- Campos -->
                    </div>
                </div>
            </div>

            <!-- Columna Derecha -->
            <div class="col-lg-6">
                <div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
                    <div class="card-body">
                        <h5 class="fw-bold mb-3" style="color: #1e3a5f;">
                            <i class="bi bi-gear me-2" style="color: #FF8600;"></i>
                            Sección 2
                        </h5>
                        <!-- Campos -->
                    </div>
                </div>
            </div>

            <!-- Vista Previa -->
            <div class="col-12">
                <div class="card shadow-sm mb-3" style="border-left: 4px solid #FF8600;">
                    <div class="card-body">
                        <h5 class="fw-bold mb-3" style="color: #1e3a5f;">
                            <i class="bi bi-eye me-2" style="color: #FF8600;"></i>
                            Vista Previa en Tiempo Real
                        </h5>

                        <div id="componentPreview" class="[component-class]">
                            <!-- HTML idéntico al front-end -->
                        </div>

                        <div class="d-flex justify-content-between align-items-center mt-3">
                            <small class="text-muted">
                                <i class="bi bi-info-circle me-1"></i>
                                Los cambios se reflejan en tiempo real
                            </small>
                            <div class="btn-group btn-group-sm" role="group">
                                <button type="button" class="btn btn-outline-secondary active" id="previewDesktop">
                                    <i class="bi bi-display"></i> Desktop
                                </button>
                                <button type="button" class="btn btn-outline-secondary" id="previewMobile">
                                    <i class="bi bi-phone"></i> Mobile
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Bootstrap JS -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/Js/bootstrap.bundle.min.js"></script>

    <script>
    document.addEventListener('DOMContentLoaded', function() {
        console.log('✅ Admin Panel cargado');
        loadConfig();
        updatePreview();
        initializeEventListeners();
    });

    function initializeEventListeners() {
        // Conectar event listeners
    }

    function updatePreview() {
        // Actualizar vista previa
    }

    function saveConfig() {
        // Guardar configuración
    }

    function loadConfig() {
        // Cargar configuración
    }

    function resetToDefaults() {
        if (!confirm('¿Estás seguro de restaurar los valores por defecto?')) {
            return;
        }
        // Reset a defaults
    }
    </script>
</body>
</html>

Checklist de Implementación

Antes de Empezar

  • Leer este manual completo
  • Revisar la librería de componentes HTML (../componentes-html-bootstrap/)
  • Identificar qué campos necesita el componente
  • Determinar si necesita vista previa en tiempo real

Estructura HTML

  • Crear el header del tab con gradiente navy + border orange
  • Incluir botón "Restaurar valores por defecto"
  • Organizar campos en grid de 2 columnas (col-lg-6)
  • Agrupar campos relacionados en cards con border-left navy
  • Agregar card de vista previa con border-left orange

Formularios

  • Todos los labels tienen icono orange
  • Labels importantes tienen fw-semibold
  • Campos requeridos tienen <span class="text-danger">*</span>
  • Color pickers muestran valor hex debajo
  • Textareas tienen contador de caracteres + progress bar
  • Selects usan .form-select-sm
  • Inputs usan .form-control-sm
  • Switches tienen icono + strong en label

Vista Previa

  • HTML de preview es IDÉNTICO al del front-end
  • Se usa clase real del componente (ej: .top-notification-bar)
  • NO hay inline styles que sobreescriban el CSS real
  • Se cargan los mismos archivos CSS que el front-end
  • Botones Desktop/Mobile funcionales

JavaScript

  • Función updatePreview() implementada
  • Función saveConfig() guarda en localStorage/JSON
  • Función loadConfig() carga al iniciar
  • Función resetToDefaults() restaura valores
  • Event listeners en todos los campos
  • Color pickers actualizan el valor hex
  • Textareas actualizan contador + progress bar

CSS

  • Fix WordPress .card { max-width: none !important; }
  • Fix WordPress switches (pseudo-elementos)
  • Fix alineación vertical switches
  • Responsive breakpoints configurados

Troubleshooting

La vista previa no se ve igual al front-end

Causa: Inline styles sobreescribiendo el CSS real

Solución:

  1. Verificar que NO haya inline styles en el HTML del preview
  2. Verificar que se carga ../../Css/style.css
  3. Usar solo la clase del componente real
  4. Si es necesario, agregar CSS con !important SOLO para el border

Los colores no coinciden

Causa: No se están usando los valores correctos

Solución:

  1. Usar valores hex exactos: #0E2337, #FF8600, etc.
  2. Verificar que style.css define las variables :root

El contador de caracteres no funciona

Causa: Event listener no conectado

Solución:

textarea.addEventListener('input', function() {
    counter.textContent = this.value.length;
});

El responsive no funciona

Causa: Falta el viewport meta tag

Solución:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Recursos

Bootstrap 5.3.2

Bootstrap Icons

Google Fonts - Poppins

  • Pesos usados: 400 (Regular), 500 (Medium), 600 (Semi-Bold), 700 (Bold)

Volver al Índice

← Volver al README