Add documentation for all new e-commerce macros: Priority 4 - Navigation & Discovery: - Category Navigation: category_nav, mega_menu, mobile_category_drawer - Breadcrumbs: breadcrumbs with variants and schema.org markup - Search Bar: search_bar, search_autocomplete, mobile_search - Filter Sidebar: filter_sidebar, price_filter, rating_filter, sort_dropdown Priority 5 - Social Proof & Trust: - Star Rating: star_rating, rating_input, rating_summary, compact_rating - Reviews: review_card, review_list, review_form, review_summary_section - Trust Badges: trust_badges, trust_banner, payment_icons, guarantee_badge, security_seals, checkout_trust_section Also adds Alpine.js state variables for reviews and ratings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
726 lines
21 KiB
Markdown
726 lines
21 KiB
Markdown
# UI Components Quick Reference
|
|
|
|
## Most Common Patterns
|
|
|
|
### 📝 Form Field (Basic)
|
|
```html
|
|
<label class="block mb-4 text-sm">
|
|
<span class="text-gray-700 dark:text-gray-400">Field Name</span>
|
|
<input
|
|
type="text"
|
|
x-model="formData.field"
|
|
class="block w-full mt-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray form-input"
|
|
/>
|
|
</label>
|
|
```
|
|
|
|
### 📝 Required Field with Error
|
|
```html
|
|
<label class="block mb-4 text-sm">
|
|
<span class="text-gray-700 dark:text-gray-400">
|
|
Field Name <span class="text-red-600">*</span>
|
|
</span>
|
|
<input
|
|
type="text"
|
|
x-model="formData.field"
|
|
required
|
|
:class="{ 'border-red-600': errors.field }"
|
|
class="block w-full mt-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple form-input"
|
|
/>
|
|
<span x-show="errors.field" class="text-xs text-red-600 dark:text-red-400" x-text="errors.field"></span>
|
|
</label>
|
|
```
|
|
|
|
### 📝 Read-Only Field
|
|
```html
|
|
<label class="block mb-4 text-sm">
|
|
<span class="text-gray-700 dark:text-gray-400">Field Name</span>
|
|
<input
|
|
type="text"
|
|
x-model="data.field"
|
|
disabled
|
|
class="block w-full mt-1 text-sm bg-gray-100 border-gray-300 rounded-md dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 cursor-not-allowed"
|
|
/>
|
|
</label>
|
|
```
|
|
|
|
### 🃏 Stats Card
|
|
```html
|
|
<div class="flex items-center p-4 bg-white rounded-lg shadow-xs dark:bg-gray-800">
|
|
<div class="p-3 mr-4 text-purple-500 bg-purple-100 rounded-full dark:text-purple-100 dark:bg-purple-500">
|
|
<span x-html="$icon('user-group', 'w-5 h-5')"></span>
|
|
</div>
|
|
<div>
|
|
<p class="mb-2 text-sm font-medium text-gray-600 dark:text-gray-400">Label</p>
|
|
<p class="text-lg font-semibold text-gray-700 dark:text-gray-200">Value</p>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### 🃏 Info Card
|
|
```html
|
|
<div class="px-4 py-3 bg-white rounded-lg shadow-md dark:bg-gray-800">
|
|
<h3 class="mb-4 text-lg font-semibold text-gray-700 dark:text-gray-200">Title</h3>
|
|
<div class="space-y-3">
|
|
<div>
|
|
<p class="text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase">Label</p>
|
|
<p class="text-sm text-gray-700 dark:text-gray-300">Value</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### 🔘 Primary Button
|
|
```html
|
|
<button class="px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg hover:bg-purple-700 focus:outline-none">
|
|
Click Me
|
|
</button>
|
|
```
|
|
|
|
### 🔘 Button with Icon
|
|
```html
|
|
<button class="flex items-center px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg hover:bg-purple-700">
|
|
<span x-html="$icon('plus', 'w-4 h-4 mr-2')"></span>
|
|
Add Item
|
|
</button>
|
|
```
|
|
|
|
### 🔘 Secondary Button
|
|
```html
|
|
<button class="px-4 py-2 text-sm font-medium leading-5 text-gray-700 transition-colors duration-150 bg-white border border-gray-300 rounded-lg hover:border-gray-400 dark:text-gray-400 dark:border-gray-600 dark:bg-gray-800">
|
|
Cancel
|
|
</button>
|
|
```
|
|
|
|
### 🏷️ Status Badge (Success)
|
|
```html
|
|
<span class="inline-flex items-center px-3 py-1 text-xs font-semibold leading-tight text-green-700 bg-green-100 rounded-full dark:bg-green-700 dark:text-green-100">
|
|
<span x-html="$icon('check-circle', 'w-3 h-3 mr-1')"></span>
|
|
Active
|
|
</span>
|
|
```
|
|
|
|
### 🏷️ Status Badge (Warning)
|
|
```html
|
|
<span class="inline-flex items-center px-3 py-1 text-xs font-semibold leading-tight text-orange-700 bg-orange-100 rounded-full dark:bg-orange-700 dark:text-orange-100">
|
|
<span x-html="$icon('clock', 'w-3 h-3 mr-1')"></span>
|
|
Pending
|
|
</span>
|
|
```
|
|
|
|
### 🏷️ Status Badge (Danger)
|
|
```html
|
|
<span class="inline-flex items-center px-3 py-1 text-xs font-semibold leading-tight text-red-700 bg-red-100 rounded-full dark:bg-red-700 dark:text-red-100">
|
|
<span x-html="$icon('x-circle', 'w-3 h-3 mr-1')"></span>
|
|
Inactive
|
|
</span>
|
|
```
|
|
|
|
## Number Stepper
|
|
|
|
A number input with +/- buttons for quantity selection. Ideal for cart quantities, batch sizes, and product pages.
|
|
|
|
### Basic Number Stepper
|
|
```html
|
|
{% from 'shared/macros/inputs.html' import number_stepper %}
|
|
|
|
{# Basic usage - cart quantity #}
|
|
{{ number_stepper(model='quantity', min=1, max=99) }}
|
|
```
|
|
|
|
### Size Variants
|
|
```html
|
|
{# Small - compact for tables/lists #}
|
|
{{ number_stepper(model='item.qty', min=1, max='item.stock', size='sm') }}
|
|
|
|
{# Medium (default) #}
|
|
{{ number_stepper(model='quantity', min=1, max=99) }}
|
|
|
|
{# Large - prominent placement #}
|
|
{{ number_stepper(model='batchSize', min=100, max=5000, step=100, size='lg') }}
|
|
```
|
|
|
|
### With Disabled State
|
|
```html
|
|
{{ number_stepper(model='qty', min=1, disabled_var='isLoading') }}
|
|
```
|
|
|
|
### Number Stepper Parameters
|
|
| Parameter | Default | Description |
|
|
|-----------|---------|-------------|
|
|
| `model` | required | Alpine.js x-model variable |
|
|
| `min` | `1` | Minimum allowed value |
|
|
| `max` | `none` | Maximum allowed value (can be Alpine.js expression) |
|
|
| `step` | `1` | Increment/decrement step |
|
|
| `size` | `'md'` | Size variant: `'sm'`, `'md'`, `'lg'` |
|
|
| `disabled_var` | `none` | Alpine.js variable for disabled state |
|
|
| `name` | `none` | Input name for form submission |
|
|
| `id` | `none` | Input id attribute |
|
|
| `label` | `'Quantity'` | Accessible label for screen readers |
|
|
|
|
---
|
|
|
|
## Tabs
|
|
|
|
Tab navigation components for switching between content sections.
|
|
|
|
### 🗂️ Navigation Tabs (with icons)
|
|
```html
|
|
{% from 'shared/macros/tabs.html' import tabs_nav, tab_button %}
|
|
|
|
{% call tabs_nav() %}
|
|
{{ tab_button('dashboard', 'Dashboard', icon='home') }}
|
|
{{ tab_button('settings', 'Settings', icon='cog') }}
|
|
{{ tab_button('profile', 'Profile', icon='user') }}
|
|
{% endcall %}
|
|
|
|
<!-- Tab content panels -->
|
|
<div x-show="activeTab === 'dashboard'" x-transition>
|
|
Dashboard content...
|
|
</div>
|
|
```
|
|
|
|
### 🗂️ Inline Tabs (with count badges)
|
|
```html
|
|
{% from 'shared/macros/tabs.html' import tabs_inline, tab_button %}
|
|
|
|
<div class="flex justify-between gap-4">
|
|
{% call tabs_inline() %}
|
|
{{ tab_button('all', 'All Items', count_var='allItems.length') }}
|
|
{{ tab_button('active', 'Active', count_var='activeItems.length') }}
|
|
{{ tab_button('archived', 'Archived', count_var='archivedItems.length') }}
|
|
{% endcall %}
|
|
<div>Search...</div>
|
|
</div>
|
|
```
|
|
|
|
### 🗂️ Tabs with Custom Click Handlers
|
|
```html
|
|
{% call tabs_nav() %}
|
|
{{ tab_button('database', 'Database Logs',
|
|
tab_var='logSource',
|
|
icon='database',
|
|
onclick="logSource = 'database'; loadDatabaseLogs()") }}
|
|
{{ tab_button('file', 'File Logs',
|
|
tab_var='logSource',
|
|
icon='document',
|
|
onclick="logSource = 'file'; loadFileLogs()") }}
|
|
{% endcall %}
|
|
```
|
|
|
|
### Tab Button Parameters
|
|
| Parameter | Default | Description |
|
|
|-----------|---------|-------------|
|
|
| `id` | required | Tab identifier for comparison |
|
|
| `label` | required | Display text |
|
|
| `tab_var` | `'activeTab'` | Alpine.js variable for active state |
|
|
| `icon` | `none` | Optional icon name |
|
|
| `count_var` | `none` | Alpine.js variable for count badge |
|
|
| `onclick` | `none` | Custom click handler (overrides default) |
|
|
|
|
## Grid Layouts
|
|
|
|
### 2 Columns (Desktop)
|
|
```html
|
|
<div class="grid gap-6 md:grid-cols-2">
|
|
<!-- Column 1 -->
|
|
<div>...</div>
|
|
<!-- Column 2 -->
|
|
<div>...</div>
|
|
</div>
|
|
```
|
|
|
|
### 4 Columns (Responsive)
|
|
```html
|
|
<div class="grid gap-6 mb-8 md:grid-cols-2 xl:grid-cols-4">
|
|
<!-- Cards -->
|
|
</div>
|
|
```
|
|
|
|
## Color Classes
|
|
|
|
### Background Colors
|
|
- Primary: `bg-purple-600`
|
|
- Success: `bg-green-600`
|
|
- Warning: `bg-orange-600`
|
|
- Danger: `bg-red-600`
|
|
- Info: `bg-blue-600`
|
|
|
|
### Text Colors
|
|
- Primary: `text-purple-600`
|
|
- Success: `text-green-600`
|
|
- Warning: `text-orange-600`
|
|
- Danger: `text-red-600`
|
|
- Info: `text-blue-600`
|
|
|
|
### Icon Colors
|
|
- Primary: `text-purple-500 bg-purple-100`
|
|
- Success: `text-green-500 bg-green-100`
|
|
- Warning: `text-orange-500 bg-orange-100`
|
|
- Danger: `text-red-500 bg-red-100`
|
|
- Info: `text-blue-500 bg-blue-100`
|
|
|
|
## Common Icons
|
|
- `user-group` - Users/Teams
|
|
- `badge-check` - Verified
|
|
- `check-circle` - Success
|
|
- `x-circle` - Error/Inactive
|
|
- `clock` - Pending
|
|
- `calendar` - Dates
|
|
- `refresh` - Update
|
|
- `edit` - Edit
|
|
- `delete` - Delete
|
|
- `plus` - Add
|
|
- `arrow-left` - Back
|
|
- `exclamation` - Warning
|
|
|
|
## Spacing
|
|
- Small gap: `gap-3`
|
|
- Medium gap: `gap-6`
|
|
- Large gap: `gap-8`
|
|
- Margin bottom: `mb-4`, `mb-6`, `mb-8`
|
|
- Padding: `p-3`, `p-4`, `px-4 py-3`
|
|
|
|
## Quick Copy-Paste: Page Structure
|
|
|
|
```html
|
|
{# app/templates/admin/your-page.html #}
|
|
{% extends "admin/base.html" %}
|
|
|
|
{% block title %}Your Page{% endblock %}
|
|
|
|
{% block alpine_data %}yourPageData(){% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- Page Header -->
|
|
<div class="my-6">
|
|
<h2 class="text-2xl font-semibold text-gray-700 dark:text-gray-200">
|
|
Page Title
|
|
</h2>
|
|
</div>
|
|
|
|
<!-- Loading State -->
|
|
<div x-show="loading" 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">Loading...</p>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div x-show="!loading">
|
|
<div class="px-4 py-3 mb-8 bg-white rounded-lg shadow-md dark:bg-gray-800">
|
|
<!-- Your content here -->
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
```
|
|
|
|
## Remember
|
|
|
|
1. Always use `dark:` variants for dark mode
|
|
2. Add `:disabled="saving"` to buttons during operations
|
|
3. Use `x-show` for conditional display
|
|
4. Use `x-text` for dynamic text
|
|
5. Use `x-html="$icon(...)"` for icons
|
|
6. Validation errors: `border-red-600` class
|
|
7. Helper text: `text-xs text-gray-600`
|
|
8. Error text: `text-xs text-red-600`
|
|
|
|
---
|
|
|
|
## E-commerce Components (Shop Frontend)
|
|
|
|
Reusable macros for shop/storefront functionality. Located in `app/templates/shared/macros/shop/`.
|
|
|
|
### 🛍️ Product Card
|
|
```html
|
|
{% from 'shared/macros/shop/product-card.html' import product_card %}
|
|
|
|
{# Basic product card #}
|
|
{{ product_card(product_var='product') }}
|
|
|
|
{# With size and options #}
|
|
{{ product_card(
|
|
product_var='item',
|
|
size='lg',
|
|
show_rating=true,
|
|
show_quick_add=true,
|
|
show_wishlist=true
|
|
) }}
|
|
```
|
|
|
|
**Size variants:** `sm` (compact), `md` (default), `lg` (featured)
|
|
|
|
**Features:**
|
|
- Sale badge (when `sale_price` exists)
|
|
- "New" badge (when `is_new` is true)
|
|
- Out of stock overlay
|
|
- Star ratings with review count
|
|
- Wishlist toggle button
|
|
- Quick add to cart
|
|
|
|
### 🛍️ Product Grid
|
|
```html
|
|
{% from 'shared/macros/shop/product-grid.html' import product_grid %}
|
|
|
|
{# Basic grid #}
|
|
{{ product_grid(products_var='products', loading_var='loading') }}
|
|
|
|
{# With empty state #}
|
|
{{ product_grid(
|
|
products_var='searchResults',
|
|
loading_var='searching',
|
|
empty_message='No products found',
|
|
empty_icon='search'
|
|
) }}
|
|
```
|
|
|
|
**Features:**
|
|
- Responsive columns (auto-adjusts or fixed)
|
|
- Loading skeleton placeholders
|
|
- Empty state with customizable icon/message
|
|
|
|
### 🛒 Add to Cart
|
|
```html
|
|
{% from 'shared/macros/shop/add-to-cart.html' import add_to_cart_button, add_to_cart_form, buy_now_button %}
|
|
|
|
{# Simple button #}
|
|
{{ add_to_cart_button(action='addToCart()') }}
|
|
|
|
{# Complete form with quantity #}
|
|
{{ add_to_cart_form(product_var='product', size='md') }}
|
|
|
|
{# Buy now button #}
|
|
{{ buy_now_button(action='buyNow()') }}
|
|
```
|
|
|
|
**Macros available:**
|
|
- `add_to_cart_button()` - Simple button with loading state
|
|
- `add_to_cart_form()` - Form with quantity selector + button
|
|
- `buy_now_button()` - Direct checkout button
|
|
- `shop_quantity_selector()` - Stock-aware quantity input
|
|
|
|
### 🛒 Mini Cart (Header)
|
|
```html
|
|
{% from 'shared/macros/shop/mini-cart.html' import mini_cart, mini_cart_icon %}
|
|
|
|
{# Complete mini cart with dropdown #}
|
|
{{ mini_cart(cart_var='cart', show_var='showCart') }}
|
|
|
|
{# Just the icon with badge #}
|
|
{{ mini_cart_icon(cart_var='cart', size='md') }}
|
|
```
|
|
|
|
**Macros available:**
|
|
- `mini_cart()` - Combined icon + dropdown
|
|
- `mini_cart_icon()` - Icon with item count badge
|
|
- `mini_cart_dropdown()` - Dropdown panel
|
|
- `cart_item()` - Individual item display
|
|
- `cart_summary()` - Subtotal, shipping, total
|
|
|
|
### 🖼️ Product Gallery (Priority 3)
|
|
```html
|
|
{% from 'shared/macros/shop/product-gallery.html' import product_gallery %}
|
|
|
|
{# Full gallery with thumbnails, zoom, and lightbox #}
|
|
{{ product_gallery(images_var='product.images', enable_zoom=true, enable_lightbox=true) }}
|
|
|
|
{# Simple single image viewer #}
|
|
{{ simple_image_viewer(image_var='product.image_url') }}
|
|
```
|
|
|
|
**Features:**
|
|
- Thumbnail navigation
|
|
- Hover zoom on main image
|
|
- Fullscreen lightbox with keyboard navigation
|
|
- Responsive design
|
|
|
|
### 🎨 Variant Selector (Priority 3)
|
|
```html
|
|
{% from 'shared/macros/shop/variant-selector.html' import size_selector, color_swatches %}
|
|
|
|
{# Size buttons with size guide link #}
|
|
{{ size_selector(sizes_var='product.sizes', show_guide=true) }}
|
|
|
|
{# Color swatches with out-of-stock indicators #}
|
|
{{ color_swatches(colors_var='product.colors', selected_var='selectedColor') }}
|
|
```
|
|
|
|
**Macros available:**
|
|
- `variant_selector()` - Generic (buttons/dropdown/swatches)
|
|
- `size_selector()` - Specialized for sizes
|
|
- `color_swatches()` - Color selection with hex preview
|
|
- `multi_variant_selector()` - Multiple option types
|
|
|
|
### 📄 Product Info (Priority 3)
|
|
```html
|
|
{% from 'shared/macros/shop/product-info.html' import product_info, product_price %}
|
|
|
|
{# Complete info block #}
|
|
{{ product_info(product_var='product', show_vendor=true, show_rating=true) }}
|
|
|
|
{# Individual components #}
|
|
{{ product_price(product_var='product', size='lg') }}
|
|
{{ product_rating(product_var='product', clickable=true) }}
|
|
{{ stock_status(product_var='product') }}
|
|
```
|
|
|
|
**Macros available:**
|
|
- `product_info()` - Complete info section
|
|
- `product_price()` - Price with sale support
|
|
- `product_rating()` - Star rating display
|
|
- `stock_status()` - Stock indicator
|
|
- `trust_indicators()` - Shipping/returns badges
|
|
|
|
### 📑 Product Tabs (Priority 3)
|
|
```html
|
|
{% from 'shared/macros/shop/product-tabs.html' import product_tabs %}
|
|
|
|
{# Tabbed product information #}
|
|
{{ product_tabs(
|
|
product_var='product',
|
|
tabs=['description', 'specifications', 'reviews', 'shipping']
|
|
) }}
|
|
```
|
|
|
|
**Tab options:** `description`, `specifications`, `reviews`, `shipping`, `warranty`
|
|
|
|
### 📂 Category Navigation (Priority 4)
|
|
```html
|
|
{% from 'shared/macros/shop/category-nav.html' import category_nav, category_tree, category_menu %}
|
|
|
|
{# Sidebar with nested categories #}
|
|
{{ category_nav(categories_var='categories', current_var='currentCategory', show_count=true) }}
|
|
|
|
{# Horizontal pills #}
|
|
{{ category_tree(categories_var='categories', layout='horizontal') }}
|
|
|
|
{# Header dropdown menu #}
|
|
{{ category_menu(categories_var='mainCategories') }}
|
|
```
|
|
|
|
**Macros:** `category_nav()`, `category_tree()`, `category_menu()`, `category_drawer()`
|
|
|
|
### 🍞 Breadcrumbs (Priority 4)
|
|
```html
|
|
{% from 'shared/macros/shop/breadcrumbs.html' import shop_breadcrumbs, compact_breadcrumbs %}
|
|
|
|
{# Static breadcrumbs #}
|
|
{{ shop_breadcrumbs(items=[
|
|
{'label': 'Electronics', 'url': '/electronics'},
|
|
{'label': 'Audio', 'url': '/audio'},
|
|
{'label': 'Headphones'}
|
|
]) }}
|
|
|
|
{# Mobile-friendly compact #}
|
|
{{ compact_breadcrumbs(parent={'label': 'Audio', 'url': '/audio'}, current='Headphones') }}
|
|
```
|
|
|
|
**Macros:** `shop_breadcrumbs()`, `auto_breadcrumbs()`, `compact_breadcrumbs()`
|
|
|
|
### 🔍 Search Bar (Priority 4)
|
|
```html
|
|
{% from 'shared/macros/shop/search-bar.html' import search_bar, search_autocomplete %}
|
|
|
|
{# Basic search #}
|
|
{{ search_bar(placeholder='Search products...') }}
|
|
|
|
{# With search button #}
|
|
{{ search_bar(placeholder='Search...', show_button=true, size='lg') }}
|
|
|
|
{# Autocomplete with suggestions #}
|
|
{{ search_autocomplete(search_endpoint='/api/search', show_recent=true, show_popular=true) }}
|
|
```
|
|
|
|
**Macros:** `search_bar()`, `search_autocomplete()`, `mobile_search()`, `search_trigger()`
|
|
|
|
### 🎛️ Filter Sidebar (Priority 4)
|
|
```html
|
|
{% from 'shared/macros/shop/filter-sidebar.html' import filter_sidebar, price_filter, sort_dropdown %}
|
|
|
|
{# Complete filter panel #}
|
|
{{ filter_sidebar(filters_var='filters', active_filters_var='activeFilters', on_change='filterProducts()') }}
|
|
|
|
{# Standalone price filter #}
|
|
{{ price_filter(min=0, max=500, on_change='updateFilters()') }}
|
|
|
|
{# Sort dropdown #}
|
|
{{ sort_dropdown(value_var='sortBy', on_change='sortProducts()') }}
|
|
```
|
|
|
|
**Macros:** `filter_sidebar()`, `price_filter()`, `rating_filter()`, `sort_dropdown()`, `mobile_filter_drawer()`
|
|
|
|
### ⭐ Star Rating (Priority 5)
|
|
```html
|
|
{% from 'shared/macros/shop/star-rating.html' import star_rating, rating_input, rating_summary, compact_rating %}
|
|
|
|
{# Static star rating with half-star support #}
|
|
{{ star_rating(rating=4.5, show_value=true, show_count=true, count=127) }}
|
|
|
|
{# Dynamic rating from Alpine.js #}
|
|
{{ star_rating(rating_var='product.rating', show_count=true, count_var='product.review_count') }}
|
|
|
|
{# Interactive rating input #}
|
|
{{ rating_input(model='userRating', size='lg', allow_half=true) }}
|
|
|
|
{# Rating summary with distribution bars #}
|
|
{{ rating_summary(rating_var='rating', count_var='reviewCount', distribution_var='ratingDistribution') }}
|
|
|
|
{# Compact rating for lists/cards #}
|
|
{{ compact_rating(rating=4.5, count=127, size='sm') }}
|
|
```
|
|
|
|
**Macros:** `star_rating()`, `rating_input()`, `rating_summary()`, `compact_rating()`
|
|
|
|
### 💬 Reviews (Priority 5)
|
|
```html
|
|
{% from 'shared/macros/shop/reviews.html' import review_card, review_list, review_form, review_summary_section %}
|
|
|
|
{# Single review card with helpful buttons #}
|
|
{{ review_card(review_var='review', on_helpful='markHelpful(review.id)') }}
|
|
|
|
{# Review list with sorting #}
|
|
{{ review_list(reviews_var='reviews', sort_var='reviewSort', on_helpful='markHelpful') }}
|
|
|
|
{# Review submission form #}
|
|
{{ review_form(rating_model='rating', title_model='title', content_model='content', on_submit='submitReview()') }}
|
|
|
|
{# Complete review summary section #}
|
|
{{ review_summary_section(rating_var='rating', count_var='count', distribution_var='dist', on_write='openForm()') }}
|
|
```
|
|
|
|
**Macros:** `review_card()`, `review_list()`, `review_form()`, `review_summary_section()`
|
|
|
|
### 🛡️ Trust Badges (Priority 5)
|
|
```html
|
|
{% from 'shared/macros/shop/trust-badges.html' import trust_badges, trust_banner, payment_icons, guarantee_badge, security_seals, checkout_trust_section %}
|
|
|
|
{# Trust badges grid #}
|
|
{{ trust_badges(badges=['secure_payment', 'free_shipping', 'easy_returns', 'support_24_7'], layout='grid') }}
|
|
|
|
{# Trust banner variants #}
|
|
{{ trust_banner() }}
|
|
{{ trust_banner(variant='compact') }}
|
|
{{ trust_banner(variant='detailed') }}
|
|
|
|
{# Payment method icons #}
|
|
{{ payment_icons(methods=['visa', 'mastercard', 'paypal', 'apple_pay']) }}
|
|
{{ payment_icons(methods=['visa', 'mastercard'], size='lg') }}
|
|
|
|
{# Guarantee badges #}
|
|
{{ guarantee_badge(type='money_back', days=30) }}
|
|
{{ guarantee_badge(type='satisfaction', variant='filled') }}
|
|
|
|
{# Security seals #}
|
|
{{ security_seals(seals=['ssl', 'verified']) }}
|
|
|
|
{# Complete checkout trust section #}
|
|
{{ checkout_trust_section() }}
|
|
```
|
|
|
|
**Macros:** `trust_badges()`, `trust_banner()`, `payment_icons()`, `guarantee_badge()`, `security_seals()`, `checkout_trust_section()`
|
|
|
|
### E-commerce Alpine.js State
|
|
```javascript
|
|
// Required state variables for e-commerce components
|
|
{
|
|
// Products
|
|
products: [],
|
|
loading: true,
|
|
|
|
// Cart
|
|
cart: {
|
|
items: [],
|
|
item_count: 0,
|
|
subtotal: 0,
|
|
total: 0
|
|
},
|
|
showCart: false,
|
|
|
|
// Add to cart
|
|
quantity: 1,
|
|
addingToCart: false,
|
|
addedToCart: false,
|
|
|
|
// Product detail (Priority 3)
|
|
selectedImage: 0,
|
|
selectedSize: null,
|
|
selectedColor: null,
|
|
activeProductTab: 'description',
|
|
|
|
// Navigation & Discovery (Priority 4)
|
|
categories: [],
|
|
currentCategory: null,
|
|
breadcrumbs: [],
|
|
|
|
// Filters (Priority 4)
|
|
filters: {
|
|
categories: [],
|
|
brands: [],
|
|
priceRange: { min: 0, max: 1000 },
|
|
attributes: {},
|
|
ratings: []
|
|
},
|
|
activeFilters: {
|
|
categories: [],
|
|
brands: [],
|
|
priceMin: undefined,
|
|
priceMax: undefined,
|
|
rating: undefined,
|
|
attributes: {},
|
|
inStock: false
|
|
},
|
|
sortBy: 'relevance',
|
|
|
|
// Mobile UI (Priority 4)
|
|
showMobileSearch: false,
|
|
showMobileFilters: false,
|
|
showCategoryDrawer: false,
|
|
|
|
// Reviews & Ratings (Priority 5)
|
|
reviews: [],
|
|
reviewSort: 'newest',
|
|
userRating: 0,
|
|
ratingDistribution: { 5: 0, 4: 0, 3: 0, 2: 0, 1: 0 },
|
|
newReview: { rating: 0, title: '', content: '' },
|
|
submittingReview: false,
|
|
showReviewForm: false,
|
|
|
|
// Wishlist
|
|
toggleWishlist(product) {
|
|
product.in_wishlist = !product.in_wishlist;
|
|
},
|
|
|
|
// Cart actions
|
|
addToCart() {
|
|
this.addingToCart = true;
|
|
// API call...
|
|
},
|
|
removeFromCart(itemId) {
|
|
this.cart.items = this.cart.items.filter(i => i.id !== itemId);
|
|
},
|
|
|
|
// Filter actions (Priority 4)
|
|
filterProducts() {
|
|
// Apply filters and update products...
|
|
},
|
|
sortProducts() {
|
|
// Sort products by sortBy value...
|
|
},
|
|
|
|
// Review actions (Priority 5)
|
|
submitReview() {
|
|
this.submittingReview = true;
|
|
// API call to submit review...
|
|
},
|
|
markHelpful(reviewId, helpful) {
|
|
// Mark review as helpful/not helpful...
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Reference Page
|
|
|
|
Visit `/admin/components` for full component library with live examples!
|