Files
prestashop-icons/preview.html
myprestarocks 99a8f5bf9b Add shape prefix to symbol IDs, fix brand naming, add assets
- Symbol IDs now include shape for uniqueness: {shape}_{brand}_{mode}
  e.g., text-only_paypal_lm, rectangle_visa_la, icon_mastercard_dm
- Fixed brand name inconsistencies:
  - amazon_pay → amazon
  - naverpay → naver_pay
  - p24 → przelewy24
  - direct_debit → bacs (unified BACS Direct Debit name)
- Added font assets (FontAwesome, Material Icons)
- Added MprIconsAssets and MprIconsConfig classes
- Updated preview.html with shape parameter support
- All 752 icons complete (38 payment × 4 shapes × 4 modes + 12 social × 3 shapes × 4 modes)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 10:17:23 +00:00

459 lines
22 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PrestaShop Icons Preview</title>
<style>
* { box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0; padding: 20px;
background: #f5f5f5;
color: #333;
transition: background 0.3s, color 0.3s;
}
body.dark-theme {
background: #1a1a1a;
color: #eee;
}
h1 { margin: 0 0 20px; }
h2 { margin: 30px 0 10px; padding: 10px; background: #333; color: #fff; border-radius: 4px; }
body.dark-theme h2 { background: #444; }
h3 { margin: 20px 0 10px; color: #666; border-bottom: 1px solid #ddd; padding-bottom: 5px; }
body.dark-theme h3 { color: #aaa; border-color: #444; }
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.theme-switch {
display: flex;
align-items: center;
gap: 10px;
}
.switch {
position: relative;
width: 60px;
height: 30px;
}
.switch input { opacity: 0; width: 0; height: 0; }
.slider {
position: absolute;
cursor: pointer;
top: 0; left: 0; right: 0; bottom: 0;
background: #ccc;
border-radius: 30px;
transition: 0.3s;
}
.slider:before {
position: absolute;
content: "";
height: 22px;
width: 22px;
left: 4px;
bottom: 4px;
background: white;
border-radius: 50%;
transition: 0.3s;
}
input:checked + .slider { background: #333; }
input:checked + .slider:before { transform: translateX(30px); }
.theme-label { font-size: 14px; }
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 15px;
margin-bottom: 30px;
}
.grid-wide {
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}
.icon-box {
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
text-align: center;
transition: all 0.3s;
}
body.dark-theme .icon-box {
background: #2a2a2a;
border-color: #444;
}
.icon-box:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
body.dark-theme .icon-box:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.5); }
.icon-box.dark { background: #1a1a1a; border-color: #333; }
body.dark-theme .icon-box.dark { background: #0a0a0a; border-color: #222; }
.icon-box svg { display: block; margin: 0 auto 10px; }
.icon-box span { font-size: 11px; color: #666; word-break: break-all; }
body.dark-theme .icon-box span { color: #999; }
.icon-box.dark span { color: #999; }
.tabs { display: flex; gap: 5px; margin-bottom: 20px; flex-wrap: wrap; }
.tab {
padding: 8px 16px;
background: #ddd;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
body.dark-theme .tab { background: #444; color: #eee; }
.tab.active { background: #333; color: #fff; }
body.dark-theme .tab.active { background: #666; }
.section { display: none; }
.section.active { display: block; }
</style>
</head>
<body>
<div class="header">
<h1>PrestaShop Icons Preview</h1>
<div class="theme-switch">
<span class="theme-label">Light</span>
<label class="switch">
<input type="checkbox" id="themeToggle" onchange="toggleTheme()">
<span class="slider"></span>
</label>
<span class="theme-label">Dark</span>
</div>
</div>
<div class="tabs">
<button class="tab active" onclick="showSection('payments')">Payment Icons</button>
<button class="tab" onclick="showSection('socials')">Social Icons</button>
</div>
<div id="payments" class="section active">
<h2>Payment Icons</h2>
<h3>Icon (logo mark only) - Light Accent</h3>
<div class="grid" id="payments-icon-la"></div>
<h3>Icon (logo mark only) - Dark Accent on Dark Background</h3>
<div class="grid" id="payments-icon-da"></div>
<h3>Icon (logo mark only) - Light Mode (monochrome)</h3>
<div class="grid" id="payments-icon-lm"></div>
<h3>Icon (logo mark only) - Dark Mode (monochrome) on Dark Background</h3>
<div class="grid" id="payments-icon-dm"></div>
<h3>Square (logo in square frame) - Light Accent</h3>
<div class="grid" id="payments-square-la"></div>
<h3>Square (logo in square frame) - Dark Accent on Dark Background</h3>
<div class="grid" id="payments-square-da"></div>
<h3>Square (logo in square frame) - Light Mode (monochrome)</h3>
<div class="grid" id="payments-square-lm"></div>
<h3>Square (logo in square frame) - Dark Mode (monochrome) on Dark Background</h3>
<div class="grid" id="payments-square-dm"></div>
<h3>Rectangle (icon + brand text, 150×100) - Light Accent</h3>
<div class="grid grid-wide" id="payments-rectangle-la"></div>
<h3>Rectangle (icon + brand text, 150×100) - Dark Accent on Dark Background</h3>
<div class="grid grid-wide" id="payments-rectangle-da"></div>
<h3>Rectangle (icon + brand text, 150×100) - Light Mode (monochrome)</h3>
<div class="grid grid-wide" id="payments-rectangle-lm"></div>
<h3>Rectangle (icon + brand text, 150×100) - Dark Mode (monochrome) on Dark Background</h3>
<div class="grid grid-wide" id="payments-rectangle-dm"></div>
<h3>Text Only (brand name) - Light Accent</h3>
<div class="grid grid-wide" id="payments-text-only-la"></div>
<h3>Text Only (brand name) - Dark Accent on Dark Background</h3>
<div class="grid grid-wide" id="payments-text-only-da"></div>
<h3>Text Only (brand name) - Light Mode (monochrome)</h3>
<div class="grid grid-wide" id="payments-text-only-lm"></div>
<h3>Text Only (brand name) - Dark Mode (monochrome) on Dark Background</h3>
<div class="grid grid-wide" id="payments-text-only-dm"></div>
</div>
<div id="socials" class="section">
<h2>Social Icons</h2>
<h3>Icon (logo mark only) - Light Accent</h3>
<div class="grid" id="socials-icon-la"></div>
<h3>Icon (logo mark only) - Dark Accent on Dark Background</h3>
<div class="grid" id="socials-icon-da"></div>
<h3>Icon (logo mark only) - Light Mode (monochrome)</h3>
<div class="grid" id="socials-icon-lm"></div>
<h3>Icon (logo mark only) - Dark Mode (monochrome) on Dark Background</h3>
<div class="grid" id="socials-icon-dm"></div>
<h3>Full Logo (icon + brand text, 150×100) - Light Accent</h3>
<div class="grid grid-wide" id="socials-full-logo-la"></div>
<h3>Full Logo (icon + brand text, 150×100) - Dark Accent on Dark Background</h3>
<div class="grid grid-wide" id="socials-full-logo-da"></div>
<h3>Full Logo (icon + brand text, 150×100) - Light Mode (monochrome)</h3>
<div class="grid grid-wide" id="socials-full-logo-lm"></div>
<h3>Full Logo (icon + brand text, 150×100) - Dark Mode (monochrome) on Dark Background</h3>
<div class="grid grid-wide" id="socials-full-logo-dm"></div>
<h3>Text Only (brand name) - Light Accent</h3>
<div class="grid grid-wide" id="socials-text-only-la"></div>
<h3>Text Only (brand name) - Dark Accent on Dark Background</h3>
<div class="grid grid-wide" id="socials-text-only-da"></div>
<h3>Text Only (brand name) - Light Mode (monochrome)</h3>
<div class="grid grid-wide" id="socials-text-only-lm"></div>
<h3>Text Only (brand name) - Dark Mode (monochrome) on Dark Background</h3>
<div class="grid grid-wide" id="socials-text-only-dm"></div>
</div>
<script>
const paymentBrands = [
'afterpay', 'alipay', 'alma', 'amazon', 'american_express', 'apple_pay',
'bacs', 'bancontact', 'bank', 'billie', 'blik', 'cartes_bancaires', 'cod',
'credit_pay', 'eps', 'google_pay', 'ideal', 'jcb', 'kakao_pay', 'klarna',
'link', 'mastercard', 'mobilepay', 'multibanco', 'naver_pay', 'przelewy24', 'payco',
'paypal', 'pickup', 'point_of_sale', 'quote', 'revolut', 'samsung_pay', 'satispay',
'sepa', 'twint', 'visa', 'wechat_pay'
];
const socialBrands = [
'amazon', 'apple', 'facebook', 'google', 'linkedin', 'microsoft',
'outlook', 'paypal', 'reddit', 'tiktok', 'x', 'yahoo'
];
function renderIcons(containerId, brands, spriteFile, suffix, size, isDark = false, shape = 'icon') {
const container = document.getElementById(containerId);
if (!container) return;
console.log(`[${containerId}] Loading sprite: ${spriteFile}`);
// Load sprite
fetch(spriteFile)
.then(r => {
console.log(`[${containerId}] Fetch status: ${r.status}`);
return r.text();
})
.then(svg => {
// Insert hidden sprite with unique ID
// Use position:absolute + clip instead of display:none to keep gradients/clipPaths working
const spriteId = `sprite-${containerId}`;
const div = document.createElement('div');
div.id = spriteId;
div.style.cssText = 'position:absolute;width:0;height:0;overflow:hidden;';
div.innerHTML = svg;
document.body.appendChild(div);
// Find all symbols in this sprite
const symbols = div.querySelectorAll('symbol');
const symbolIds = Array.from(symbols).map(s => s.id);
console.log(`[${containerId}] Found ${symbols.length} symbols:`, symbolIds);
// Render icons - symbol ID format: {shape}_{brand}_{mode}
brands.forEach(brand => {
const id = `${shape}_${brand}_${suffix}`;
const exists = symbolIds.includes(id);
if (!exists) {
console.warn(`[${containerId}] MISSING symbol: #${id}`);
}
const box = document.createElement('div');
box.className = 'icon-box' + (isDark ? ' dark' : '') + (exists ? '' : ' missing');
box.innerHTML = `
<svg width="${size}" height="${size}" style="${exists ? '' : 'border: 2px dashed red;'}">
<use href="#${id}"></use>
</svg>
<span>${brand}${exists ? '' : ' (MISSING)'}</span>
`;
container.appendChild(box);
// Check if symbol has content
if (exists) {
const symbol = div.querySelector(`#${id}`);
const content = symbol ? symbol.innerHTML.trim() : '';
if (!content) {
console.warn(`[${containerId}] EMPTY symbol: #${id}`);
} else {
// Check for references in the symbol
const urls = content.match(/url\(#([^)]+)\)/g) || [];
const hrefs = content.match(/href="#([^"]+)"/g) || [];
if (urls.length || hrefs.length) {
console.log(`[${containerId}] ${id} references:`, [...urls, ...hrefs]);
// Check if references exist
[...urls, ...hrefs].forEach(ref => {
const refId = ref.match(/#([^)"]+)/)?.[1];
if (refId && !document.getElementById(refId)) {
console.error(`[${containerId}] BROKEN REF in ${id}: #${refId} not found in DOM`);
}
});
}
}
}
});
})
.catch(e => {
console.error(`[${containerId}] Error:`, e);
container.innerHTML = `<p>Error loading ${spriteFile}: ${e.message}</p>`;
});
}
// Render wide icons (150x100 aspect ratio)
function renderIconsWide(containerId, brands, spriteFile, suffix, width, height, isDark = false, shape = 'rectangle') {
const container = document.getElementById(containerId);
if (!container) return;
fetch(spriteFile)
.then(r => r.text())
.then(svg => {
const spriteId = `sprite-${containerId}`;
const div = document.createElement('div');
div.id = spriteId;
div.style.cssText = 'position:absolute;width:0;height:0;overflow:hidden;';
div.innerHTML = svg;
document.body.appendChild(div);
const symbols = div.querySelectorAll('symbol');
const symbolIds = Array.from(symbols).map(s => s.id);
// Symbol ID format: {shape}_{brand}_{mode}
brands.forEach(brand => {
const id = `${shape}_${brand}_${suffix}`;
const exists = symbolIds.includes(id);
if (!exists) {
console.warn(`[${containerId}] MISSING symbol: #${id}`);
}
const box = document.createElement('div');
box.className = 'icon-box' + (isDark ? ' dark' : '') + (exists ? '' : ' missing');
box.innerHTML = `
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" style="${exists ? '' : 'border: 2px dashed red;'}">
<use href="#${id}"></use>
</svg>
<span>${brand}${exists ? '' : ' (MISSING)'}</span>
`;
container.appendChild(box);
});
})
.catch(e => {
console.error(`[${containerId}] Error:`, e);
container.innerHTML = `<p>Error loading ${spriteFile}: ${e.message}</p>`;
});
}
// Debug: Check for invisible icons after render
function debugInvisibleIcons() {
document.querySelectorAll('.icon-box').forEach(box => {
const svg = box.querySelector('svg');
const use = box.querySelector('use');
const label = box.querySelector('span')?.textContent || 'unknown';
if (!use) return;
const href = use.getAttribute('href');
const symbolId = href?.replace('#', '');
const symbol = document.getElementById(symbolId);
if (symbol) {
// Check if symbol has visible paths
const paths = symbol.querySelectorAll('path, rect, circle, polygon, g');
const hasVisibleContent = paths.length > 0;
// Check if any path has fill or stroke
let hasColor = false;
paths.forEach(p => {
const fill = p.getAttribute('fill') || p.style.fill;
const stroke = p.getAttribute('stroke') || p.style.stroke;
if ((fill && fill !== 'none') || (stroke && stroke !== 'none')) {
hasColor = true;
}
});
if (!hasVisibleContent) {
console.error(`NO CONTENT: ${label} (${symbolId}) - no paths/shapes found`);
} else if (!hasColor) {
console.warn(`NO COLOR: ${label} (${symbolId}) - shapes exist but no fill/stroke`);
}
}
});
console.log('Debug check complete. Look for NO CONTENT or NO COLOR warnings above.');
}
// Run debug after all sprites loaded
setTimeout(debugInvisibleIcons, 2000);
// Payment icons - Icon
renderIcons('payments-icon-la', paymentBrands, 'sprites/payments/icon-la.svg', 'la', 45, false, 'icon');
renderIcons('payments-icon-da', paymentBrands, 'sprites/payments/icon-da.svg', 'da', 45, true, 'icon');
renderIcons('payments-icon-lm', paymentBrands, 'sprites/payments/icon-lm.svg', 'lm', 45, false, 'icon');
renderIcons('payments-icon-dm', paymentBrands, 'sprites/payments/icon-dm.svg', 'dm', 45, true, 'icon');
// Payment icons - Square
renderIcons('payments-square-la', paymentBrands, 'sprites/payments/square-la.svg', 'la', 45, false, 'square');
renderIcons('payments-square-da', paymentBrands, 'sprites/payments/square-da.svg', 'da', 45, true, 'square');
renderIcons('payments-square-lm', paymentBrands, 'sprites/payments/square-lm.svg', 'lm', 45, false, 'square');
renderIcons('payments-square-dm', paymentBrands, 'sprites/payments/square-dm.svg', 'dm', 45, true, 'square');
// Payment icons - Rectangle
renderIconsWide('payments-rectangle-la', paymentBrands, 'sprites/payments/rectangle-la.svg', 'la', 150, 100, false, 'rectangle');
renderIconsWide('payments-rectangle-da', paymentBrands, 'sprites/payments/rectangle-da.svg', 'da', 150, 100, true, 'rectangle');
renderIconsWide('payments-rectangle-lm', paymentBrands, 'sprites/payments/rectangle-lm.svg', 'lm', 150, 100, false, 'rectangle');
renderIconsWide('payments-rectangle-dm', paymentBrands, 'sprites/payments/rectangle-dm.svg', 'dm', 150, 100, true, 'rectangle');
// Payment icons - Text Only
renderIconsWide('payments-text-only-la', paymentBrands, 'sprites/payments/text-only-la.svg', 'la', 150, 100, false, 'text-only');
renderIconsWide('payments-text-only-da', paymentBrands, 'sprites/payments/text-only-da.svg', 'da', 150, 100, true, 'text-only');
renderIconsWide('payments-text-only-lm', paymentBrands, 'sprites/payments/text-only-lm.svg', 'lm', 150, 100, false, 'text-only');
renderIconsWide('payments-text-only-dm', paymentBrands, 'sprites/payments/text-only-dm.svg', 'dm', 150, 100, true, 'text-only');
// Social icons - Icon
renderIcons('socials-icon-la', socialBrands, 'sprites/socials/icon-la.svg', 'la', 45, false, 'icon');
renderIcons('socials-icon-da', socialBrands, 'sprites/socials/icon-da.svg', 'da', 45, true, 'icon');
renderIcons('socials-icon-lm', socialBrands, 'sprites/socials/icon-lm.svg', 'lm', 45, false, 'icon');
renderIcons('socials-icon-dm', socialBrands, 'sprites/socials/icon-dm.svg', 'dm', 45, true, 'icon');
// Social icons - Full Logo
renderIconsWide('socials-full-logo-la', socialBrands, 'sprites/socials/full-logo-la.svg', 'la', 150, 100, false, 'full-logo');
renderIconsWide('socials-full-logo-da', socialBrands, 'sprites/socials/full-logo-da.svg', 'da', 150, 100, true, 'full-logo');
renderIconsWide('socials-full-logo-lm', socialBrands, 'sprites/socials/full-logo-lm.svg', 'lm', 150, 100, false, 'full-logo');
renderIconsWide('socials-full-logo-dm', socialBrands, 'sprites/socials/full-logo-dm.svg', 'dm', 150, 100, true, 'full-logo');
// Social icons - Text Only
renderIconsWide('socials-text-only-la', socialBrands, 'sprites/socials/text-only-la.svg', 'la', 150, 100, false, 'text-only');
renderIconsWide('socials-text-only-da', socialBrands, 'sprites/socials/text-only-da.svg', 'da', 150, 100, true, 'text-only');
renderIconsWide('socials-text-only-lm', socialBrands, 'sprites/socials/text-only-lm.svg', 'lm', 150, 100, false, 'text-only');
renderIconsWide('socials-text-only-dm', socialBrands, 'sprites/socials/text-only-dm.svg', 'dm', 150, 100, true, 'text-only');
function showSection(name) {
document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.getElementById(name).classList.add('active');
event.target.classList.add('active');
}
function toggleTheme() {
document.body.classList.toggle('dark-theme');
localStorage.setItem('theme', document.body.classList.contains('dark-theme') ? 'dark' : 'light');
}
// Load saved theme
if (localStorage.getItem('theme') === 'dark') {
document.body.classList.add('dark-theme');
document.getElementById('themeToggle').checked = true;
}
</script>
</body>
</html>