Feat: Custom SVG mascot Aubix integrated for stable HF deployment (Phase 9 UI)
Browse files
frontend/src/components/AubixIcon.tsx
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react';
|
| 2 |
+
import { motion } from 'framer-motion';
|
| 3 |
+
|
| 4 |
+
const AubixIcon: React.FC<{ size?: number; className?: string }> = ({ size = 100, className }) => {
|
| 5 |
+
return (
|
| 6 |
+
<motion.svg
|
| 7 |
+
width={size}
|
| 8 |
+
height={size}
|
| 9 |
+
viewBox="0 0 200 200"
|
| 10 |
+
fill="none"
|
| 11 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 12 |
+
className={className}
|
| 13 |
+
initial={{ y: 0 }}
|
| 14 |
+
animate={{ y: [0, -10, 0] }}
|
| 15 |
+
transition={{ repeat: Infinity, duration: 3, ease: "easeInOut" }}
|
| 16 |
+
>
|
| 17 |
+
{/* Robot Head / Helmet */}
|
| 18 |
+
<circle cx="100" cy="80" r="60" fill="#1A1A1A" stroke="#6E59FF" strokeWidth="4" />
|
| 19 |
+
<path d="M60 80C60 57.9086 77.9086 40 100 40C122.091 40 140 57.9086 140 80V90H60V80Z" fill="#2A2A2A" />
|
| 20 |
+
|
| 21 |
+
{/* Face Screen */}
|
| 22 |
+
<rect x="70" y="65" width="60" height="35" rx="10" fill="#000" stroke="#00F0FF" strokeWidth="2" />
|
| 23 |
+
|
| 24 |
+
{/* Glowing Eyes */}
|
| 25 |
+
<motion.circle
|
| 26 |
+
cx="85" cy="82" r="5" fill="#00F0FF"
|
| 27 |
+
animate={{ opacity: [1, 0.3, 1] }}
|
| 28 |
+
transition={{ repeat: Infinity, duration: 2 }}
|
| 29 |
+
/>
|
| 30 |
+
<motion.circle
|
| 31 |
+
cx="115" cy="82" r="5" fill="#00F0FF"
|
| 32 |
+
animate={{ opacity: [1, 0.3, 1] }}
|
| 33 |
+
transition={{ repeat: Infinity, duration: 2, delay: 0.2 }}
|
| 34 |
+
/>
|
| 35 |
+
|
| 36 |
+
{/* Tentacles (Techno-organic) */}
|
| 37 |
+
<path d="M70 130C50 150 30 140 20 160" stroke="#6E59FF" strokeWidth="8" strokeLinecap="round" />
|
| 38 |
+
<path d="M90 140C85 170 80 180 85 190" stroke="#6E59FF" strokeWidth="8" strokeLinecap="round" />
|
| 39 |
+
<path d="M110 140C115 170 120 180 115 190" stroke="#6E59FF" strokeWidth="8" strokeLinecap="round" />
|
| 40 |
+
<path d="M130 130C150 150 170 140 180 160" stroke="#6E59FF" strokeWidth="8" strokeLinecap="round" />
|
| 41 |
+
|
| 42 |
+
<path d="M50 110C30 120 20 100 10 120" stroke="#5040CC" strokeWidth="6" strokeLinecap="round" opacity="0.7" />
|
| 43 |
+
<path d="M150 110C170 120 180 100 190 120" stroke="#5040CC" strokeWidth="6" strokeLinecap="round" opacity="0.7" />
|
| 44 |
+
|
| 45 |
+
{/* Chest Badge */}
|
| 46 |
+
<rect x="85" y="105" width="30" height="15" rx="4" fill="#6E59FF" />
|
| 47 |
+
<text x="100" y="116" fontSize="8" fill="white" textAnchor="middle" fontWeight="bold" fontFamily="Arial">AUBM</text>
|
| 48 |
+
|
| 49 |
+
{/* Antenna/Sensors */}
|
| 50 |
+
<line x1="100" y1="40" x2="100" y2="20" stroke="#00F0FF" strokeWidth="2" />
|
| 51 |
+
<circle cx="100" cy="20" r="4" fill="#00F0FF">
|
| 52 |
+
<animate attributeName="r" values="3;5;3" dur="2s" repeatCount="indefinite" />
|
| 53 |
+
</circle>
|
| 54 |
+
</motion.svg>
|
| 55 |
+
);
|
| 56 |
+
};
|
| 57 |
+
|
| 58 |
+
export default AubixIcon;
|
frontend/src/components/Dashboard.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { getApiUrl } from '../services/runtimeConfig';
|
|
| 4 |
import { motion } from 'framer-motion';
|
| 5 |
import { supabase } from '../services/supabase';
|
| 6 |
import { useAuth } from '../context/useAuth';
|
|
|
|
| 7 |
import StatusBadge from './common/StatusBadge';
|
| 8 |
|
| 9 |
interface Project {
|
|
@@ -209,18 +210,7 @@ const Dashboard: React.FC<DashboardProps> = ({ onNewProject, onOpenProject }) =>
|
|
| 209 |
gap: 'var(--space-lg)',
|
| 210 |
background: 'rgba(110, 89, 255, 0.05)'
|
| 211 |
}}>
|
| 212 |
-
<
|
| 213 |
-
width: '64px',
|
| 214 |
-
height: '64px',
|
| 215 |
-
background: 'var(--accent)',
|
| 216 |
-
borderRadius: '16px',
|
| 217 |
-
display: 'flex',
|
| 218 |
-
alignItems: 'center',
|
| 219 |
-
justifyContent: 'center',
|
| 220 |
-
boxShadow: '0 0 20px rgba(110, 89, 255, 0.3)'
|
| 221 |
-
}}>
|
| 222 |
-
<Bot size={32} color="white" />
|
| 223 |
-
</div>
|
| 224 |
<div style={{ flex: 1 }}>
|
| 225 |
<div style={{ display: 'flex', gap: 'var(--space-sm)', position: 'relative' }}>
|
| 226 |
<input
|
|
|
|
| 4 |
import { motion } from 'framer-motion';
|
| 5 |
import { supabase } from '../services/supabase';
|
| 6 |
import { useAuth } from '../context/useAuth';
|
| 7 |
+
import AubixIcon from './AubixIcon';
|
| 8 |
import StatusBadge from './common/StatusBadge';
|
| 9 |
|
| 10 |
interface Project {
|
|
|
|
| 210 |
gap: 'var(--space-lg)',
|
| 211 |
background: 'rgba(110, 89, 255, 0.05)'
|
| 212 |
}}>
|
| 213 |
+
<AubixIcon size={64} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
<div style={{ flex: 1 }}>
|
| 215 |
<div style={{ display: 'flex', gap: 'var(--space-sm)', position: 'relative' }}>
|
| 216 |
<input
|
frontend/src/components/SplashScreen.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import React from 'react';
|
| 2 |
import { motion } from 'framer-motion';
|
| 3 |
import { Bot } from 'lucide-react';
|
|
|
|
| 4 |
|
| 5 |
const SplashScreen: React.FC = () => {
|
| 6 |
return (
|
|
@@ -32,21 +33,7 @@ const SplashScreen: React.FC = () => {
|
|
| 32 |
delay: 0.2
|
| 33 |
}}
|
| 34 |
>
|
| 35 |
-
<
|
| 36 |
-
animate={{ y: [0, -10, 0] }}
|
| 37 |
-
transition={{ repeat: Infinity, duration: 3, ease: "easeInOut" }}
|
| 38 |
-
style={{
|
| 39 |
-
background: 'linear-gradient(135deg, var(--accent) 0%, var(--primary) 100%)',
|
| 40 |
-
padding: '40px',
|
| 41 |
-
borderRadius: '40px',
|
| 42 |
-
boxShadow: '0 20px 40px rgba(110, 89, 255, 0.4)',
|
| 43 |
-
display: 'flex',
|
| 44 |
-
alignItems: 'center',
|
| 45 |
-
justifyContent: 'center'
|
| 46 |
-
}}
|
| 47 |
-
>
|
| 48 |
-
<Bot size={100} color="white" />
|
| 49 |
-
</motion.div>
|
| 50 |
</motion.div>
|
| 51 |
|
| 52 |
<motion.h1
|
|
|
|
| 1 |
import React from 'react';
|
| 2 |
import { motion } from 'framer-motion';
|
| 3 |
import { Bot } from 'lucide-react';
|
| 4 |
+
import AubixIcon from './AubixIcon';
|
| 5 |
|
| 6 |
const SplashScreen: React.FC = () => {
|
| 7 |
return (
|
|
|
|
| 33 |
delay: 0.2
|
| 34 |
}}
|
| 35 |
>
|
| 36 |
+
<AubixIcon size={180} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
</motion.div>
|
| 38 |
|
| 39 |
<motion.h1
|