459 lines
15 KiB
HTML
459 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Claude Exporter Icon Generator</title>
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
padding: 40px;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
min-height: 100vh;
|
|
}
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
background: white;
|
|
border-radius: 20px;
|
|
padding: 40px;
|
|
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
}
|
|
h1 {
|
|
color: #333;
|
|
text-align: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
.subtitle {
|
|
text-align: center;
|
|
color: #666;
|
|
margin-bottom: 40px;
|
|
}
|
|
.icon-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
gap: 30px;
|
|
margin-bottom: 40px;
|
|
}
|
|
.icon-card {
|
|
text-align: center;
|
|
padding: 20px;
|
|
border-radius: 10px;
|
|
background: #f8f9fa;
|
|
transition: transform 0.2s;
|
|
}
|
|
.icon-card:hover {
|
|
transform: translateY(-5px);
|
|
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
|
|
}
|
|
.icon-card h3 {
|
|
margin: 15px 0 10px 0;
|
|
color: #5436DA;
|
|
}
|
|
.icon-card p {
|
|
color: #666;
|
|
font-size: 14px;
|
|
margin: 5px 0;
|
|
}
|
|
canvas {
|
|
border-radius: 10px;
|
|
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
|
cursor: pointer;
|
|
transition: transform 0.2s;
|
|
}
|
|
canvas:hover {
|
|
transform: scale(1.05);
|
|
}
|
|
.controls {
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
}
|
|
button {
|
|
background: #5436DA;
|
|
color: white;
|
|
border: none;
|
|
padding: 12px 30px;
|
|
border-radius: 25px;
|
|
font-size: 16px;
|
|
cursor: pointer;
|
|
margin: 0 10px;
|
|
transition: all 0.3s;
|
|
}
|
|
button:hover {
|
|
background: #4329B8;
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 10px 20px rgba(84, 54, 218, 0.3);
|
|
}
|
|
.design-selector {
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
}
|
|
.design-btn {
|
|
background: #e0e0e0;
|
|
color: #333;
|
|
margin: 5px;
|
|
padding: 10px 20px;
|
|
}
|
|
.design-btn.active {
|
|
background: #5436DA;
|
|
color: white;
|
|
}
|
|
.popup-preview {
|
|
margin-top: 40px;
|
|
padding: 30px;
|
|
background: #f8f9fa;
|
|
border-radius: 10px;
|
|
}
|
|
.popup-preview h2 {
|
|
color: #5436DA;
|
|
margin-bottom: 20px;
|
|
}
|
|
#popupCanvas {
|
|
width: 100%;
|
|
max-width: 600px;
|
|
height: auto;
|
|
margin: 0 auto;
|
|
display: block;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>🎨 Claude Exporter Icon Generator</h1>
|
|
<p class="subtitle">Click any icon to download it, or use the buttons to download all</p>
|
|
|
|
<div class="design-selector">
|
|
<button class="design-btn active" onclick="selectDesign('modern')">Modern Export</button>
|
|
<button class="design-btn" onclick="selectDesign('chat')">Chat Bubbles</button>
|
|
<button class="design-btn" onclick="selectDesign('gradient')">Gradient Flow</button>
|
|
<button class="design-btn" onclick="selectDesign('minimal')">Minimal</button>
|
|
</div>
|
|
|
|
<div class="controls">
|
|
<button onclick="downloadAllIcons()">📥 Download All Icons</button>
|
|
<button onclick="regenerateAll()">🔄 Regenerate</button>
|
|
</div>
|
|
|
|
<div class="icon-grid">
|
|
<div class="icon-card">
|
|
<canvas id="icon16" width="16" height="16"></canvas>
|
|
<h3>16x16</h3>
|
|
<p>Toolbar icon</p>
|
|
</div>
|
|
<div class="icon-card">
|
|
<canvas id="icon48" width="48" height="48"></canvas>
|
|
<h3>48x48</h3>
|
|
<p>Extensions page</p>
|
|
</div>
|
|
<div class="icon-card">
|
|
<canvas id="icon128" width="128" height="128"></canvas>
|
|
<h3>128x128</h3>
|
|
<p>Web Store</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="popup-preview">
|
|
<h2>Popup Header Graphic</h2>
|
|
<canvas id="popupCanvas" width="600" height="150"></canvas>
|
|
<p style="text-align: center; margin-top: 20px;">
|
|
<button onclick="downloadPopupGraphic()">📥 Download Popup Graphic</button>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let currentDesign = 'modern';
|
|
|
|
function selectDesign(design) {
|
|
currentDesign = design;
|
|
document.querySelectorAll('.design-btn').forEach(btn => {
|
|
btn.classList.remove('active');
|
|
});
|
|
event.target.classList.add('active');
|
|
regenerateAll();
|
|
}
|
|
|
|
function drawModernIcon(ctx, size) {
|
|
const scale = size / 128;
|
|
ctx.clearRect(0, 0, size, size);
|
|
|
|
// Background gradient
|
|
const gradient = ctx.createLinearGradient(0, 0, size, size);
|
|
gradient.addColorStop(0, '#5436DA');
|
|
gradient.addColorStop(1, '#7B5FE8');
|
|
ctx.fillStyle = gradient;
|
|
ctx.fillRect(0, 0, size, size);
|
|
|
|
// Draw export arrow
|
|
ctx.strokeStyle = 'white';
|
|
ctx.lineWidth = 3 * scale;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'round';
|
|
|
|
// Download arrow
|
|
const centerX = size / 2;
|
|
const centerY = size * 0.45;
|
|
const arrowSize = size * 0.3;
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(centerX, centerY - arrowSize/2);
|
|
ctx.lineTo(centerX, centerY + arrowSize/2);
|
|
ctx.stroke();
|
|
|
|
// Arrow head
|
|
ctx.beginPath();
|
|
ctx.moveTo(centerX - arrowSize/3, centerY + arrowSize/4);
|
|
ctx.lineTo(centerX, centerY + arrowSize/2);
|
|
ctx.lineTo(centerX + arrowSize/3, centerY + arrowSize/4);
|
|
ctx.stroke();
|
|
|
|
// Document lines at bottom
|
|
const lineY = size * 0.75;
|
|
const lineWidth = size * 0.5;
|
|
ctx.lineWidth = 2 * scale;
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(centerX - lineWidth/2, lineY + i * size * 0.08);
|
|
ctx.lineTo(centerX + lineWidth/2 - (i * size * 0.1), lineY + i * size * 0.08);
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
|
|
function drawChatIcon(ctx, size) {
|
|
const scale = size / 128;
|
|
ctx.clearRect(0, 0, size, size);
|
|
|
|
// Background
|
|
const gradient = ctx.createRadialGradient(size/2, size/2, 0, size/2, size/2, size/2);
|
|
gradient.addColorStop(0, '#6B5FE8');
|
|
gradient.addColorStop(1, '#5436DA');
|
|
ctx.fillStyle = gradient;
|
|
ctx.fillRect(0, 0, size, size);
|
|
|
|
// Chat bubbles
|
|
ctx.fillStyle = 'white';
|
|
|
|
// First bubble (left)
|
|
const bubble1X = size * 0.25;
|
|
const bubble1Y = size * 0.3;
|
|
const bubble1W = size * 0.4;
|
|
const bubble1H = size * 0.25;
|
|
|
|
ctx.beginPath();
|
|
ctx.roundRect(bubble1X, bubble1Y, bubble1W, bubble1H, 4 * scale);
|
|
ctx.fill();
|
|
|
|
// Second bubble (right)
|
|
const bubble2X = size * 0.35;
|
|
const bubble2Y = size * 0.6;
|
|
const bubble2W = size * 0.4;
|
|
const bubble2H = size * 0.25;
|
|
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
|
|
ctx.beginPath();
|
|
ctx.roundRect(bubble2X, bubble2Y, bubble2W, bubble2H, 4 * scale);
|
|
ctx.fill();
|
|
|
|
// Export arrow overlay
|
|
ctx.strokeStyle = '#5436DA';
|
|
ctx.lineWidth = 3 * scale;
|
|
const arrowX = size * 0.7;
|
|
const arrowY = size * 0.5;
|
|
const arrowSize = size * 0.2;
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(arrowX, arrowY);
|
|
ctx.lineTo(arrowX + arrowSize, arrowY);
|
|
ctx.moveTo(arrowX + arrowSize - 5*scale, arrowY - 5*scale);
|
|
ctx.lineTo(arrowX + arrowSize, arrowY);
|
|
ctx.lineTo(arrowX + arrowSize - 5*scale, arrowY + 5*scale);
|
|
ctx.stroke();
|
|
}
|
|
|
|
function drawGradientIcon(ctx, size) {
|
|
const scale = size / 128;
|
|
ctx.clearRect(0, 0, size, size);
|
|
|
|
// Flowing gradient background
|
|
const gradient = ctx.createLinearGradient(0, 0, size, size);
|
|
gradient.addColorStop(0, '#667eea');
|
|
gradient.addColorStop(0.5, '#5436DA');
|
|
gradient.addColorStop(1, '#764ba2');
|
|
ctx.fillStyle = gradient;
|
|
ctx.fillRect(0, 0, size, size);
|
|
|
|
// Flowing lines representing data export
|
|
ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
|
|
ctx.lineWidth = 2 * scale;
|
|
ctx.lineCap = 'round';
|
|
|
|
for (let i = 0; i < 4; i++) {
|
|
ctx.beginPath();
|
|
const startY = size * (0.2 + i * 0.2);
|
|
ctx.moveTo(size * 0.2, startY);
|
|
ctx.quadraticCurveTo(
|
|
size * 0.5, startY + Math.sin(i) * size * 0.1,
|
|
size * 0.8, startY + size * 0.1
|
|
);
|
|
ctx.stroke();
|
|
}
|
|
|
|
// Central export symbol
|
|
ctx.fillStyle = 'white';
|
|
ctx.font = `bold ${size * 0.4}px Arial`;
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'middle';
|
|
ctx.fillText('↓', size/2, size/2);
|
|
}
|
|
|
|
function drawMinimalIcon(ctx, size) {
|
|
const scale = size / 128;
|
|
ctx.clearRect(0, 0, size, size);
|
|
|
|
// Simple white background
|
|
ctx.fillStyle = '#5436DA';
|
|
ctx.fillRect(0, 0, size, size);
|
|
|
|
// Minimalist export symbol
|
|
ctx.strokeStyle = 'white';
|
|
ctx.fillStyle = 'white';
|
|
ctx.lineWidth = Math.max(2, 3 * scale);
|
|
ctx.lineCap = 'round';
|
|
|
|
const centerX = size / 2;
|
|
const centerY = size / 2;
|
|
const boxSize = size * 0.5;
|
|
|
|
// Box
|
|
ctx.strokeRect(centerX - boxSize/2, centerY - boxSize/2 + size*0.1, boxSize, boxSize * 0.7);
|
|
|
|
// Arrow
|
|
ctx.beginPath();
|
|
ctx.moveTo(centerX, centerY - boxSize/2);
|
|
ctx.lineTo(centerX, centerY + boxSize/4);
|
|
ctx.stroke();
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(centerX - boxSize/4, centerY);
|
|
ctx.lineTo(centerX, centerY + boxSize/4);
|
|
ctx.lineTo(centerX + boxSize/4, centerY);
|
|
ctx.stroke();
|
|
}
|
|
|
|
function drawIcon(canvasId, size) {
|
|
const canvas = document.getElementById(canvasId);
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
switch(currentDesign) {
|
|
case 'chat':
|
|
drawChatIcon(ctx, size);
|
|
break;
|
|
case 'gradient':
|
|
drawGradientIcon(ctx, size);
|
|
break;
|
|
case 'minimal':
|
|
drawMinimalIcon(ctx, size);
|
|
break;
|
|
default:
|
|
drawModernIcon(ctx, size);
|
|
}
|
|
|
|
// Add click to download
|
|
canvas.onclick = () => downloadIcon(canvas, `icon${size}.png`);
|
|
}
|
|
|
|
function drawPopupGraphic() {
|
|
const canvas = document.getElementById('popupCanvas');
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
// Create gradient background
|
|
const gradient = ctx.createLinearGradient(0, 0, 600, 150);
|
|
gradient.addColorStop(0, '#667eea');
|
|
gradient.addColorStop(0.5, '#5436DA');
|
|
gradient.addColorStop(1, '#764ba2');
|
|
ctx.fillStyle = gradient;
|
|
ctx.fillRect(0, 0, 600, 150);
|
|
|
|
// Add pattern overlay
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.05)';
|
|
for (let i = 0; i < 20; i++) {
|
|
ctx.beginPath();
|
|
ctx.arc(
|
|
Math.random() * 600,
|
|
Math.random() * 150,
|
|
Math.random() * 30 + 10,
|
|
0,
|
|
Math.PI * 2
|
|
);
|
|
ctx.fill();
|
|
}
|
|
|
|
// Title text
|
|
ctx.fillStyle = 'white';
|
|
ctx.font = 'bold 32px -apple-system, Arial';
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'middle';
|
|
ctx.fillText('Claude Conversation Exporter', 300, 60);
|
|
|
|
// Subtitle
|
|
ctx.font = '16px -apple-system, Arial';
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
|
|
ctx.fillText('Export • Browse • Archive', 300, 95);
|
|
|
|
// Decorative elements
|
|
ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
|
|
ctx.lineWidth = 2;
|
|
|
|
// Left decoration
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 75);
|
|
ctx.lineTo(150, 75);
|
|
ctx.stroke();
|
|
|
|
// Right decoration
|
|
ctx.beginPath();
|
|
ctx.moveTo(450, 75);
|
|
ctx.lineTo(550, 75);
|
|
ctx.stroke();
|
|
}
|
|
|
|
function downloadIcon(canvas, filename) {
|
|
canvas.toBlob(blob => {
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = filename;
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
});
|
|
}
|
|
|
|
function downloadAllIcons() {
|
|
downloadIcon(document.getElementById('icon16'), 'icon16.png');
|
|
setTimeout(() => {
|
|
downloadIcon(document.getElementById('icon48'), 'icon48.png');
|
|
}, 100);
|
|
setTimeout(() => {
|
|
downloadIcon(document.getElementById('icon128'), 'icon128.png');
|
|
}, 200);
|
|
}
|
|
|
|
function downloadPopupGraphic() {
|
|
const canvas = document.getElementById('popupCanvas');
|
|
downloadIcon(canvas, 'popup-header.png');
|
|
}
|
|
|
|
function regenerateAll() {
|
|
drawIcon('icon16', 16);
|
|
drawIcon('icon48', 48);
|
|
drawIcon('icon128', 128);
|
|
drawPopupGraphic();
|
|
}
|
|
|
|
// Initialize on load
|
|
window.onload = regenerateAll;
|
|
</script>
|
|
</body>
|
|
</html>
|