- 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>
421 lines
13 KiB
Markdown
421 lines
13 KiB
Markdown
# 📦 EJEMPLOS COMPLETOS Y RECURSOS
|
|
|
|
## Ejemplo 1: Campo de Color con Valor Hex
|
|
|
|
```html
|
|
<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
|
|
|
|
```html
|
|
<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
|
|
|
|
```html
|
|
<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
|
|
|
|
```html
|
|
<!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:**
|
|
```javascript
|
|
textarea.addEventListener('input', function() {
|
|
counter.textContent = this.value.length;
|
|
});
|
|
```
|
|
|
|
### El responsive no funciona
|
|
|
|
**Causa:** Falta el viewport meta tag
|
|
|
|
**Solución:**
|
|
```html
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
```
|
|
|
|
---
|
|
|
|
## Recursos
|
|
|
|
### Bootstrap 5.3.2
|
|
- Documentación: https://getbootstrap.com/docs/5.3/
|
|
- Components: https://getbootstrap.com/docs/5.3/components/
|
|
|
|
### Bootstrap Icons
|
|
- Catálogo: https://icons.getbootstrap.com/
|
|
- Búsqueda: Usar el buscador para encontrar iconos
|
|
|
|
### Google Fonts - Poppins
|
|
- Pesos usados: 400 (Regular), 500 (Medium), 600 (Semi-Bold), 700 (Bold)
|
|
|
|
---
|
|
|
|
## Volver al Índice
|
|
|
|
[← Volver al README](README.md)
|