File manager - Edit - /home/webapp69.cm.in.th/u69319090013/portfolio/013 Thitinun portfolio/.vscode/settings.json
Back
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ณัฐชนน สุทธกัน | Futuristic Portfolio</title> <!-- Tailwind CSS --> <script src="https://cdn.tailwindcss.com"></script> <script> tailwind.config = { darkMode: 'class', theme: { extend: { colors: { themeRed: '#ff003c', themeWhite: '#ffffff', themeDarkRed: '#8b0000', darkBg: '#050505', glass: 'rgba(20, 20, 20, 0.6)', glassBorder: 'rgba(255, 255, 255, 0.1)', }, fontFamily: { sans: ['Inter', 'sans-serif' ], display: ['Outfit', 'sans-serif' ], mono: ['Fira Code', 'monospace' ], }, animation: { 'float': 'float 6s ease-in-out infinite', 'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite', }, keyframes: { float: { '0%, 100%': { transform: 'translateY(0)' }, '50%': { transform: 'translateY(-20px)' }, } } } } } </script> <style type="text/tailwindcss"> @layer utilities { .glass-panel { @apply bg-white/40 dark:bg-glass backdrop-blur-xl border border-white/50 dark:border-glassBorder rounded-2xl shadow-[ 0_8px_32px_0_rgba(31, 38, 135, 0.1) ] dark:shadow-[ 0_8px_32px_0_rgba(0, 0, 0, 0.5) ]; } .text-glow { text-shadow: 0 0 20px currentColor; } .heading-gradient { @apply bg-clip-text text-transparent bg-gradient-to-r from-themeRed via-purple-500 to-themeDarkRed; } } body { margin: 0; min-height: 100vh; background: linear-gradient(135deg, #000000 0%, #0a192f 100%); background-attachment: fixed; font-family: 'Poppins', sans-serif; overflow-x: hidden; transition: background 0.5s ease; } .dark body { background: linear-gradient(135deg, #000000 0%, #020617 50%, #0f172a 100%); } /* Light mode overrides */ body:not(.dark) .text-white { color: #0f172a !important; } body:not(.dark) .text-gray-300, body:not(.dark) .text-gray-400 { color: #475569 !important; } body:not(.dark) .text-gray-500 { color: #64748b !important; } body:not(.dark) .bg-black\/60 { background-color: rgba(255, 255, 255, 0.6) !important; } body:not(.dark) .bg-black\/80 { background-color: rgba(255, 255, 255,0.😎 !important; } body:not(.dark) .bg-black\/50 { background-color: rgba(255, 255, 255, 0.5) !important; } /* Custom Scrollbar */ : :-webkit-scrollbar { width: 6px; } : :-webkit-scrollbar-track { background: #0fce8e; } : :-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.2); border-radius: 10px; } : :-webkit-scrollbar-thumb:hover { background: rgba(108, 174, 11, 0.5); } </style> <!-- React & ReactDOM --> <script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script> <!-- Babel for JSX --> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <!-- Framer Motion --> <script src="https://unpkg.com/framer-motion@10.16.4/dist/framer-motion.js"></script> <!-- Lucide Icons --> <script src="https://unpkg.com/lucide@latest"></script> <!-- Google Fonts --> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Outfit:wght@300;500;700;800&family=Fira+Code&display=swap" rel="stylesheet"> </head> <body> <div id="root"></div> <script type="text/babel" data-type="module"> const { useState, useEffect, useRef, createContext, useContext } = React; const { motion, useScroll, useTransform, AnimatePresence } = window.Motion; const LanguageContext = createContext(); const translations = { th: { navAbout: "เกี่ยวกับฉัน", navWork: "ผลงาน", navSkills: "ทักษะ", navContact: "ติดต่อ", heroNameFirst: "ณัฐชนน", heroNameLast: "สุทธกัน", heroDesc: "วิศวกรฟูลสแต็กและนักพัฒนาเชิงสร้างสรรค์ ผู้เชี่ยวชาญด้านประสบการณ์เว็บแบบสมจริงและอินเทอร์เฟซแห่งอนาคต", heroBtn: "สำรวจระบบ", workTitle: "ผลงานที่โดดเด่น // 2026", workCard1Title: "Smart Home Automation System", workCard2Title: "IoT Temperature Monitoring", workCard3Title: "Robotics Control System", workCard1Desc: "ควบคุมไฟและอุปกรณ์ผ่านมือถือ พร้อมแสดงผลสถานะแบบ Real-time", workCard2Desc: "อ่านค่า Sensor และส่งข้อมูลขึ้น Cloud พร้อมแจ้งเตือนอัตโนมัติเมื่ออุณหภูมิผิดปกติ", workCard3Desc: "เขียนโปรแกรมควบคุมมอเตอร์และเซนเซอร์ เพื่อพัฒนาระบบควบคุมการเคลื่อนที่อัตโนมัติ", workCardBtn: "ดูรายละเอียด", expTitle: "ประสบการณ์การทำงาน (Embedded Systems & Circuit Programming)", exp1: "เขียนโปรแกรมควบคุมวงจรอิเล็กทรอนิกส์และไมโครคอนโทรลเลอร์", exp2: "พัฒนาโปรเจกต์ด้วย Arduino, ESP32 และ Raspberry Pi", exp3: "ออกแบบระบบ IoT เชื่อมต่อ Sensor และอุปกรณ์อัตโนมัติ", exp4: "เขียนโปรแกรมควบคุม Relay, Motor Driver และระบบ Smart Control", exp5: "เชื่อมต่อวงจรกับ Mobile Application และ Web Dashboard", exp6: "พัฒนา Real-time Monitoring System ผ่าน Wi-Fi และ Bluetooth", exp7: "ใช้งานภาษา C/C++, Python และ JavaScript สำหรับระบบ Embedded", exp8: "วิเคราะห์และแก้ไขปัญหาวงจร Hardware และ Software Integration", skillsTitleFirst: "ความสามารถ", skillsTitleLast: "ของระบบ", skillsDesc: "มาพร้อมกับเทคโนโลยีสมัยใหม่ที่เน้นประสิทธิภาพ ความสวยงาม และโครงสร้างที่รองรับการขยายตัว พัฒนาและปรับตัวให้เข้ากับกระบวนทัศน์ใหม่อย่างต่อเนื่อง", skillsOp: "5+", skillsOpSub: "ปีแห่งการทำงาน", skillsDep: "42", skillsDepSub: "โปรเจกต์ที่ใช้งานจริง", contactTitleFirst: "เริ่มต้น", contactTitleLast: "การเชื่อมต่อ", contactDesc: "เปิดรับโอกาสและความร่วมมือใหม่ๆ ส่งข้อความของคุณด้านล่าง", contactLabel1: "ชื่อ", contactLabel2: "อีเมล", contactLabel3: "ข้อความ", contactBtn: "ส่งข้อมูล", aboutTitleFirst: "เรื่องราว", aboutTitleLast: "ของฉัน", aboutDesc: "สวัสดีครับ ผมชื่อนายณัฐชนน สุทธกัน อายุ 18 ปี ผมมีประสบการณ์ทำงานที่ Topviepoint และมีความเชี่ยวชาญในการประกอบคอมพิวเตอร์ การต่อวงจรอิเล็กทรอนิกส์ การลงโปรแกรม และการเขียนโค้ด", skill1: "การประกอบคอมพิวเตอร์", skill2: "การต่อวงจรอิเล็กทรอนิกส์", skill3: "การลงโปรแกรมและซอฟต์แวร์", skill4: "การเขียนโค้ดโปรแกรมมิ่ง", aiTitle: "ผู้ช่วยระบบ", aiGreeting: "สวัสดี ผมคือผู้ช่วยระบบ มีอะไรให้ผมแนะนำในพอร์ตโฟลิโอนี้ไหมครับ?", aiPlaceholder: "พิมพ์คำถาม...", footerRights: "© 2026 ณัฐชนน สุทธกัน สงวนลิขสิทธิ์" }, en: { navAbout: "ABOUT", navWork: "WORK", navSkills: "SKILLS", navContact: "CONTACT", heroNameFirst: "NATCHANON", heroNameLast: "SUTTAKUN", heroDesc: "Full-stack engineer & creative developer specializing in immersive web experiences and futuristic interfaces.", heroBtn: "EXPLORE SYSTEM", workTitle: "Selected Works // 2026", workCard1Title: "Smart Home Automation System", workCard2Title: "IoT Temperature Monitoring", workCard3Title: "Robotics Control System", workCard1Desc: "Mobile control for lighting and devices with real-time status display.", workCard2Desc: "Read sensor data, sync to Cloud, and trigger automated alerts on abnormal temperatures.", workCard3Desc: "Programmed motors and sensors to develop an automated movement control system.", workCardBtn: "View Case Study", expTitle: "Experience (Embedded Systems & Circuit Programming)", exp1: "Programmed electronic circuits and microcontrollers.", exp2: "Developed projects using Arduino, ESP32, and Raspberry Pi.", exp3: "Designed IoT systems connecting sensors and automated devices.", exp4: "Coded control systems for Relays, Motor Drivers, and Smart Controls.", exp5: "Integrated circuits with Mobile Applications and Web Dashboards.", exp6: "Developed Real-time Monitoring Systems via Wi-Fi and Bluetooth.", exp7: "Utilized C/C++, Python, and JavaScript for Embedded Systems.", exp8: "Analyzed and troubleshooted Hardware circuits and Software Integration.", skillsTitleFirst: "SYSTEM", skillsTitleLast: "CAPABILITIES", skillsDesc: "Equipped with a modern technology stack focused on performance, aesthetics, and scalable architectures. Continually evolving and adapting to new paradigms.", skillsOp: "5+", skillsOpSub: "Years Operation", skillsDep: "42", skillsDepSub: "Projects Deployed", contactTitleFirst: "INITIATE", contactTitleLast: "CONNECTION", contactDesc: "Open for new opportunities and collaborations. Transmit your message below.", contactLabel1: "Identifier", contactLabel2: "Frequency", contactLabel3: "Payload", contactBtn: "Transmit Data", aboutTitleFirst: "ABOUT", aboutTitleLast: "ME", aboutDesc: "Hello, my name is Natchanon Suttakun, I am 18 years old. I have work experience at Topviepoint and am highly capable in PC assembly, electronic circuits, software installation, and coding.", skill1: "PC Assembly / Hardware", skill2: "Electronics Circuit Assembly", skill3: "Software Installation & Setup", skill4: "Coding & Programming", aiTitle: "System AI", aiGreeting: "Greetings. I am the system assistant. How may I guide you through this portfolio?", aiPlaceholder: "Type query...", footerRights: "© 2026 Natchanon Suttakun. All rights reserved." }, zh: { navAbout: "关于我", navWork: "作品", navSkills: "技能", navContact: "联系", heroNameFirst: "纳查农", heroNameLast: "苏塔昆", heroDesc: "全栈工程师与创意开发者,专注于沉浸式网络体验与未来主义界面。", heroBtn: "探索系统", workTitle: "精选作品 // 2026", workCard1Title: "Smart Home Automation System", workCard2Title: "IoT Temperature Monitoring", workCard3Title: "Robotics Control System", workCard1Desc: "通过手机控制灯光和设备,并具有实时状态显示功能。", workCard2Desc: "读取传感器数据并同步到云端,在温度异常时触发自动警报。", workCard3Desc: "编写电机和传感器控制程序,以开发自动运动控制系统。", workCardBtn: "查看案例研究", expTitle: "工作经验 (Embedded Systems & Circuit Programming)", exp1: "编写电子电路和微控制器控制程序。", exp2: "使用 Arduino、ESP32 和 Raspberry Pi 开发项目。", exp3: "设计连接传感器和自动化设备的 IoT 系统。", exp4: "编写继电器、电机驱动器和智能控制系统的控制程序。", exp5: "将电路与移动应用和 Web 仪表板集成。", exp6: "通过 Wi-Fi 和蓝牙开发实时监控系统。", exp7: "在嵌入式系统中使用 C/C++、Python 和 JavaScript。", exp8: "分析并解决硬件电路和软件集成问题。", skillsTitleFirst: "系统", skillsTitleLast: "功能", skillsDesc: "配备现代技术栈,注重性能、美观和可扩展的架构。不断发展并适应新模式。", skillsOp: "5+", skillsOpSub: "年运营经验", skillsDep: "42", skillsDepSub: "已部署项目", contactTitleFirst: "建立", contactTitleLast: "连接", contactDesc: "对新的机会和合作持开放态度。在下方发送您的信息。", contactLabel1: "标识符", contactLabel2: "频率", contactLabel3: "有效载荷", contactBtn: "传输数据", aboutTitleFirst: "关于", aboutTitleLast: "我", aboutDesc: "你好,我叫 Natchanon Suttakun(纳查农·苏塔昆),今年 18 岁。我曾在 Topviepoint 工作,擅长电脑组装、电子电路、软件安装和编程。", skill1: "电脑组装 (PC Assembly)", skill2: "电子电路组装 (Circuit Assembly)", skill3: "软件安装与配置 (Software Setup)", skill4: "编程与代码编写 (Coding)", aiTitle: "系统助手", aiGreeting: "您好。我是系统助手。有什么我可以为您导航的吗?", aiPlaceholder: "输入查询...", footerRights: "© 2026 纳查农·苏塔昆。版权所有。" } }; const useLanguage = () => useContext(LanguageContext); // Custom hook for mouse position to create interactive glow const useMousePosition = () => { const [mousePosition, setMousePosition ] = useState({ x: null, y: null }); useEffect(() => { const updateMousePosition = ev => { setMousePosition({ x: ev.clientX, y: ev.clientY }); }; window.addEventListener('mousemove', updateMousePosition); return () => window.removeEventListener('mousemove', updateMousePosition); }, []); return mousePosition; }; const NavBar = () => { const { t, lang, setLang, theme, toggleTheme } = useLanguage(); return ( <motion.nav initial={ { y: -100, opacity: 0 } } animate={ { y: 0, opacity: 1 } } transition={ { duration: 0.8, ease: "easeOut" } } className="fixed w-full top-0 z-50 flex justify-between items-center px-10 py-6 mix-blend-difference" > <div className="flex items-center gap-6"> <div className="text-2xl font-display font-bold tracking-widest text-white uppercase"> <span className="text-themeRed">N</span>ATCHANON </div> <div className="hidden md:flex gap-3 text-xs font-mono items-center"> <button onClick={() => setLang('th') } className={`transition-colors ${lang === 'th' ? 'text-themeRed' : 'text-gray-500 hover:text-white' }` }>TH</button> <span className="text-gray-700">|</span> <button onClick={() => setLang('en') } className={`transition-colors ${lang === 'en' ? 'text-themeRed' : 'text-gray-500 hover:text-white' }` }>EN</button> <span className="text-gray-700">|</span> <button onClick={() => setLang('zh') } className={`transition-colors ${lang === 'zh' ? 'text-themeRed' : 'text-gray-500 hover:text-white' }` }>ZH</button> <span className="text-gray-700 ml-2">|</span> <button onClick={toggleTheme } className="ml-2 text-gray-500 hover:text-white transition-colors"> {theme === 'dark' ? ( <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg> ) : ( <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg> ) } </button> </div> </div> <div className="flex gap-8 text-sm font-mono tracking-widest text-gray-300"> <a href="#about" className="hover:text-themeRed transition-colors duration-300">{t.navAbout }</a> <a href="#work" className="hover:text-themeRed transition-colors duration-300">{t.navWork }</a> <a href="#skills" className="hover:text-themeWhite transition-colors duration-300">{t.navSkills }</a> <a href="#contact" className="hover:text-themeDarkRed transition-colors duration-300">{t.navContact }</a> </div> </motion.nav> ); }; const HeroSection = () => { const { t } = useLanguage(); const { scrollY } = useScroll(); const y1 = useTransform(scrollY, [ 0, 1000 ], [ 0, 200 ]); const y2 = useTransform(scrollY, [ 0, 1000 ], [ 0, -100 ]); const opacity = useTransform(scrollY, [ 0, 500 ], [ 1, 0 ]); return ( <section className="relative h-screen flex items-center justify-center overflow-hidden"> { /* Background Elements */} <motion.div style={ { y: y1 } } className="absolute w-[500px] h-[500px] rounded-full bg-themeWhite/10 blur-[120px] top-[-10%] right-[-5%]" /> <motion.div style={ { y: y2 } } className="absolute w-[400px] h-[400px] rounded-full bg-themeRed/15 blur-[100px] bottom-[-10%] left-[-5%]" /> <motion.div style={ { opacity } } className="z-10 flex flex-col items-center text-center space-y-6" > <motion.div initial={ { scale: 0.8, opacity: 0 } } animate={ { scale: 1, opacity: 1 } } transition={ { duration: 1.2, ease: "easeOut" } } className="relative mb-8 mt-16" > <div className="w-40 h-40 rounded-full glass-panel flex items-center justify-center p-2 animate-float"> <div className="w-full h-full rounded-full bg-gradient-to-br from-themeRed to-themeDarkRed opacity-80 blur-sm absolute inset-0"></div> <img src="./profile.jpg" alt="Profile" className="w-full h-full rounded-full object-cover z-10 border-2 border-glassBorder" /> </div> </motion.div> <motion.h1 initial={ { y: 50, opacity: 0 } } animate={ { y: 0, opacity: 1 } } transition={ { duration: 0.8, delay: 0.2 } } className="text-6xl md:text-8xl font-display font-bold tracking-tight" > {t.heroNameFirst } <br /> <span className="heading-gradient text-glow">{t.heroNameLast }</span> </motion.h1> <motion.p initial={ { y: 50, opacity: 0 } } animate={ { y: 0, opacity: 1 } } transition={ { duration: 0.8, delay: 0.4 } } className="text-xl text-gray-400 font-light max-w-2xl px-4" > {t.heroDesc } </motion.p> <motion.button initial={ { y: 50, opacity: 0 } } animate={ { y: 0, opacity: 1 } } transition={ { duration: 0.8, delay: 0.6 } } whileHover={ { scale: 1.05, boxShadow: "0 0 20px rgba(255,0,60,0.5)" } } whileTap={ { scale: 0.95 } } className="px-8 py-4 mt-8 rounded-full bg-transparent border border-themeRed text-themeRed font-mono tracking-widest hover:bg-themeRed hover:text-white transition-all duration-300" > {t.heroBtn } </motion.button> </motion.div> </section> ); }; const AboutSection = () => { const { t } = useLanguage(); return ( <section id="about" className="py-32 px-6 md:px-20 max-w-4xl mx-auto text-center relative z-10"> <motion.div initial={ { opacity: 0, y: 50 } } whileInView={ { opacity: 1, y: 0 } } viewport={ { once: true } } transition={ { duration: 0.8 } } > <h2 className="text-4xl md:text-5xl font-display font-bold mb-10">{t.aboutTitleFirst } <span className="text-themeRed text-glow">{t.aboutTitleLast }</span></h2> <div className="glass-panel p-8 md:p-12 relative overflow-hidden group hover:border-themeRed/50 transition-colors duration-500"> <div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-themeRed to-themeDarkRed"></div> <p className="text-xl text-gray-300 font-light leading-relaxed mb-8"> {t.aboutDesc } </p> <h3 className="text-2xl text-left font-display font-bold text-white mb-6 border-b border-glassBorder pb-4">{t.expTitle }</h3> <ul className="text-left space-y-4 text-gray-400 font-light text-sm md:text-base"> { [ 1, 2, 3, 4, 5, 6, 7, 8 ].map(num => ( <li key={num } className="flex items-start gap-3"> <div className="mt-1 text-themeRed flex-shrink-0"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> </div> <span>{t[`exp${num }` ] }</span> </li> )) } </ul> </div> </motion.div> </section> ); }; const ProjectCard = ({ title, tech, image, align, desc }) => { const { t } = useLanguage(); return ( <motion.div initial={ { opacity: 0, y: 100 } } whileInView={ { opacity: 1, y: 0 } } viewport={ { once: true, margin: "-100px" } } transition={ { duration: 0.8 } } className={`flex flex-col md:flex-row gap-10 items-center ${align === 'right' ? 'md:flex-row-reverse' : '' }` } > <div className="w-full md:w-1/2 group relative"> <div className="absolute inset-0 bg-gradient-to-r from-themeRed to-themeDarkRed opacity-0 group-hover:opacity-30 blur-xl transition-opacity duration-500 rounded-2xl"></div> <div className="glass-panel overflow-hidden relative z-10 aspect-video group-hover:border-themeRed/50 transition-colors duration-500"> <img src={image } alt={title } className="w-full h-full object-cover opacity-60 group-hover:opacity-100 group-hover:scale-105 transition-all duration-700" /> </div> </div> <div className="w-full md:w-1/2 space-y-6"> <h3 className="text-4xl font-display font-bold text-white group-hover:text-themeRed transition-colors">{title }</h3> <div className="flex gap-3 flex-wrap"> {tech.map((tc, i) => ( <span key={i } className="px-3 py-1 text-xs font-mono rounded-full border border-glassBorder bg-glass text-gray-300"> {tc } </span> )) } </div> <p className="text-gray-400 font-light text-lg"> {desc } </p> <a href="#" className="inline-flex items-center gap-2 text-themeRed hover:text-white transition-colors font-mono uppercase text-sm tracking-widest mt-4 group"> {t.workCardBtn } <span className="group-hover:translate-x-2 transition-transform duration-300">→</span> </a> </div> </motion.div> ); }; const WorkSection = () => { const { t } = useLanguage(); const projects = [ { title: t.workCard1Title, desc: t.workCard1Desc, tech: [ "Mobile App", "Relay", "Smart Control" ], image: "https://images.unsplash.com/photo-1558346490-a72e53ae2d4f?q=80&w=2000&auto=format&fit=crop" }, { title: t.workCard2Title, desc: t.workCard2Desc, tech: [ "ESP32", "Sensors", "Cloud API" ], image: "https://images.unsplash.com/photo-1518770660439-4636190af475?q=80&w=2000&auto=format&fit=crop", align: 'right' }, { title: t.workCard3Title, desc: t.workCard3Desc, tech: [ "Arduino", "Motor Driver", "Robotics" ], image: "https://images.unsplash.com/photo-1485827404703-89b55fcc595e?q=80&w=2000&auto=format&fit=crop" }, ]; return ( <section id="work" className="py-32 px-6 md:px-20 max-w-7xl mx-auto relative"> <h2 className="text-sm font-mono tracking-[0.3em] text-gray-500 mb-20 uppercase">{t.workTitle }</h2> <div className="space-y-40"> {projects.map((p, i) => <ProjectCard key={i } {...p } />) } </div> </section> ); }; const SkillBar = ({ name, level, color }) => { return ( <div className="space-y-2"> <div className="flex justify-between font-mono text-xs uppercase tracking-widest"> <span className="text-gray-300">{name }</span> <span className="text-gray-500">{level }%</span> </div> <div className="h-1.5 w-full bg-glass rounded-full overflow-hidden"> <motion.div initial={ { width: 0 } } whileInView={ { width: ${level }% } } viewport={ { once: true } } transition={ { duration: 1.5, ease: "easeOut" } } className={`h-full ${color }` } ></motion.div> </div> </div> ); }; const SkillsSection = () => { const { t } = useLanguage(); return ( <section id="skills" className="py-32 px-6 md:px-20 relative overflow-hidden bg-black/60 backdrop-blur-3xl border-y border-glassBorder"> <div className="max-w-7xl mx-auto grid md:grid-cols-2 gap-20"> <div> <h2 className="text-5xl font-display font-bold mb-8">{t.skillsTitleFirst } <span className="text-themeRed">{t.skillsTitleLast }</span></h2> <p className="text-gray-400 font-light mb-10 text-lg"> {t.skillsDesc } </p> <div className="glass-panel p-8 space-y-6 relative overflow-hidden group"> <div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-themeRed to-themeDarkRed transform origin-left scale-x-0 group-hover:scale-x-100 transition-transform duration-500"></div> <SkillBar name={t.skill1 } level="95" color="bg-themeRed" /> <SkillBar name={t.skill2 } level="90" color="bg-themeWhite" /> <SkillBar name={t.skill3 } level="85" color="bg-themeDarkRed" /> <SkillBar name={t.skill4 } level="75" color="bg-gray-500" /> </div> </div> <div className="grid grid-cols-2 gap-6 items-center"> <motion.div whileHover={ { scale: 1.05 } } className="glass-panel aspect-square flex flex-col items-center justify-center p-6 border-t-themeRed border-t-2"> <div className="text-4xl font-display font-bold text-white mb-2">{t.skillsOp }</div> <div className="text-xs font-mono text-gray-500 uppercase tracking-widest text-center">{t.skillsOpSub }</div> </motion.div> <motion.div whileHover={ { scale: 1.05 } } className="glass-panel aspect-square flex flex-col items-center justify-center p-6 mt-10 border-t-themeWhite border-t-2"> <div className="text-4xl font-display font-bold text-white mb-2">{t.skillsDep }</div> <div className="text-xs font-mono text-gray-500 uppercase tracking-widest text-center">{t.skillsDepSub }</div> </motion.div> </div> </div> </section> ); }; const ContactSection = () => { const { t } = useLanguage(); return ( <section id="contact" className="py-32 px-6 md:px-20 max-w-4xl mx-auto text-center relative"> <motion.div initial={ { opacity: 0, scale: 0.9 } } whileInView={ { opacity: 1, scale: 1 } } viewport={ { once: true } } transition={ { duration: 0.8 } } className="glass-panel p-12 md:p-20 relative overflow-hidden" > <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[300px] h-[300px] bg-themeDarkRed/30 rounded-full blur-[100px] -z-10"></div> <h2 className="text-4xl md:text-6xl font-display font-bold mb-6">{t.contactTitleFirst } <span className="text-themeRed text-glow">{t.contactTitleLast }</span></h2> <p className="text-gray-400 mb-12 font-light">{t.contactDesc }</p> <form className="space-y-6 text-left" onSubmit={(e) => e.preventDefault() }> <div className="grid md:grid-cols-2 gap-6"> <div className="space-y-2"> <label className="text-xs font-mono uppercase tracking-widest text-gray-500 ml-2">{t.contactLabel1 }</label> <input type="text" className="w-full bg-black/80 border border-glassBorder rounded-xl px-4 py-4 text-white focus:outline-none focus:border-themeRed transition-colors focus:bg-black" placeholder="Name" /> </div> <div className="space-y-2"> <label className="text-xs font-mono uppercase tracking-widest text-gray-500 ml-2">{t.contactLabel2 }</label> <input type="email" className="w-full bg-black/80 border border-glassBorder rounded-xl px-4 py-4 text-white focus:outline-none focus:border-themeRed transition-colors focus:bg-black" placeholder="Email" /> </div> </div> <div className="space-y-2"> <label className="text-xs font-mono uppercase tracking-widest text-gray-500 ml-2">{t.contactLabel3 }</label> <textarea rows="4" className="w-full bg-black/80 border border-glassBorder rounded-xl px-4 py-4 text-white focus:outline-none focus:border-themeRed transition-colors focus:bg-black resize-none" placeholder="Message content..."></textarea> </div> <button className="w-full py-5 rounded-xl bg-gradient-to-r from-themeRed to-themeDarkRed text-white font-mono uppercase tracking-widest hover:opacity-90 transition-opacity flex items-center justify-center gap-2"> {t.contactBtn } <i data-lucide="send" className="w-4 h-4"></i> </button> </form> </motion.div> </section> ); }; const AIAssistant = () => { const { t } = useLanguage(); const [isOpen, setIsOpen ] = useState(false); return ( <div className="fixed bottom-8 right-8 z-50"> <AnimatePresence> {isOpen && ( <motion.div initial={ { opacity: 0, y: 20, scale: 0.9 } } animate={ { opacity: 1, y: 0, scale: 1 } } exit={ { opacity: 0, y: 20, scale: 0.9 } } className="absolute bottom-20 right-0 w-[300px] h-[400px] glass-panel p-4 flex flex-col" > <div className="flex justify-between items-center border-b border-glassBorder pb-3 mb-3"> <div className="flex items-center gap-2"> <div className="w-2 h-2 rounded-full bg-themeRed animate-pulse"></div> <span className="font-mono text-xs uppercase tracking-widest text-white">{t.aiTitle }</span> </div> <button onClick={() => setIsOpen(false) } className="text-gray-500 hover:text-white">✕</button> </div> <div className="flex-1 overflow-y-auto font-light text-sm space-y-4 pr-2 text-gray-300"> <div className="bg-black/80 p-3 rounded-lg border border-glassBorder inline-block max-w-[85%]"> {t.aiGreeting } </div> </div> <div className="mt-4 flex gap-2"> <input type="text" placeholder={t.aiPlaceholder } className="flex-1 bg-black/80 border border-glassBorder rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-themeRed text-white" /> <button className="bg-themeRed/20 text-themeRed p-2 rounded-lg hover:bg-themeRed/40 transition-colors"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg> </button> </div> </motion.div> ) } </AnimatePresence> <motion.button whileHover={ { scale: 1.1 } } whileTap={ { scale: 0.9 } } onClick={() => setIsOpen(!isOpen) } className="w-14 h-14 rounded-full glass-panel flex items-center justify-center border border-themeRed/50 text-themeRed hover:bg-themeRed/20 transition-colors shadow-[0_0_20px_rgba(255,0,60,0.3)] relative bg-black/50" > <div className="absolute inset-0 rounded-full border border-themeRed animate-ping opacity-20"></div> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg> </motion.button> </div> ); }; const CursorGlow = () => { const mousePosition = useMousePosition(); if (mousePosition.x === null) return null; return ( <motion.div className="fixed top-0 left-0 w-96 h-96 bg-themeRed/10 rounded-full pointer-events-none blur-[100px] mix-blend-screen z-0" animate={ { x: mousePosition.x - 192, y: mousePosition.y - 192, } } transition={ { type: "tween", ease: "backOut", duration: 0.5 } } /> ); }; const App = () => { const [lang, setLang ] = useState('th'); const [theme, setTheme ] = useState('dark'); useEffect(() => { // Initialize Lucide icons if used globally if (window.lucide) { window.lucide.createIcons(); } }, []); useEffect(() => { if (theme === 'dark') { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } }, [theme ]); const toggleTheme = () => setTheme(prev => prev === 'dark' ? 'light' : 'dark'); return ( <LanguageContext.Provider value={ { t: translations[lang ], lang, setLang, theme, toggleTheme } }> <div className="min-h-screen text-slate-900 dark:text-white font-sans selection:bg-themeRed/30 transition-colors duration-500"> <CursorGlow /> <NavBar /> <HeroSection /> <AboutSection /> <WorkSection /> <SkillsSection /> <ContactSection /> <AIAssistant /> <footer className="py-8 text-center border-t border-glassBorder mt-20 font-mono text-xs text-gray-600 uppercase tracking-widest"> {translations[lang ].footerRights } </footer> </div> </LanguageContext.Provider> ); }; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<App />); </script> </body> </html>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.24 |
proxy
|
phpinfo
|
Settings