turash/bugulma/frontend/components/ui/Logo.tsx
Damir Mukimov 6347f42e20
Consolidate repositories: Remove nested frontend .git and merge into main repository
- Remove nested git repository from bugulma/frontend/.git
- Add all frontend files to main repository tracking
- Convert from separate frontend/backend repos to unified monorepo
- Preserve all frontend code and development history as tracked files
- Eliminate nested repository complexity for simpler development workflow

This creates a proper monorepo structure with frontend and backend
coexisting in the same repository for easier development and deployment.
2025-11-25 06:02:57 +01:00

195 lines
6.4 KiB
TypeScript

import React, { useRef, useEffect } from 'react';
import {
PixelArtRenderer,
PALETTES,
createCircle,
createTriangle,
createPoint,
type LinearGradient,
type RadialGradient,
} from '@/lib/pixel-art';
interface LogoProps {
size?: number;
className?: string;
}
const Logo: React.FC<LogoProps> = ({ size = 64, className = '' }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
// Create renderer with pixel art library
const renderer = new PixelArtRenderer(
ctx,
{
width: 32,
height: 32,
pixelSize: 1,
scale: size / 32,
antialiasing: false,
},
PALETTES.warm
);
renderer.clear();
// Main crust triangle (outer layer with folded edges)
const outerCrust = createTriangle(createPoint(6, 26), createPoint(16, 4), createPoint(26, 26));
const foldedCrust = createTriangle(createPoint(9, 26), createPoint(16, 4), createPoint(23, 26));
renderer.triangle(foldedCrust, renderer.color('crustLight'));
// Crust gradient overlay
const crustGradient: LinearGradient = {
x1: 6,
y1: 4,
x2: 26,
y2: 26,
stops: [
{ offset: 0, color: renderer.color('crustMedium') },
{ offset: 0.5, color: renderer.color('crustDark') },
{ offset: 1, color: renderer.color('crustDarker') },
],
};
renderer.linearGradient(crustGradient, outerCrust);
// Crust edge outline
renderer.triangleOutline(outerCrust, renderer.color('crustEdge'), 0.8);
// Flaky crust texture lines
renderer.line(createPoint(10, 22), createPoint(16, 19), renderer.color('crustEdge'), 0.3, 0.6);
renderer.line(
createPoint(12, 23.5),
createPoint(17.5, 20.5),
renderer.color('crustEdge'),
0.3,
0.6
);
renderer.line(createPoint(14, 25), createPoint(19, 22), renderer.color('crustEdge'), 0.3, 0.6);
renderer.line(createPoint(14, 25), createPoint(14, 20), renderer.color('crustEdge'), 0.3, 0.6);
renderer.line(createPoint(18, 25), createPoint(18, 21), renderer.color('crustEdge'), 0.3, 0.6);
// Meat filling (inner triangle)
const meatFilling = createTriangle(createPoint(9, 23), createPoint(16, 9), createPoint(23, 23));
renderer.triangle(meatFilling, renderer.color('meatLight'));
// Meat gradient
const meatGradient: LinearGradient = {
x1: 9,
y1: 9,
x2: 23,
y2: 23,
stops: [
{ offset: 0, color: renderer.color('meatMedium') },
{ offset: 1, color: renderer.color('meatDark') },
],
};
renderer.linearGradient(meatGradient, meatFilling);
// Onion layers
renderer.circle(createCircle(16, 16, 3), renderer.color('onionLight'), 0.8);
renderer.circle(createCircle(14, 18, 1.5), renderer.color('onionMedium'), 0.6);
renderer.circle(createCircle(18, 19, 1.2), renderer.color('onionLight'), 0.7);
// Meat chunks
renderer.circle(createCircle(13, 15, 1), renderer.color('meatDark'));
renderer.circle(createCircle(17, 17, 0.8), renderer.color('crustDarker'));
renderer.circle(createCircle(15, 20, 0.6), renderer.color('meatDark'));
renderer.circle(createCircle(19, 18, 0.7), renderer.color('crustDarker'));
// Onion ring details
renderer.circleOutline(createCircle(16, 16, 2.5), renderer.color('onionMedium'), 0.2, 0.8);
renderer.circleOutline(createCircle(14, 18, 1), renderer.color('onionMedium'), 0.2, 0.8);
// Steam puffs with glow effect
const steamGlow1: RadialGradient = {
cx: 12,
cy: 2,
r: 2,
stops: [
{ offset: 0, color: renderer.color('steam'), alpha: 0.9 },
{ offset: 1, color: renderer.color('steam'), alpha: 0.3 },
],
};
const steamGlow2: RadialGradient = {
cx: 20,
cy: 3,
r: 2,
stops: [
{ offset: 0, color: renderer.color('steam'), alpha: 0.9 },
{ offset: 1, color: renderer.color('steam'), alpha: 0.3 },
],
};
const steamGlow3: RadialGradient = {
cx: 16,
cy: 1,
r: 1.5,
stops: [
{ offset: 0, color: renderer.color('steam'), alpha: 0.9 },
{ offset: 1, color: renderer.color('steam'), alpha: 0.3 },
],
};
// Main steam puffs
renderer.radialGradient(steamGlow1, createCircle(12, 2, 1.8));
renderer.circle(createCircle(12, 4.5, 1.2), renderer.color('steam'), 0.85);
renderer.circle(createCircle(12, 6, 0.8), renderer.color('steam'), 0.85);
renderer.radialGradient(steamGlow2, createCircle(20, 3, 1.5));
renderer.circle(createCircle(20, 5.5, 1), renderer.color('steam'), 0.85);
renderer.circle(createCircle(20, 7, 0.6), renderer.color('steam'), 0.85);
// Center steam accent
renderer.radialGradient(steamGlow3, createCircle(16, 1, 1));
renderer.circle(createCircle(16, 3, 0.7), renderer.color('steam'), 0.85);
// Stars around the pie
renderer.circle(createCircle(8, 6, 0.3), renderer.color('stars'), 0.8);
renderer.circle(createCircle(24, 7, 0.3), renderer.color('stars'), 0.8);
renderer.circle(createCircle(7, 12, 0.2), renderer.color('stars'), 0.8);
renderer.circle(createCircle(25, 13, 0.2), renderer.color('stars'), 0.8);
// Sparkles
renderer.circle(createCircle(10, 8, 0.2), renderer.color('sparkles'), 0.6);
renderer.circle(createCircle(22, 9, 0.2), renderer.color('sparkles'), 0.6);
renderer.circle(createCircle(9, 14, 0.15), renderer.color('sparkles'), 0.6);
renderer.circle(createCircle(23, 15, 0.15), renderer.color('sparkles'), 0.6);
// Little heart on top (simplified)
renderer.circle(createCircle(15, 4.5, 0.3), renderer.color('heart'), 0.9);
renderer.circle(createCircle(15.5, 4.5, 0.3), renderer.color('heart'), 0.9);
renderer.rect({ x: 14.7, y: 4.5, width: 0.6, height: 0.4 }, renderer.color('heart'), 0.9);
renderer.circle(createCircle(15.2, 4.3, 0.1), renderer.color('sparkles'), 0.7);
// Crust edge folds (bottom) - using quadratic curves
for (let i = 0; i < 6; i++) {
const x = 10 + i * 2;
renderer.line(
createPoint(x, 25),
createPoint(x + 1, 25),
renderer.color('crustEdge'),
0.3,
0.8
);
}
}, [size]);
return (
<canvas
ref={canvasRef}
className={`inline-block ${className}`}
style={{
imageRendering: 'pixelated' as const,
}}
/>
);
};
export default Logo;