aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorLofiSu <163713803+LofiSu@users.noreply.github.com>2025-01-26 04:27:57 +0000
committerLofiSu <163713803+LofiSu@users.noreply.github.com>2025-01-26 04:27:57 +0000
commit60f54181d6d5e21d3140953dece51fee7a0d40c5 (patch)
tree6cb9cd1ff43125126f06a09aab95ab7bf108f61d /src
parent2a65ec749b0b1974b757ecf175b3d638d1025aef (diff)
downloadHydroRollSite-60f54181d6d5e21d3140953dece51fee7a0d40c5.tar.gz
HydroRollSite-60f54181d6d5e21d3140953dece51fee7a0d40c5.zip
home components
Diffstat (limited to 'src')
-rw-r--r--src/App.css42
-rw-r--r--src/App.tsx42
-rw-r--r--src/HomePage.tsx91
-rw-r--r--src/components/FutureCard.tsx28
-rw-r--r--src/components/StatsCard.tsx26
-rw-r--r--src/components/ThreeBackground.tsx72
-rw-r--r--src/index.css68
-rw-r--r--src/main.tsx10
8 files changed, 227 insertions, 152 deletions
diff --git a/src/App.css b/src/App.css
deleted file mode 100644
index b9d355d..0000000
--- a/src/App.css
+++ /dev/null
@@ -1,42 +0,0 @@
-#root {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
-}
-
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
- transition: filter 300ms;
-}
-.logo:hover {
- filter: drop-shadow(0 0 2em #646cffaa);
-}
-.logo.react:hover {
- filter: drop-shadow(0 0 2em #61dafbaa);
-}
-
-@keyframes logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
-
-@media (prefers-reduced-motion: no-preference) {
- a:nth-of-type(2) .logo {
- animation: logo-spin infinite 20s linear;
- }
-}
-
-.card {
- padding: 2em;
-}
-
-.read-the-docs {
- color: #888;
-}
diff --git a/src/App.tsx b/src/App.tsx
index 3d7ded3..b708bf5 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,35 +1,13 @@
-import { useState } from 'react'
-import reactLogo from './assets/react.svg'
-import viteLogo from '/vite.svg'
-import './App.css'
-
-function App() {
- const [count, setCount] = useState(0)
+import React from 'react';
+import { NextUIProvider } from '@nextui-org/react';
+import HomePage from './HomePage';
+const App: React.FC = () => {
return (
- <>
- <div>
- <a href="https://vite.dev" target="_blank">
- <img src={viteLogo} className="logo" alt="Vite logo" />
- </a>
- <a href="https://react.dev" target="_blank">
- <img src={reactLogo} className="logo react" alt="React logo" />
- </a>
- </div>
- <h1>Vite + React</h1>
- <div className="card">
- <button onClick={() => setCount((count) => count + 1)}>
- count is {count}
- </button>
- <p>
- Edit <code>src/App.tsx</code> and save to test HMR
- </p>
- </div>
- <p className="read-the-docs">
- Click on the Vite and React logos to learn more
- </p>
- </>
- )
-}
+ <NextUIProvider>
+ <HomePage />
+ </NextUIProvider>
+ );
+};
-export default App
+export default App;
diff --git a/src/HomePage.tsx b/src/HomePage.tsx
new file mode 100644
index 0000000..dcbb88c
--- /dev/null
+++ b/src/HomePage.tsx
@@ -0,0 +1,91 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import { FaGithub, FaDiscord } from 'react-icons/fa';
+import { SiPython, SiTypescript, SiReact } from 'react-icons/si';
+import { Button, Card } from '@nextui-org/react';
+import { ThreeBackground } from './components/ThreeBackground';
+import { StatsCard } from './components/StatsCard';
+import { FeatureCard } from './components/FeatureCard';
+
+const HomePage: React.FC = () => {
+ return (
+ <div className="min-h-screen bg-gradient-to-b from-gray-900 to-black text-white relative overflow-hidden">
+ <ThreeBackground />
+
+ {/* Hero Section */}
+ <section className="relative z-10 pt-20 pb-32">
+ <motion.div
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.8 }}
+ className="container mx-auto px-4 text-center"
+ >
+ <h1 className="text-6xl font-bold mb-6 bg-clip-text text-transparent bg-gradient-to-r from-cyan-400 to-purple-500">
+ HydroRoll
+ </h1>
+ <p className="text-xl text-gray-300 mb-8 max-w-2xl mx-auto">
+ 下一代开源 TRPG 骰子机器人框架,为你的游戏体验带来无限可能
+ </p>
+ <div className="flex gap-4 justify-center">
+ <Button
+ className="bg-gradient-to-r from-cyan-500 to-blue-500 text-white"
+ size="lg"
+ href="https://github.com/HydroRoll-Team"
+ target="_blank"
+ as="a"
+ >
+ <FaGithub className="mr-2" />
+ 加入 GitHub
+ </Button>
+ <Button
+ className="bg-gradient-to-r from-indigo-500 to-purple-500 text-white"
+ size="lg"
+ >
+ <FaDiscord className="mr-2" />
+ 加入 Discord
+ </Button>
+ </div>
+ </motion.div>
+ </section>
+
+ {/* Features Section */}
+ <section className="relative z-10 py-20 bg-black/50">
+ <div className="container mx-auto px-4">
+ <h2 className="text-4xl font-bold text-center mb-16 bg-clip-text text-transparent bg-gradient-to-r from-cyan-400 to-purple-500">
+ 核心特性
+ </h2>
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
+ <FeatureCard
+ icon={<SiPython className="text-4xl text-blue-400" />}
+ title="Python 驱动"
+ description="基于 Python 构建,提供灵活且强大的插件系统"
+ />
+ <FeatureCard
+ icon={<SiTypescript className="text-4xl text-blue-500" />}
+ title="TypeScript 支持"
+ description="完整的 TypeScript 类型支持,提供更好的开发体验"
+ />
+ <FeatureCard
+ icon={<SiReact className="text-4xl text-cyan-400" />}
+ title="现代化框架"
+ description="采用现代化的框架设计,支持多平台部署"
+ />
+ </div>
+ </div>
+ </section>
+
+ {/* Stats Section */}
+ <section className="relative z-10 py-20">
+ <div className="container mx-auto px-4">
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
+ <StatsCard title="GitHub Stars" value="1000+" />
+ <StatsCard title="社区成员" value="500+" />
+ <StatsCard title="插件数量" value="50+" />
+ </div>
+ </div>
+ </section>
+ </div>
+ );
+};
+
+export default HomePage;
diff --git a/src/components/FutureCard.tsx b/src/components/FutureCard.tsx
new file mode 100644
index 0000000..5f8a95d
--- /dev/null
+++ b/src/components/FutureCard.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import { Card } from '@nextui-org/react';
+
+interface FeatureCardProps {
+ icon: React.ReactNode;
+ title: string;
+ description: string;
+}
+
+export const FeatureCard: React.FC<FeatureCardProps> = ({ icon, title, description }) => {
+ return (
+ <motion.div
+ whileHover={{ scale: 1.05 }}
+ transition={{ type: "spring", stiffness: 300 }}
+ >
+ <Card className="p-6 bg-gradient-to-br from-gray-800/50 to-gray-900/50 border border-gray-700">
+ <div className="flex flex-col items-center text-center">
+ <div className="mb-4">
+ {icon}
+ </div>
+ <h3 className="text-xl font-bold mb-2 text-white">{title}</h3>
+ <p className="text-gray-400">{description}</p>
+ </div>
+ </Card>
+ </motion.div>
+ );
+};
diff --git a/src/components/StatsCard.tsx b/src/components/StatsCard.tsx
new file mode 100644
index 0000000..237f5dc
--- /dev/null
+++ b/src/components/StatsCard.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import { motion } from 'framer-motion';
+import { Card } from '@nextui-org/react';
+
+interface StatsCardProps {
+ title: string;
+ value: string;
+}
+
+export const StatsCard: React.FC<StatsCardProps> = ({ title, value }) => {
+ return (
+ <motion.div
+ initial={{ opacity: 0, y: 20 }}
+ whileInView={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5 }}
+ viewport={{ once: true }}
+ >
+ <Card className="p-6 bg-gradient-to-br from-gray-800/50 to-gray-900/50 border border-gray-700">
+ <div className="text-center">
+ <h3 className="text-2xl font-bold text-white mb-2">{value}</h3>
+ <p className="text-gray-400">{title}</p>
+ </div>
+ </Card>
+ </motion.div>
+ );
+};
diff --git a/src/components/ThreeBackground.tsx b/src/components/ThreeBackground.tsx
new file mode 100644
index 0000000..1a6337c
--- /dev/null
+++ b/src/components/ThreeBackground.tsx
@@ -0,0 +1,72 @@
+import React, { useEffect, useRef } from 'react';
+import * as THREE from 'three';
+
+export const ThreeBackground: React.FC = () => {
+ const containerRef = useRef<HTMLDivElement>(null);
+
+ useEffect(() => {
+ if (!containerRef.current) return;
+
+ const scene = new THREE.Scene();
+ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
+ const renderer = new THREE.WebGLRenderer({ alpha: true });
+
+ renderer.setSize(window.innerWidth, window.innerHeight);
+ containerRef.current.appendChild(renderer.domElement);
+
+ // Create particles
+ const geometry = new THREE.BufferGeometry();
+ const vertices = [];
+
+ for (let i = 0; i < 5000; i++) {
+ vertices.push(
+ THREE.MathUtils.randFloatSpread(2000), // x
+ THREE.MathUtils.randFloatSpread(2000), // y
+ THREE.MathUtils.randFloatSpread(2000) // z
+ );
+ }
+
+ geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
+
+ const material = new THREE.PointsMaterial({
+ color: 0x88ccff,
+ size: 2,
+ transparent: true,
+ opacity: 0.5
+ });
+
+ const particles = new THREE.Points(geometry, material);
+ scene.add(particles);
+
+ camera.position.z = 1000;
+
+ const animate = () => {
+ requestAnimationFrame(animate);
+ particles.rotation.x += 0.0001;
+ particles.rotation.y += 0.0001;
+ renderer.render(scene, camera);
+ };
+
+ animate();
+
+ const handleResize = () => {
+ camera.aspect = window.innerWidth / window.innerHeight;
+ camera.updateProjectionMatrix();
+ renderer.setSize(window.innerWidth, window.innerHeight);
+ };
+
+ window.addEventListener('resize', handleResize);
+
+ return () => {
+ window.removeEventListener('resize', handleResize);
+ containerRef.current?.removeChild(renderer.domElement);
+ };
+ }, []);
+
+ return (
+ <div
+ ref={containerRef}
+ className="fixed top-0 left-0 w-full h-full z-0"
+ />
+ );
+};
diff --git a/src/index.css b/src/index.css
deleted file mode 100644
index 6119ad9..0000000
--- a/src/index.css
+++ /dev/null
@@ -1,68 +0,0 @@
-:root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- line-height: 1.5;
- font-weight: 400;
-
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
-
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-a:hover {
- color: #535bf2;
-}
-
-body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
-}
-button:hover {
- border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #747bff;
- }
- button {
- background-color: #f9f9f9;
- }
-}
diff --git a/src/main.tsx b/src/main.tsx
deleted file mode 100644
index bef5202..0000000
--- a/src/main.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import './index.css'
-import App from './App.tsx'
-
-createRoot(document.getElementById('root')!).render(
- <StrictMode>
- <App />
- </StrictMode>,
-)