docs: add macros and pagination sections to components page
Update admin components page with documentation for: - New Macros section listing all available shared macros with imports - Pagination section with live interactive examples - Copy-to-clipboard functionality for code snippets - Dark mode support for all new sections This serves as a living style guide for developers implementing new admin pages using the shared component library. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,216 @@ html {
|
||||
<!-- Main Content - WIDELY SPACED SECTIONS -->
|
||||
<div class="flex-1 space-y-32">
|
||||
|
||||
<!-- MACROS SECTION -->
|
||||
<section id="macros" class="scroll-mt-24">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
|
||||
<h2 class="text-2xl font-bold text-gray-800 dark:text-gray-200 mb-6 flex items-center">
|
||||
<span x-html="$icon('template', 'w-6 h-6 mr-2 text-purple-600 dark:text-purple-400')"></span>
|
||||
Jinja Macros
|
||||
</h2>
|
||||
|
||||
<div class="mb-6 p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
|
||||
<div class="flex items-start">
|
||||
<span x-html="$icon('information-circle', 'w-5 h-5 text-blue-600 dark:text-blue-400 mr-2 flex-shrink-0 mt-0.5')"></span>
|
||||
<div>
|
||||
<p class="text-sm text-blue-800 dark:text-blue-200">
|
||||
<strong>Reusable Components:</strong> Use Jinja macros from <code class="bg-blue-100 dark:bg-blue-800 px-1 rounded">shared/macros/</code> instead of copy-pasting HTML. This ensures consistency and makes updates easier.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Available Macros -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-4">Available Macro Files</h3>
|
||||
<div class="grid gap-4 md:grid-cols-2">
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">pagination.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Table pagination with page numbers</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">pagination(), pagination_simple()</code>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">alerts.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Alerts, loading states, toasts</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">loading_state(), error_state(), alert(), toast()</code>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">badges.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Status badges and indicators</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">badge(), status_badge(), verification_badge(), role_badge()</code>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">buttons.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Button variants and action buttons</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">btn_primary(), btn_secondary(), action_button()</code>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">forms.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Form inputs with validation</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">form_input(), form_select(), form_textarea()</code>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">tables.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Table components and empty states</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">table_wrapper(), table_header(), table_empty_state()</code>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">cards.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Stat cards and info cards</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">stat_card(), card(), info_card(), coming_soon_card()</code>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 dark:text-gray-200 mb-2">headers.html</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">Page headers and breadcrumbs</p>
|
||||
<code class="text-xs bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded">page_header(), section_header(), breadcrumbs()</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Usage Example -->
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3">Usage Example</h3>
|
||||
<div class="bg-gray-900 rounded-lg p-4 mb-3 overflow-x-auto">
|
||||
<pre class="text-sm text-gray-100"><code>{# Import at the top of your template #}
|
||||
{% raw %}{% from 'shared/macros/pagination.html' import pagination %}
|
||||
{% from 'shared/macros/alerts.html' import loading_state, error_state %}
|
||||
{% from 'shared/macros/badges.html' import status_badge, verification_badge %}
|
||||
{% from 'shared/macros/buttons.html' import btn_primary, action_button %}
|
||||
{% from 'shared/macros/cards.html' import stat_card %}
|
||||
{% from 'shared/macros/headers.html' import page_header %}
|
||||
|
||||
{# Then use in your template #}
|
||||
{{ page_header('User Management', action_label='Create User', action_url='/users/create') }}
|
||||
|
||||
{{ loading_state('Loading users...') }}
|
||||
{{ error_state('Error loading users') }}
|
||||
|
||||
{# In your table #}
|
||||
{{ pagination() }}{% endraw %}</code></pre>
|
||||
</div>
|
||||
<button @click="copyCode(`{% from 'shared/macros/pagination.html' import pagination %}
|
||||
{% from 'shared/macros/alerts.html' import loading_state, error_state %}
|
||||
{% from 'shared/macros/badges.html' import status_badge, verification_badge %}
|
||||
|
||||
{{ page_header('Page Title', action_label='Action', action_url='/action') }}
|
||||
{{ loading_state('Loading...') }}
|
||||
{{ pagination() }}`)" class="text-sm text-purple-600 hover:text-purple-700 dark:text-purple-400 flex items-center">
|
||||
<span x-html="$icon('duplicate', 'w-4 h-4 mr-1')"></span>
|
||||
Copy Code
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- PAGINATION SECTION -->
|
||||
<section id="pagination" class="scroll-mt-24">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
|
||||
<h2 class="text-2xl font-bold text-gray-800 dark:text-gray-200 mb-6 flex items-center">
|
||||
<span x-html="$icon('dots-horizontal', 'w-6 h-6 mr-2 text-purple-600 dark:text-purple-400')"></span>
|
||||
Pagination
|
||||
</h2>
|
||||
|
||||
<!-- Full Pagination -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3">Full Pagination (with page numbers)</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
Use the <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">pagination()</code> macro. Requires Alpine.js properties: <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">pagination</code>, <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">startIndex</code>, <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">endIndex</code>, <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">totalPages</code>, <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">pageNumbers</code>.
|
||||
</p>
|
||||
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 mb-3">
|
||||
<!-- Live example of pagination -->
|
||||
<div class="grid px-4 py-3 text-xs font-semibold tracking-wide text-gray-500 uppercase border dark:border-gray-700 bg-gray-50 sm:grid-cols-9 dark:text-gray-400 dark:bg-gray-800 rounded-lg">
|
||||
<span class="flex items-center col-span-3">
|
||||
Showing <span class="mx-1 font-bold">1</span>-<span class="mx-1 font-bold">10</span> of <span class="mx-1 font-bold">97</span>
|
||||
</span>
|
||||
<span class="col-span-2"></span>
|
||||
<span class="flex col-span-4 mt-2 sm:mt-auto sm:justify-end">
|
||||
<nav aria-label="Table navigation">
|
||||
<ul class="inline-flex items-center">
|
||||
<li>
|
||||
<button class="px-3 py-1 rounded-md rounded-l-lg focus:outline-none opacity-50 cursor-not-allowed" disabled>
|
||||
<svg class="w-4 h-4 fill-current" viewBox="0 0 20 20"><path d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
|
||||
</button>
|
||||
</li>
|
||||
<li><button class="px-3 py-1 rounded-md text-white bg-purple-600 border border-purple-600">1</button></li>
|
||||
<li><button class="px-3 py-1 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">2</button></li>
|
||||
<li><button class="px-3 py-1 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">3</button></li>
|
||||
<li><span class="px-3 py-1">...</span></li>
|
||||
<li><button class="px-3 py-1 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">10</button></li>
|
||||
<li>
|
||||
<button class="px-3 py-1 rounded-md rounded-r-lg hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<svg class="w-4 h-4 fill-current" viewBox="0 0 20 20"><path d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button @click="copyCode(`{% from 'shared/macros/pagination.html' import pagination %}
|
||||
|
||||
{# In your template (inside the table wrapper) #}
|
||||
{{ pagination() }}
|
||||
|
||||
{# Required JS properties in your Alpine component: #}
|
||||
pagination: { page: 1, per_page: 10, total: 0, pages: 0 },
|
||||
|
||||
get totalPages() { return this.pagination.pages; },
|
||||
get startIndex() { return this.pagination.total === 0 ? 0 : (this.pagination.page - 1) * this.pagination.per_page + 1; },
|
||||
get endIndex() { return Math.min(this.pagination.page * this.pagination.per_page, this.pagination.total); },
|
||||
get pageNumbers() {
|
||||
const pages = [];
|
||||
const totalPages = this.totalPages;
|
||||
const current = this.pagination.page;
|
||||
if (totalPages <= 7) {
|
||||
for (let i = 1; i <= totalPages; i++) pages.push(i);
|
||||
} else {
|
||||
pages.push(1);
|
||||
if (current > 3) pages.push('...');
|
||||
for (let i = Math.max(2, current - 1); i <= Math.min(totalPages - 1, current + 1); i++) pages.push(i);
|
||||
if (current < totalPages - 2) pages.push('...');
|
||||
pages.push(totalPages);
|
||||
}
|
||||
return pages;
|
||||
},
|
||||
previousPage() { if (this.pagination.page > 1) { this.pagination.page--; this.load(); } },
|
||||
nextPage() { if (this.pagination.page < this.totalPages) { this.pagination.page++; this.load(); } },
|
||||
goToPage(n) { if (n !== '...' && n >= 1 && n <= this.totalPages) { this.pagination.page = n; this.load(); } }`)" class="text-sm text-purple-600 hover:text-purple-700 dark:text-purple-400 flex items-center">
|
||||
<span x-html="$icon('duplicate', 'w-4 h-4 mr-1')"></span>
|
||||
Copy Code
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Simple Pagination -->
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3">Simple Pagination (prev/next only)</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
Use <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">pagination_simple()</code> for a simpler prev/next navigation.
|
||||
</p>
|
||||
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 mb-3">
|
||||
<div class="flex items-center justify-between px-4 py-3 bg-white border dark:border-gray-700 dark:bg-gray-800 rounded-lg">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-400">
|
||||
Showing <span class="font-semibold">1</span>-<span class="font-semibold">10</span> of <span class="font-semibold">97</span> results
|
||||
</span>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button disabled class="px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md opacity-50 cursor-not-allowed">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
|
||||
</button>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-400">Page 1 of 10</span>
|
||||
<button class="px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button @click="copyCode(`{% from 'shared/macros/pagination.html' import pagination_simple %}
|
||||
{{ pagination_simple() }}`)" class="text-sm text-purple-600 hover:text-purple-700 dark:text-purple-400 flex items-center">
|
||||
<span x-html="$icon('duplicate', 'w-4 h-4 mr-1')"></span>
|
||||
Copy Code
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FORMS SECTION -->
|
||||
<section id="forms" class="scroll-mt-24">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
|
||||
|
||||
@@ -21,6 +21,8 @@ function adminComponents() {
|
||||
|
||||
// Component sections
|
||||
sections: [
|
||||
{ id: 'macros', name: 'Macros', icon: 'template' },
|
||||
{ id: 'pagination', name: 'Pagination', icon: 'dots-horizontal' },
|
||||
{ id: 'forms', name: 'Forms', icon: 'clipboard-list' },
|
||||
{ id: 'buttons', name: 'Buttons', icon: 'cursor-click' },
|
||||
{ id: 'cards', name: 'Cards', icon: 'collection' },
|
||||
|
||||
Reference in New Issue
Block a user