{# ============================================ UNIFIED COMPONENT LIBRARY - Tailwind CSS All UI components in one place for consistency ============================================ #} {# ============================================ PAGE HEADERS ============================================ #} {% macro page_header(icon_class, title_text, subtitle_text=None, actions_html=None, breadcrumbs=None) %}
{% if breadcrumbs %}
{{ breadcrumb_nav(breadcrumbs) }}
{% endif %}
{% if icon_class %}
{% endif %}

{{ _(title_text) }}

{% if subtitle_text %}

{{ _(subtitle_text) }}

{% endif %}
{% if actions_html %}
{{ actions_html|safe }}
{% endif %}
{% endmacro %} {# ============================================ BREADCRUMBS ============================================ #} {% macro breadcrumb_nav(items) %} {% endmacro %} {# ============================================ STAT CARDS ============================================ #} {% macro stat_card(title, value, icon_class, color="primary", trend=None, subtitle=None) %}

{{ _(title) }}

{{ value }}

{% if subtitle %}

{{ _(subtitle) }}

{% endif %} {% if trend %}
{% if trend > 0 %} {{ "%.1f"|format(trend) }}% {% elif trend < 0 %} {{ "%.1f"|format(trend|abs) }}% {% else %} 0% {% endif %}
{% endif %}
{% endmacro %} {# ============================================ EMPTY STATES ============================================ #} {% macro empty_state(icon_class, title, message, actions_html=None, type="default", illustration=None) %} {% set type_colors = { 'default': 'primary', 'no-data': 'gray-500', 'no-results': 'amber-500', 'error': 'red-500', 'success': 'green-500', 'info': 'blue-500' } %} {% set color = type_colors.get(type, 'primary') %}
{% if illustration %}
{{ illustration|safe }}
{% else %}
{% endif %}

{{ _(title) }}

{{ _(message) }}

{% if actions_html %}
{{ actions_html|safe }}
{% endif %}
{% endmacro %} {# ============================================ LOADING STATES ============================================ #} {% macro loading_spinner(size="md", text=None, context=None) %} {% set size_classes = {'sm': 'w-6 h-6', 'md': 'w-10 h-10', 'lg': 'w-16 h-16'} %} {% set context_icons = { 'export': 'fas fa-download', 'delete': 'fas fa-trash', 'save': 'fas fa-save', 'load': 'fas fa-spinner', 'bulk': 'fas fa-tasks' } %}
{% if context and context in context_icons %}
{% else %}
{% endif %} {% if text %}

{{ _(text) }}

{% endif %}
{% endmacro %} {% macro progress_indicator(text, percentage=None, show_percentage=True) %}
{% if text %}
{{ _(text) }} {% if show_percentage and percentage is not none %} {{ percentage }}% {% endif %}
{% endif %}
{% endmacro %} {% macro skeleton_card() %}
{% endmacro %} {% macro skeleton_table(rows=5, cols=4, show_checkbox=False) %}
{% if show_checkbox %}
{% endif %} {% for j in range(cols) %}
{% endfor %}
{% for i in range(rows) %}
{% if show_checkbox %}
{% endif %} {% for j in range(cols) %}
{% endfor %}
{% endfor %}
{% endmacro %} {% macro skeleton_list(items=5) %}
{% for i in range(items) %}
{% endfor %}
{% endmacro %} {# ============================================ BADGES & CHIPS ============================================ #} {% macro badge(text, color="primary", icon=None, size="md") %} {% set size_classes = { 'sm': 'text-xs px-2 py-0.5', 'md': 'text-sm px-3 py-1', 'lg': 'text-base px-4 py-1.5' } %} {% if icon %}{% endif %} {{ _(text) }} {% endmacro %} {# ============================================ BUTTONS ============================================ #} {% macro button(text, url=None, icon_class=None, variant="primary", size="md", type="button", attributes="", loading=False) %} {% set size_classes = { 'sm': 'px-3 py-1.5 text-sm', 'md': 'px-4 py-2', 'lg': 'px-6 py-3 text-lg' } %} {% set variant_classes = { 'primary': 'bg-primary text-white hover:bg-primary/90', 'secondary': 'bg-gray-500 text-white hover:bg-gray-600', 'success': 'bg-green-600 text-white hover:bg-green-700', 'danger': 'bg-red-600 text-white hover:bg-red-700', 'warning': 'bg-amber-500 text-white hover:bg-amber-600', 'outline': 'border-2 border-primary text-primary hover:bg-primary hover:text-white', 'ghost': 'text-primary hover:bg-primary/10' } %} {% set tag = 'a' if url else 'button' %} <{{ tag }} {% if url %}href="{{ url }}"{% endif %} {% if type and tag == 'button' %}type="{{ type }}"{% endif %} class="inline-flex items-center justify-center {{ size_classes.get(size, size_classes['md']) }} {{ variant_classes.get(variant, variant_classes['primary']) }} rounded-lg font-medium transition-all duration-200 hover:shadow-md focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed" {{ attributes|safe }} {% if loading %}disabled{% endif %} > {% if loading %} {% elif icon_class %} {% endif %} {{ _(text) }} {% endmacro %} {# ============================================ FILTER BADGES ============================================ #} {% macro filter_badge(label, value, remove_url) %} {{ _(label) }}: {{ value }} {% endmacro %} {# ============================================ PROGRESS BARS ============================================ #} {% macro progress_bar(current, total, color="primary", show_label=True, animate=True) %} {% set percentage = (current / total * 100) if total > 0 else 0 %}
{% if show_label %}
{{ current }} / {{ total }} {{ "%.0f"|format(percentage) }}%
{% endif %}
{% if animate %}
{% endif %}
{% endmacro %} {# ============================================ ALERTS & NOTIFICATIONS ============================================ #} {% macro alert(message, type="info", icon=None, dismissible=True) %} {% set type_config = { 'info': {'bg': 'blue-50', 'border': 'blue-200', 'text': 'blue-800', 'icon': 'fa-info-circle'}, 'success': {'bg': 'green-50', 'border': 'green-200', 'text': 'green-800', 'icon': 'fa-check-circle'}, 'warning': {'bg': 'amber-50', 'border': 'amber-200', 'text': 'amber-800', 'icon': 'fa-exclamation-triangle'}, 'error': {'bg': 'red-50', 'border': 'red-200', 'text': 'red-800', 'icon': 'fa-exclamation-circle'} } %} {% set config = type_config.get(type, type_config['info']) %} {% endmacro %} {# ============================================ MODAL WRAPPER ============================================ #} {% macro modal(id, title, content_html, footer_html=None, size="md") %} {% set size_classes = { 'sm': 'max-w-md', 'md': 'max-w-lg', 'lg': 'max-w-2xl', 'xl': 'max-w-4xl', 'full': 'max-w-full mx-4' } %} {% endmacro %} {# ============================================ CONFIRMATION DIALOG ============================================ #} {% macro confirm_dialog(id, title, message, confirm_text="Confirm", cancel_text="Cancel", confirm_class="danger") %} {% endmacro %} {# ============================================ DATA TABLE WRAPPER ============================================ #} {% macro data_table(headers, rows, actions=None, empty_message="No data available", sortable=True) %}
{% for header in headers %} {% endfor %} {% if actions %} {% endif %} {% if rows %} {{ rows|safe }} {% else %} {% endif %}
{{ _(header.label) }} {% if sortable %} {% endif %}
{{ _('Actions') }}
{{ _(empty_message) }}
{% endmacro %} {# ============================================ TABS ============================================ #} {% macro tabs(items, active_tab) %}
{% endmacro %} {# ============================================ TIMELINE ITEM ============================================ #} {% macro timeline_item(icon, title, description, time, color="primary", is_last=False) %}
{% if not is_last %}
{% endif %}

{{ _(title) }}

{{ _(description) }}

{{ time }}
{% endmacro %}