Receta
Dashboard
Starter
Charts
Sidebar
Receta: App Starter / Dashboard
Plantilla base completa con navbar, sidebar, KPIs, tabla de datos, gráficos, timeline y estado vacío. El punto de partida ideal para cualquier aplicación.
Código fuente del template
template.html
{% extends "showcase/base_empty.html" %}
{% load components_ui %}
{% block title %}Receta: App Starter — Django Components UI{% endblock %}
{% block content %}
<!--
╔══════════════════════════════════════════════════════╗
║ PLANTILLA DE INICIO — django-components-ui ║
║ Copia este archivo como base para tu aplicación ║
║ Personaliza los menu_items, el título y el contenido║
╚══════════════════════════════════════════════════════╝
-->
<div class="h-full flex flex-col overflow-hidden bg-gray-50" id="app-root">
<!-- ══ NAVBAR ══
comp_navbar renderiza barra superior con logo, usuario y menú móvil.
Pasa show_user=True para mostrar el avatar del usuario de sesión. -->
<div class="z-30 flex-shrink-0">
{% comp_navbar title="Mi Aplicación" show_user=True %}
</div>
<div class="flex flex-1 overflow-hidden">
<!-- ══ SIDEBAR ══
Pasa menu_items desde la view. Cada item puede tener 'children' para submenús.
is_open controla si empieza expandido o colapsado. -->
<div id="sidebar-wrapper"
class="flex-shrink-0 bg-gray-900 hidden lg:block shadow-xl relative z-20 transition-all duration-300">
{% comp_sidebar_menu menu_items=menu_items title="Mi App" is_open=True footer_text="v1.0 — Powered by django-components-ui" %}
</div>
<!-- ══ MAIN CONTENT ══ -->
<main class="flex-1 overflow-y-auto focus:outline-none" tabindex="-1">
<div class="p-6 lg:p-10 space-y-8 max-w-7xl mx-auto">
<!-- ── Page Header ─────────────────────────────────── -->
<header class="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div>
{% comp_title text="Dashboard" level=1 %}
<p class="text-gray-500 text-sm mt-1 font-medium">
Resumen del sistema — {{ fecha_actual }}
</p>
</div>
<div class="flex items-center gap-2.5">
<!-- Acción principal de la página -->
{% comp_button text="Nueva acción" color="primary" icon="PlusIcon" onclick="alert('¡Personaliza esta acción!')" %}
</div>
</header>
<!-- ── KPI Cards ────────────────────────────────────── -->
<section>
<h2 class="text-xs font-black text-gray-400 uppercase tracking-widest mb-4">Resumen</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4">
{% for kpi in kpis %}
{% comp_data_card title=kpi.title value=kpi.value trend=kpi.trend color=kpi.color icon=kpi.icon sparkline_data=kpi.sparkline %}
{% endfor %}
</div>
</section>
<!-- ── Main Grid ────────────────────────────────────── -->
<div class="grid grid-cols-1 xl:grid-cols-3 gap-6">
<!-- Tabla principal (ocupa 2/3) -->
<div class="xl:col-span-2 space-y-4">
<div class="flex items-center justify-between">
<h2 class="text-xs font-black text-gray-400 uppercase tracking-widest">Datos Recientes</h2>
<a href="#" class="text-xs text-primary-600 hover:text-primary-700 font-semibold">Ver todo →</a>
</div>
{% comp_tabla id="main-table" data_url="/api/mock-data/" columns=tabla_columnas searchable=True page_size=8 height="380px" %}
</div>
<!-- Panel lateral derecho (ocupa 1/3) -->
<div class="space-y-6">
<!-- Estadísticas rápidas -->
<div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-5">
{% comp_stat_list title="Métricas Clave" items=stat_items %}
</div>
<!-- Actividad reciente -->
<div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-5">
<h3 class="text-xs font-black text-gray-400 uppercase tracking-widest mb-4">Actividad Reciente</h3>
{% comp_timeline items=timeline_items %}
</div>
</div>
</div>
<!-- ── Sección con estado vacío (ejemplo) ──────────── -->
<section class="bg-white rounded-2xl border border-gray-200 shadow-sm">
<div class="px-6 py-4 border-b border-gray-100 flex items-center justify-between">
<h2 class="text-sm font-bold text-gray-700 flex items-center gap-2">
{% comp_icon name="BellIcon" size="w-4 h-4 text-warning-500" %}
Notificaciones
</h2>
{% comp_badge text="0 nuevas" color="warning" %}
</div>
<!-- comp_empty_state: muestra cuando no hay datos -->
{% comp_empty_state title="Sin notificaciones pendientes" description="Cuando haya alertas o mensajes nuevos aparecerán aquí." icon="BellSlashIcon" color="warning" action_text="Configurar alertas" action_onclick="alert('Ir a configuración de alertas')" %}
</section>
<!-- ── Gráfico ──────────────────────────────────────── -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-6">
<h3 class="text-sm font-bold text-gray-800 mb-4">Evolución Mensual</h3>
{% comp_chart id="starter-chart" type="line" data=chart_data height="220px" %}
</div>
<div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-6">
<h3 class="text-sm font-bold text-gray-800 mb-4">Distribución por Categoría</h3>
{% comp_chart id="starter-donut" type="doughnut" data=donut_data height="220px" %}
</div>
</div>
<div class="h-8"></div>
</div>
</main>
</div>
</div>
<!-- ══ TIP PARA DESARROLLADORES ══ -->
<div id="dev-tip"
class="fixed bottom-4 right-4 z-50 max-w-xs bg-gray-900 text-white rounded-2xl p-4 shadow-2xl text-xs leading-relaxed">
<div class="flex items-start gap-2.5 mb-2">
{% comp_icon name="CodeBracketIcon" size="w-4 h-4 text-primary-400" %}
<span class="font-bold text-primary-400">Plantilla de inicio</span>
<button onclick="document.getElementById('dev-tip').remove()"
class="ml-auto text-gray-500 hover:text-gray-300 transition-colors">✕</button>
</div>
<p class="text-gray-400">Copia esta página como base. Sustituye los datos de contexto en tu <code class="text-primary-300">views.py</code> y personaliza el contenido.</p>
</div>
{% endblock %}
Vista previa
Pantalla completa
/recipes/starter/