Setting the file. One moment. Preview · SVG Design · tryopendata/skills · Skills DocsRaw file
assets/preview.html
HTML·177 lines·7 KB
:
0
;
box-sizing
:
border-box
; }
8 body { font-family: system-ui, sans-serif; padding: 40px 40px 120px; background: #f8f9fa; }
9 h1 { margin-bottom: 8px; font-size: 24px; }
10 .sub { color: #666; margin-bottom: 32px; }
11 .section { margin-bottom: 48px; }
12 .section h2 { font-size: 16px; color: #888; text-transform: uppercase; letter-spacing: 0.05em;
13 margin-bottom: 16px; border-bottom: 1px solid #ddd; padding-bottom: 8px; }
14 .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 24px; }
15 .card { background: white; border-radius: 12px; padding: 12px; border: 1px solid #e5e7eb;
16 cursor: pointer; transition: outline 0.15s; }
17 .card h3 { font-size: 13px; font-weight: 600; margin-bottom: 4px; }
18 .card p { font-size: 11px; color: #9ca3af; margin-bottom: 12px; line-height: 1.4;
19 min-height: 2.5em; }
20 .sizes { display: flex; align-items: flex-end; gap: 16px;
21 background: white; border-radius: 8px; padding: 12px; }
22 .size-label { font-size: 10px; color: #9ca3af; text-align: center; }
23 .size-label img { display: block; margin: 0 auto 4px; }
24 .dark-row { background: #0d1117; padding: 12px; border-radius: 8px; margin-top: 8px;
25 display: flex; align-items: flex-end; gap: 16px; }
26 .dark-row .size-label { color: #666; }
27 .nav-preview { display: flex; align-items: center; gap: 8px; margin-top: 12px;
28 padding: 8px 12px; border: 1px solid #e5e7eb; border-radius: 6px; background: #fafafa; }
29 .nav-preview img { width: 28px; height: 28px; }
30 .nav-preview span { font-size: 16px; font-weight: 700; }
31 .nav-dark { background: #0d1117; border-color: #30363d; }
32 .nav-dark span { color: #f0f6fc; }
33 .favicon-strip { display: flex; align-items: center; gap: 6px; margin-top: 8px;
34 padding: 6px 10px; background: #dee1e6; border-radius: 8px 8px 0 0; }
35 .favicon-strip .tab { display: flex; align-items: center; gap: 6px; background: white;
36 border-radius: 8px 8px 0 0; padding: 6px 12px; font-size: 11px; color: #374151; }
37 .favicon-strip .tab img { width: 16px; height: 16px; }
38 #compare-bar { position: fixed; bottom: 0; left: 0; right: 0; background: white;
39 border-top: 2px solid #e5e7eb; padding: 16px 40px; display: flex; gap: 24px;
40 align-items: center; z-index: 10; min-height: 80px; }
41</style>
42</head>
43<body>
44<h1 id="title">Logo Options</h1>
45<p class="sub">Click any card to pin it to the comparison bar</p>
46<div id="content"></div>
47<div id="compare-bar">
48 <span style="font-size:12px;color:#9ca3af;white-space:nowrap;">Click cards to compare</span>
49</div>
50
51<!--
52 Load variant data from variants.js.
53 Expected shape of window.VARIANTS:
54 {
55 projectName: string,
56 brandName: string,
57 concepts: [{
58 name: string,
59 variants: [{
60 id: string,
61 name: string,
62 description: string,
63 light: string, // path to light SVG
64 dark: string|undefined // path to dark SVG (omit for monochrome)
65 }]
66 }]
67 }
68-->
69<script src="variants.js"></script>
70<script>
71(function () {
72 var lastDataStr = '';
73
74 function esc(s) {
75 var d = document.createElement('div');
76 d.textContent = s;
77 return d.innerHTML;
78 }
79
80 function sizeRamp(src, invert) {
81 var sizes = [16, 32, 64];
82 var filter = invert ? ' style="filter:brightness(0) invert(1)"' : '';
83 return sizes.map(function (s) {
84 return '<div class="size-label"><img src="' + src + '" width="' + s + '" height="' + s + '"' + filter + '>' + s + '</div>';
85 }).join('');
86 }
87
88 function renderCard(v, brandName) {
89 var lightSrc = v.light || '';
90 var darkSrc = v.dark || '';
91 var useDarkSrc = darkSrc || lightSrc;
92 var invert = !darkSrc;
93 var invertStyle = invert ? ' style="filter:brightness(0) invert(1)"' : '';
94
95 return '<div class="card" data-id="' + esc(v.id) + '">' +
96 '<h3>' + esc(v.id + ' - ' + v.name) + '</h3>' +
97 '<p>' + esc(v.description || '') + '</p>' +
98 '<div class="sizes">' + sizeRamp(lightSrc, false) + '</div>' +
99 '<div class="dark-row">' + sizeRamp(useDarkSrc, invert) + '</div>' +
100 '<div class="favicon-strip"><div class="tab"><img src="' + lightSrc + '">' + esc(brandName) + '</div></div>' +
101 '<div class="nav-preview"><img src="' + lightSrc + '"><span>' + esc(brandName) + '</span></div>' +
102 '<div class="nav-preview nav-dark"><img src="' + useDarkSrc + '"' + invertStyle + '><span>' + esc(brandName) + '</span></div>' +
103 '</div>';
104 }
105
106 function render() {
107 var data = window.VARIANTS;
108 if (!data) return;
109
110 var dataStr = JSON.stringify(data);
111 if (dataStr === lastDataStr) return;
112 lastDataStr = dataStr;
113
114 document.getElementById('title').textContent = data.projectName + ' Logo Options';
115 document.title = data.projectName + ' Logo Options';
116
117 var html = '';
118 (data.concepts || []).forEach(function (concept) {
119 html += '<div class="section"><h2>' + esc(concept.name) + '</h2><div class="grid">';
120 (concept.variants || []).forEach(function (v) {
121 html += renderCard(v, data.brandName || data.projectName);
122 });
123 html += '</div></div>';
124 });
125
126 document.getElementById('content').innerHTML = html;
127 }
128
129 // Click-to-compare via event delegation
130 document.getElementById('content').addEventListener('click', function (e) {
131 var card = e.target.closest('.card');
132 if (!card) return;
133 var bar = document.getElementById('compare-bar');
134 var id = card.dataset.id;
135 var existing = bar.querySelector('[data-compare-id="' + id + '"]');
136 if (existing) { existing.remove(); card.style.outline = ''; return; }
137 if (bar.querySelectorAll('.compare-item').length >= 4) return;
138 var imgSrc = card.querySelector('.sizes img');
139 if (!imgSrc) return;
140 var item = document.createElement('div');
141 item.className = 'compare-item';
142 item.dataset.compareId = id;
143 item.style.cssText = 'text-align:center;';
144 var thumb = document.createElement('img');
145 thumb.src = imgSrc.src; thumb.width = 48; thumb.height = 48;
146 thumb.style.cssText = 'display:block;margin:0 auto 4px;';
147 var label = document.createElement('div');
148 label.style.cssText = 'font-size:11px;color:#374151;';
149 label.textContent = card.querySelector('h3').textContent;
150 item.append(thumb, label);
151 bar.appendChild(item);
152 card.style.outline = '3px solid #3B82F6';
153 card.style.outlineOffset = '-3px';
154 });
155
156 // Initial render
157 render();
158
159 // Live reload: cache-bust SVG images + reload variants.js every 3s
160 setInterval(function () {
161 var t = Date.now();
162 // Cache-bust SVG images
163 document.querySelectorAll('img[src*=".svg"]').forEach(function (img) {
164 var base = img.src.split('?')[0];
165 img.src = base + '?t=' + t;
166 });
167 // Reload variants.js via script injection, re-render if data changed
168 var s = document.createElement('script');
169 s.src = 'variants.js?t=' + t;
170 s.onload = function () { render(); s.remove(); };
171 s.onerror = function () { s.remove(); };
172 document.head.appendChild(s);
173 }, 3000);
174})();
175</script>
176</body>
177</html>