Some checks failed
- Add redis-exporter container to docker-compose (oliver006/redis_exporter, 32MB) - Add Redis scrape target to Prometheus config - Add 4 Redis alert rules: RedisDown, HighMemory, HighConnections, RejectedConnections - Document Step 19b (Sentry Error Tracking) in Hetzner deployment guide - Document Step 19c (Redis Monitoring) in Hetzner deployment guide - Update resource budget and port reference tables Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
429 lines
13 KiB
Markdown
429 lines
13 KiB
Markdown
# Icon System Guide
|
|
|
|
## Overview
|
|
|
|
This project uses **Heroicons** (inline SVG) with a custom helper system for clean, maintainable icon usage across all **4 frontends**:
|
|
- **Platform** - Public platform pages
|
|
- **Admin** - Administrative portal
|
|
- **Store** - Store management portal
|
|
- **Shop** - Customer-facing store
|
|
|
|
### Why This Approach?
|
|
|
|
- **No External Dependencies**: All icons are inline SVG - no CDN required
|
|
- **Performance**: Zero extra HTTP requests
|
|
- **Tailwind Integration**: Icons work seamlessly with Tailwind utility classes
|
|
- **Clean HTML**: No verbose SVG code cluttering your templates
|
|
- **Type Safety**: All available icons are defined in one place
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### 1. Include the Icon Helper
|
|
|
|
Add this script **before** Alpine.js in your HTML pages:
|
|
|
|
```html
|
|
<!-- Load icon helper -->
|
|
<script src="/static/shared/js/icons.js"></script>
|
|
|
|
<!-- Alpine.js v3 -->
|
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.0/dist/cdn.min.js"></script>
|
|
```
|
|
|
|
### 2. Use Icons with Alpine Magic Helper
|
|
|
|
```html
|
|
<!-- Default size (w-5 h-5) -->
|
|
<span x-html="$icon('home')"></span>
|
|
|
|
<!-- Custom size and color -->
|
|
<span x-html="$icon('home', 'w-6 h-6 text-purple-600')"></span>
|
|
|
|
<!-- In buttons -->
|
|
<button>
|
|
<span x-html="$icon('plus', 'w-4 h-4 mr-2')"></span>
|
|
Create Store
|
|
</button>
|
|
```
|
|
|
|
---
|
|
|
|
## Available Icons
|
|
|
|
### Navigation Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `home` | `$icon('home')` | Dashboard, homepage |
|
|
| `menu` | `$icon('menu')` | Mobile menu toggle |
|
|
| `search` | `$icon('search')` | Search functionality |
|
|
| `arrow-left` | `$icon('arrow-left')` | Back navigation |
|
|
| `chevron-down` | `$icon('chevron-down')` | Dropdowns |
|
|
| `chevron-right` | `$icon('chevron-right')` | Next/forward |
|
|
|
|
### User & Profile Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `user` | `$icon('user')` | Single user profile |
|
|
| `users` | `$icon('users')` | Multiple users, team |
|
|
| `user-circle` | `$icon('user-circle')` | User avatar |
|
|
| `user-group` | `$icon('user-group')` | Groups, teams |
|
|
| `identification` | `$icon('identification')` | ID, credentials |
|
|
| `badge-check` | `$icon('badge-check')` | Verified badge |
|
|
|
|
### Action Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `edit` | `$icon('edit')` | Edit action |
|
|
| `delete` | `$icon('delete')` | Delete action |
|
|
| `plus` | `$icon('plus')` | Add/create action |
|
|
| `check` | `$icon('check')` | Success, confirmed |
|
|
| `close` | `$icon('close')` | Close, dismiss |
|
|
| `refresh` | `$icon('refresh')` | Reload, refresh |
|
|
| `duplicate` | `$icon('duplicate')` | Copy, duplicate |
|
|
| `eye` | `$icon('eye')` | View, show |
|
|
| `eye-off` | `$icon('eye-off')` | Hide |
|
|
| `filter` | `$icon('filter')` | Filter options |
|
|
| `dots-vertical` | `$icon('dots-vertical')` | More options (vertical) |
|
|
| `dots-horizontal` | `$icon('dots-horizontal')` | More options (horizontal) |
|
|
|
|
### E-commerce Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `shopping-bag` | `$icon('shopping-bag')` | Stores, products |
|
|
| `shopping-cart` | `$icon('shopping-cart')` | Cart |
|
|
| `credit-card` | `$icon('credit-card')` | Payment |
|
|
| `currency-dollar` | `$icon('currency-dollar')` | Money, pricing |
|
|
| `gift` | `$icon('gift')` | Promotions, gifts |
|
|
| `tag` | `$icon('tag')` | Tags, categories |
|
|
| `truck` | `$icon('truck')` | Shipping, delivery |
|
|
| `receipt` | `$icon('receipt')` | Orders, receipts |
|
|
|
|
### Inventory & Product Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `cube` | `$icon('cube')` | Products, packages |
|
|
| `collection` | `$icon('collection')` | Collections, catalog |
|
|
| `photograph` | `$icon('photograph')` | Images, media |
|
|
| `color-swatch` | `$icon('color-swatch')` | Variants, colors |
|
|
| `template` | `$icon('template')` | Templates, layouts |
|
|
| `clipboard-list` | `$icon('clipboard-list')` | Lists, inventory |
|
|
|
|
### Analytics & Reports
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `chart` | `$icon('chart')` | Analytics, stats |
|
|
| `trending-up` | `$icon('trending-up')` | Growth, increase |
|
|
| `trending-down` | `$icon('trending-down')` | Decline, decrease |
|
|
| `presentation-chart-line` | `$icon('presentation-chart-line')` | Reports, presentations |
|
|
| `calculator` | `$icon('calculator')` | Calculations, math |
|
|
|
|
### Communication Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `bell` | `$icon('bell')` | Notifications |
|
|
| `mail` | `$icon('mail')` | Email, messages |
|
|
| `chat` | `$icon('chat')` | Chat, messaging |
|
|
| `annotation` | `$icon('annotation')` | Comments, notes |
|
|
| `phone` | `$icon('phone')` | Phone, call |
|
|
|
|
### System & Settings
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `cog` | `$icon('cog')` | Settings, configuration |
|
|
| `sun` | `$icon('sun')` | Light theme |
|
|
| `moon` | `$icon('moon')` | Dark theme |
|
|
| `database` | `$icon('database')` | Database, storage |
|
|
| `server` | `$icon('server')` | Server, hosting |
|
|
| `shield-check` | `$icon('shield-check')` | Security, verified |
|
|
| `key` | `$icon('key')` | API keys, passwords |
|
|
| `lock-closed` | `$icon('lock-closed')` | Locked, secure |
|
|
| `lock-open` | `$icon('lock-open')` | Unlocked |
|
|
|
|
### Document & File Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `document` | `$icon('document')` | Documents, files |
|
|
| `folder` | `$icon('folder')` | Folders, directories |
|
|
| `folder-open` | `$icon('folder-open')` | Open folder |
|
|
| `download` | `$icon('download')` | Download action |
|
|
| `upload` | `$icon('upload')` | Upload action |
|
|
|
|
### Time & Calendar
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `calendar` | `$icon('calendar')` | Calendar, dates |
|
|
| `clock` | `$icon('clock')` | Time, schedule |
|
|
|
|
### Location Icons
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `location-marker` | `$icon('location-marker')` | Location, address |
|
|
| `globe` | `$icon('globe')` | International, language |
|
|
|
|
### Status & Indicators
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `exclamation` | `$icon('exclamation')` | Warning, alert |
|
|
| `information-circle` | `$icon('information-circle')` | Information, help |
|
|
| `spinner` | `$icon('spinner')` | Loading state |
|
|
| `star` | `$icon('star')` | Favorites, ratings |
|
|
| `heart` | `$icon('heart')` | Likes, favorites |
|
|
| `flag` | `$icon('flag')` | Reports, flags |
|
|
|
|
### Links & External
|
|
| Icon Name | Usage | Description |
|
|
|-----------|-------|-------------|
|
|
| `external-link` | `$icon('external-link')` | Open in new tab |
|
|
| `link` | `$icon('link')` | URL, hyperlink |
|
|
| `logout` | `$icon('logout')` | Sign out |
|
|
|
|
---
|
|
|
|
## Common Usage Patterns
|
|
|
|
### Buttons with Icons
|
|
|
|
```html
|
|
<!-- Primary action button -->
|
|
<button class="btn-primary">
|
|
<span x-html="$icon('plus', 'w-4 h-4 mr-2')"></span>
|
|
Create Product
|
|
</button>
|
|
|
|
<!-- Icon-only button -->
|
|
<button class="p-2 hover:bg-gray-100 rounded">
|
|
<span x-html="$icon('edit', 'w-5 h-5 text-gray-600')"></span>
|
|
</button>
|
|
|
|
<!-- Danger button -->
|
|
<button class="btn-danger">
|
|
<span x-html="$icon('delete', 'w-4 h-4 mr-2')"></span>
|
|
Delete
|
|
</button>
|
|
```
|
|
|
|
### Status Indicators
|
|
|
|
```html
|
|
<!-- Success state -->
|
|
<div class="flex items-center text-green-600">
|
|
<span x-html="$icon('check', 'w-5 h-5 mr-2')"></span>
|
|
<span>Verified</span>
|
|
</div>
|
|
|
|
<!-- Warning state -->
|
|
<div class="flex items-center text-yellow-600">
|
|
<span x-html="$icon('exclamation', 'w-5 h-5 mr-2')"></span>
|
|
<span>Pending Review</span>
|
|
</div>
|
|
|
|
<!-- Loading state -->
|
|
<div class="flex items-center text-blue-600">
|
|
<span x-html="$icon('spinner', 'w-5 h-5 mr-2')"></span>
|
|
<span>Processing...</span>
|
|
</div>
|
|
```
|
|
|
|
### Navigation Items
|
|
|
|
```html
|
|
<!-- Sidebar navigation -->
|
|
<nav>
|
|
<a href="/dashboard" class="nav-item">
|
|
<span x-html="$icon('home', 'w-5 h-5 mr-3')"></span>
|
|
Dashboard
|
|
</a>
|
|
<a href="/products" class="nav-item">
|
|
<span x-html="$icon('cube', 'w-5 h-5 mr-3')"></span>
|
|
Products
|
|
</a>
|
|
<a href="/orders" class="nav-item">
|
|
<span x-html="$icon('shopping-cart', 'w-5 h-5 mr-3')"></span>
|
|
Orders
|
|
</a>
|
|
</nav>
|
|
```
|
|
|
|
### Form Fields
|
|
|
|
```html
|
|
<!-- Search input -->
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center">
|
|
<span x-html="$icon('search', 'w-5 h-5 text-gray-400')"></span>
|
|
</div>
|
|
<input type="text" class="pl-10" placeholder="Search...">
|
|
</div>
|
|
|
|
<!-- Password field with toggle -->
|
|
<div class="relative" x-data="{ show: false }">
|
|
<input :type="show ? 'text' : 'password'" class="pr-10">
|
|
<button @click="show = !show" class="absolute inset-y-0 right-0 pr-3">
|
|
<span x-show="!show" x-html="$icon('eye', 'w-5 h-5 text-gray-400')"></span>
|
|
<span x-show="show" x-html="$icon('eye-off', 'w-5 h-5 text-gray-400')"></span>
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
### Cards & Panels
|
|
|
|
```html
|
|
<!-- Stat card -->
|
|
<div class="bg-white p-6 rounded-lg shadow">
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<p class="text-gray-500 text-sm">Total Sales</p>
|
|
<p class="text-2xl font-bold">$12,345</p>
|
|
</div>
|
|
<div class="p-3 bg-blue-100 rounded-full">
|
|
<span x-html="$icon('currency-dollar', 'w-6 h-6 text-blue-600')"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### Dropdown Menus
|
|
|
|
```html
|
|
<div x-data="{ open: false }" class="relative">
|
|
<button @click="open = !open" class="flex items-center">
|
|
<span>Options</span>
|
|
<span x-html="$icon('chevron-down', 'w-4 h-4 ml-2')"></span>
|
|
</button>
|
|
|
|
<div x-show="open" class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg">
|
|
<a href="#" class="flex items-center px-4 py-2 hover:bg-gray-100">
|
|
<span x-html="$icon('edit', 'w-4 h-4 mr-2')"></span>
|
|
Edit
|
|
</a>
|
|
<a href="#" class="flex items-center px-4 py-2 hover:bg-gray-100">
|
|
<span x-html="$icon('duplicate', 'w-4 h-4 mr-2')"></span>
|
|
Duplicate
|
|
</a>
|
|
<a href="#" class="flex items-center px-4 py-2 text-red-600 hover:bg-gray-100">
|
|
<span x-html="$icon('delete', 'w-4 h-4 mr-2')"></span>
|
|
Delete
|
|
</a>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
---
|
|
|
|
## Size Guidelines
|
|
|
|
| Class | Size | Use Case |
|
|
|-------|------|----------|
|
|
| `w-3 h-3` | 12px | Inline text icons |
|
|
| `w-4 h-4` | 16px | Small buttons, badges |
|
|
| `w-5 h-5` | 20px | Default size, most UI elements |
|
|
| `w-6 h-6` | 24px | Larger buttons, headers |
|
|
| `w-8 h-8` | 32px | Featured icons, empty states |
|
|
| `w-12 h-12` | 48px | Large feature displays |
|
|
|
|
---
|
|
|
|
## Color Patterns
|
|
|
|
```html
|
|
<!-- Semantic colors -->
|
|
<span x-html="$icon('check', 'w-5 h-5 text-green-600')"></span> <!-- Success -->
|
|
<span x-html="$icon('exclamation', 'w-5 h-5 text-yellow-600')"></span> <!-- Warning -->
|
|
<span x-html="$icon('close', 'w-5 h-5 text-red-600')"></span> <!-- Error -->
|
|
<span x-html="$icon('information-circle', 'w-5 h-5 text-blue-600')"></span> <!-- Info -->
|
|
|
|
<!-- Gray scale -->
|
|
<span x-html="$icon('user', 'w-5 h-5 text-gray-400')"></span> <!-- Muted -->
|
|
<span x-html="$icon('user', 'w-5 h-5 text-gray-600')"></span> <!-- Normal -->
|
|
<span x-html="$icon('user', 'w-5 h-5 text-gray-900')"></span> <!-- Emphasized -->
|
|
|
|
<!-- With hover states -->
|
|
<button class="group">
|
|
<span x-html="$icon('edit', 'w-5 h-5 text-gray-400 group-hover:text-gray-600')"></span>
|
|
</button>
|
|
```
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
### ✅ Do
|
|
|
|
- Use consistent icon sizes within the same context
|
|
- Match icon color with text color for visual harmony
|
|
- Use semantic colors for status indicators
|
|
- Include descriptive text for accessibility
|
|
- Use the `$icon()` helper for cleaner templates
|
|
|
|
### ❌ Don't
|
|
|
|
- Mix icon styles (outline vs solid) inconsistently
|
|
- Use icons without considering their meaning
|
|
- Make icons too small to recognize (< 16px)
|
|
- Rely solely on icons without text labels for important actions
|
|
- Use decorative icons excessively
|
|
|
|
---
|
|
|
|
## Adding New Icons
|
|
|
|
To add a new icon to the system:
|
|
|
|
1. Find the icon in [Heroicons](https://heroicons.com/)
|
|
2. Copy the SVG path data
|
|
3. Add to the `Icons` object in `icons.js`:
|
|
|
|
```javascript
|
|
'new-icon-name': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="YOUR_PATH_DATA"/>
|
|
</svg>`
|
|
```
|
|
|
|
4. Update this guide with the new icon
|
|
|
|
---
|
|
|
|
## Browser Support
|
|
|
|
The icon system works in all modern browsers:
|
|
- Chrome/Edge (latest)
|
|
- Firefox (latest)
|
|
- Safari (latest)
|
|
- Mobile browsers (iOS Safari, Chrome Mobile)
|
|
|
|
---
|
|
|
|
## Performance Notes
|
|
|
|
- Icons are inline SVG - no additional HTTP requests
|
|
- Total icon library size: ~15KB uncompressed
|
|
- Minimal impact on page load time
|
|
- Icons render instantly with the page
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
**Icon not displaying?**
|
|
- Check that `icons.js` is loaded before Alpine.js
|
|
- Verify the icon name exists in the Icons object
|
|
- Check browser console for warnings
|
|
|
|
**Icon wrong size?**
|
|
- Ensure you're passing valid Tailwind size classes
|
|
- Use both width and height (e.g., `w-5 h-5`)
|
|
|
|
**Icon wrong color?**
|
|
- Add text color class (e.g., `text-gray-600`)
|
|
- Check parent element's color inheritance
|
|
|
|
---
|
|
|
|
## Related Resources
|
|
|
|
- [Heroicons Official Site](https://heroicons.com/)
|
|
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
|
- [Alpine.js Magic Properties](https://alpinejs.dev/magics/el)
|