Add comprehensive macro library in app/templates/shared/macros/: - pagination.html: pagination(), pagination_simple() - alerts.html: loading_state(), error_state(), alert(), toast() - badges.html: badge(), status_badge(), role_badge(), severity_badge() - buttons.html: btn(), btn_primary(), btn_danger(), action_button() - forms.html: form_input(), form_select(), form_textarea(), form_toggle() - tables.html: table_wrapper(), table_header(), table_empty_state() - cards.html: stat_card(), card(), info_card(), filter_card() - headers.html: page_header(), section_header(), breadcrumbs() These macros standardize TailAdmin styling with Alpine.js integration and dark mode support, reducing code duplication across templates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
179 lines
6.8 KiB
HTML
179 lines
6.8 KiB
HTML
{#
|
|
Alert & Loading State Macros
|
|
============================
|
|
Reusable components for alerts, loading states, and notifications.
|
|
|
|
Usage:
|
|
{% from 'shared/macros/alerts.html' import loading_state, error_state, alert %}
|
|
{{ loading_state('Loading vendors...') }}
|
|
{{ error_state('Error loading data', 'error') }}
|
|
{{ alert('success', 'Success!', 'Your changes have been saved.') }}
|
|
#}
|
|
|
|
|
|
{#
|
|
Loading State
|
|
=============
|
|
Shows a centered loading spinner with message.
|
|
|
|
Parameters:
|
|
- message: Text to display below the spinner (default: 'Loading...')
|
|
- show_condition: Alpine.js condition for x-show (default: 'loading')
|
|
#}
|
|
{% macro loading_state(message='Loading...', show_condition='loading') %}
|
|
<div x-show="{{ show_condition }}" class="text-center py-12">
|
|
<span x-html="$icon('spinner', 'inline w-8 h-8 text-purple-600')"></span>
|
|
<p class="mt-2 text-gray-600 dark:text-gray-400">{{ message }}</p>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
|
|
{#
|
|
Error State
|
|
===========
|
|
Shows an error message box with icon.
|
|
|
|
Parameters:
|
|
- title: Error title (default: 'Error')
|
|
- error_var: Alpine.js variable containing error message (default: 'error')
|
|
- show_condition: Alpine.js condition for x-show (default: 'error && !loading')
|
|
#}
|
|
{% macro error_state(title='Error', error_var='error', show_condition='error && !loading') %}
|
|
<div x-show="{{ show_condition }}" class="mb-6 p-4 bg-red-100 border border-red-400 text-red-700 rounded-lg flex items-start">
|
|
<span x-html="$icon('exclamation', 'w-5 h-5 mr-3 mt-0.5 flex-shrink-0')"></span>
|
|
<div>
|
|
<p class="font-semibold">{{ title }}</p>
|
|
<p class="text-sm" x-text="{{ error_var }}"></p>
|
|
</div>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
|
|
{#
|
|
Alert
|
|
=====
|
|
A versatile alert component for different message types.
|
|
|
|
Parameters:
|
|
- type: 'success' | 'warning' | 'error' | 'info' (default: 'info')
|
|
- title: Alert title
|
|
- message: Alert message (can be Alpine.js expression with x-text)
|
|
- dismissible: Whether the alert can be dismissed (default: false)
|
|
- show_condition: Alpine.js condition for x-show (default: 'true')
|
|
- icon: Override the default icon (optional)
|
|
#}
|
|
{% macro alert(type='info', title='', message='', dismissible=false, show_condition='true', icon=none) %}
|
|
{% set colors = {
|
|
'success': 'bg-green-100 border-green-400 text-green-700 dark:bg-green-900 dark:border-green-700 dark:text-green-200',
|
|
'warning': 'bg-yellow-100 border-yellow-400 text-yellow-700 dark:bg-yellow-900 dark:border-yellow-700 dark:text-yellow-200',
|
|
'error': 'bg-red-100 border-red-400 text-red-700 dark:bg-red-900 dark:border-red-700 dark:text-red-200',
|
|
'info': 'bg-blue-100 border-blue-400 text-blue-700 dark:bg-blue-900 dark:border-blue-700 dark:text-blue-200'
|
|
} %}
|
|
{% set icons = {
|
|
'success': 'check-circle',
|
|
'warning': 'exclamation',
|
|
'error': 'exclamation-circle',
|
|
'info': 'information-circle'
|
|
} %}
|
|
{% set alert_icon = icon if icon else icons[type] %}
|
|
<div x-show="{{ show_condition }}" class="mb-4 p-4 border rounded-lg flex items-start {{ colors[type] }}" role="alert">
|
|
<span x-html="$icon('{{ alert_icon }}', 'w-5 h-5 mr-3 mt-0.5 flex-shrink-0')"></span>
|
|
<div class="flex-1">
|
|
{% if title %}
|
|
<p class="font-semibold">{{ title }}</p>
|
|
{% endif %}
|
|
{% if message %}
|
|
<p class="text-sm">{{ message }}</p>
|
|
{% endif %}
|
|
</div>
|
|
{% if dismissible %}
|
|
<button @click="$el.parentElement.remove()" class="ml-4 hover:opacity-75 focus:outline-none" aria-label="Dismiss">
|
|
<span x-html="$icon('x', 'w-4 h-4')"></span>
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
|
|
{#
|
|
Alert with Alpine.js binding
|
|
============================
|
|
Alert where the message comes from an Alpine.js variable.
|
|
|
|
Parameters:
|
|
- type: 'success' | 'warning' | 'error' | 'info' (default: 'info')
|
|
- title: Alert title
|
|
- message_var: Alpine.js variable for the message
|
|
- show_condition: Alpine.js condition for x-show (default: 'true')
|
|
#}
|
|
{% macro alert_dynamic(type='info', title='', message_var='message', show_condition='true') %}
|
|
{% set colors = {
|
|
'success': 'bg-green-100 border-green-400 text-green-700 dark:bg-green-900 dark:border-green-700 dark:text-green-200',
|
|
'warning': 'bg-yellow-100 border-yellow-400 text-yellow-700 dark:bg-yellow-900 dark:border-yellow-700 dark:text-yellow-200',
|
|
'error': 'bg-red-100 border-red-400 text-red-700 dark:bg-red-900 dark:border-red-700 dark:text-red-200',
|
|
'info': 'bg-blue-100 border-blue-400 text-blue-700 dark:bg-blue-900 dark:border-blue-700 dark:text-blue-200'
|
|
} %}
|
|
{% set icons = {
|
|
'success': 'check-circle',
|
|
'warning': 'exclamation',
|
|
'error': 'exclamation-circle',
|
|
'info': 'information-circle'
|
|
} %}
|
|
<div x-show="{{ show_condition }}" class="mb-4 p-4 border rounded-lg flex items-start {{ colors[type] }}" role="alert">
|
|
<span x-html="$icon('{{ icons[type] }}', 'w-5 h-5 mr-3 mt-0.5 flex-shrink-0')"></span>
|
|
<div class="flex-1">
|
|
{% if title %}
|
|
<p class="font-semibold">{{ title }}</p>
|
|
{% endif %}
|
|
<p class="text-sm" x-text="{{ message_var }}"></p>
|
|
</div>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
|
|
{#
|
|
Toast Notification
|
|
==================
|
|
A toast notification that appears and auto-dismisses.
|
|
|
|
Parameters:
|
|
- type: 'success' | 'warning' | 'error' | 'info' (default: 'success')
|
|
- message_var: Alpine.js variable for the message
|
|
- show_var: Alpine.js variable to control visibility
|
|
- duration: Auto-dismiss duration in ms (default: 3000, 0 to disable)
|
|
#}
|
|
{% macro toast(type='success', message_var='toastMessage', show_var='showToast', duration=3000) %}
|
|
{% set colors = {
|
|
'success': 'bg-green-500',
|
|
'warning': 'bg-yellow-500',
|
|
'error': 'bg-red-500',
|
|
'info': 'bg-blue-500'
|
|
} %}
|
|
{% set icons = {
|
|
'success': 'check-circle',
|
|
'warning': 'exclamation',
|
|
'error': 'exclamation-circle',
|
|
'info': 'information-circle'
|
|
} %}
|
|
<div
|
|
x-show="{{ show_var }}"
|
|
x-transition:enter="transition ease-out duration-300"
|
|
x-transition:enter-start="opacity-0 transform translate-y-2"
|
|
x-transition:enter-end="opacity-100 transform translate-y-0"
|
|
x-transition:leave="transition ease-in duration-200"
|
|
x-transition:leave-start="opacity-100 transform translate-y-0"
|
|
x-transition:leave-end="opacity-0 transform translate-y-2"
|
|
{% if duration > 0 %}
|
|
x-init="$watch('{{ show_var }}', value => { if (value) setTimeout(() => {{ show_var }} = false, {{ duration }}) })"
|
|
{% endif %}
|
|
class="fixed bottom-4 right-4 z-50 flex items-center px-4 py-3 text-white rounded-lg shadow-lg {{ colors[type] }}"
|
|
role="alert"
|
|
>
|
|
<span x-html="$icon('{{ icons[type] }}', 'w-5 h-5 mr-2')"></span>
|
|
<span x-text="{{ message_var }}"></span>
|
|
<button @click="{{ show_var }} = false" class="ml-4 hover:opacity-75 focus:outline-none" aria-label="Dismiss">
|
|
<span x-html="$icon('x', 'w-4 h-4')"></span>
|
|
</button>
|
|
</div>
|
|
{% endmacro %}
|