From dd6554509ca4698ae984a43f4ffee84eca8cdbe0 Mon Sep 17 00:00:00 2001 From: abhrajitray77 Date: Tue, 5 Aug 2025 13:21:31 +0530 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=94=A5Spline=20object=20responsive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- www/package.json | 2 + www/pnpm-lock.yaml | 66 +++++++++++++++++++ www/src/components/Hero.tsx | 125 ++++++++++++++++++++++++++---------- www/src/styles/global.css | 58 ++++++++++------- 4 files changed, 195 insertions(+), 56 deletions(-) diff --git a/www/package.json b/www/package.json index 8c8e271..f6f1c31 100644 --- a/www/package.json +++ b/www/package.json @@ -13,6 +13,8 @@ "@astrojs/react": "^4.3.0", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-slot": "^1.2.3", + "@splinetool/react-spline": "^4.1.0", + "@splinetool/runtime": "^1.10.39", "@tailwindcss/vite": "^4.1.3", "@types/canvas-confetti": "^1.9.0", "@types/react": "^19.1.8", diff --git a/www/pnpm-lock.yaml b/www/pnpm-lock.yaml index 274df87..220de07 100644 --- a/www/pnpm-lock.yaml +++ b/www/pnpm-lock.yaml @@ -20,6 +20,12 @@ importers: '@radix-ui/react-slot': specifier: ^1.2.3 version: 1.2.3(@types/react@19.1.8)(react@19.1.0) + '@splinetool/react-spline': + specifier: ^4.1.0 + version: 4.1.0(@splinetool/runtime@1.10.39)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@splinetool/runtime': + specifier: ^1.10.39 + version: 1.10.39 '@tailwindcss/vite': specifier: ^4.1.3 version: 4.1.11(vite@6.3.5(@types/node@24.0.11)(jiti@2.4.2)(lightningcss@1.30.1)) @@ -631,6 +637,20 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@splinetool/react-spline@4.1.0': + resolution: {integrity: sha512-Y379gm17gw+1nxT/YXTCJnVIWuu7tsUH1tp/YxsYb0pZnc9Gljk7Om4Kpq7WPq0bZ4zidVCxf6xn6jgDcbHifQ==} + peerDependencies: + '@splinetool/runtime': '*' + next: '>=14.2.0' + react: '*' + react-dom: '*' + peerDependenciesMeta: + next: + optional: true + + '@splinetool/runtime@1.10.39': + resolution: {integrity: sha512-Xjyq7+ON5uYWCARq7WteYQLwgmu/pO3Y3xwYaKI07Euz/7/GErDDNeD8OGt10DLG5JXuBeEddH+GNqvzJ7U5UQ==} + '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} @@ -856,6 +876,9 @@ packages: blob-to-buffer@1.2.9: resolution: {integrity: sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==} + blurhash@2.0.5: + resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==} + boxen@8.0.1: resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} engines: {node: '>=18'} @@ -1321,6 +1344,9 @@ packages: resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} engines: {node: '>= 12.0.0'} + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -1567,6 +1593,10 @@ packages: ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + on-change@4.0.2: + resolution: {integrity: sha512-cMtCyuJmTx/bg2HCpHo3ZLeF7FZnBOapLqZHr2AlLeJ5Ul0Zu2mUJJz051Fdwu/Et2YW04ZD+TtU+gVy0ACNCA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + oniguruma-parser@0.12.1: resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} @@ -1637,6 +1667,9 @@ packages: peerDependencies: react: ^19.1.0 + react-merge-refs@2.1.1: + resolution: {integrity: sha512-jLQXJ/URln51zskhgppGJ2ub7b2WFKGq3cl3NYKtlHoTG+dN2q7EzWrn3hN3EgPsTMvpR9tpq5ijdp7YwFZkag==} + react-refresh@0.17.0: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} @@ -1727,6 +1760,9 @@ packages: scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -1803,6 +1839,9 @@ packages: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} + thumbhash@0.1.1: + resolution: {integrity: sha512-kH5pKeIIBPQXAOni2AiY/Cu/NKdkFREdpH+TLdM0g6WA7RriCv0kPLgP731ady67MhTAqrVG/4mnEeibVuCJcg==} + tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} @@ -2630,6 +2669,21 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} + '@splinetool/react-spline@4.1.0(@splinetool/runtime@1.10.39)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@splinetool/runtime': 1.10.39 + blurhash: 2.0.5 + lodash.debounce: 4.0.8 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-merge-refs: 2.1.1 + thumbhash: 0.1.1 + + '@splinetool/runtime@1.10.39': + dependencies: + on-change: 4.0.2 + semver-compare: 1.0.0 + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 @@ -2927,6 +2981,8 @@ snapshots: blob-to-buffer@1.2.9: {} + blurhash@2.0.5: {} + boxen@8.0.1: dependencies: ansi-align: 3.0.1 @@ -3448,6 +3504,8 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.1 lightningcss-win32-x64-msvc: 1.30.1 + lodash.debounce@4.0.8: {} + longest-streak@3.1.0: {} lru-cache@10.4.3: {} @@ -3949,6 +4007,8 @@ snapshots: ohash@2.0.11: {} + on-change@4.0.2: {} + oniguruma-parser@0.12.1: {} oniguruma-to-es@4.3.3: @@ -4025,6 +4085,8 @@ snapshots: react: 19.1.0 scheduler: 0.26.0 + react-merge-refs@2.1.1: {} + react-refresh@0.17.0: {} react@19.1.0: {} @@ -4207,6 +4269,8 @@ snapshots: scheduler@0.26.0: {} + semver-compare@1.0.0: {} + semver@6.3.1: {} semver@7.7.2: {} @@ -4312,6 +4376,8 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 + thumbhash@0.1.1: {} + tiny-inflate@1.0.3: {} tinyexec@0.3.2: {} diff --git a/www/src/components/Hero.tsx b/www/src/components/Hero.tsx index 960e646..d6942d4 100644 --- a/www/src/components/Hero.tsx +++ b/www/src/components/Hero.tsx @@ -1,11 +1,64 @@ -import React from 'react'; -import { Button } from './ui/button'; -import { ArrowRight, Shield, RefreshCw } from 'lucide-react'; -import { GitHubLogoIcon } from '@radix-ui/react-icons'; +import React, { useRef, useEffect } from "react"; +import { Button } from "./ui/button"; +import { ArrowRight, Shield, RefreshCw } from "lucide-react"; +import { GitHubLogoIcon } from "@radix-ui/react-icons"; +import Spline from "@splinetool/react-spline"; export function Hero() { + const splineRef = useRef(null); + + function onLoad(spline: any) { + splineRef.current = spline; + + // - try multiple selectors + const remove = () => { + // Try the spline-viewer element + const viewer = document.querySelector("spline-viewer"); + if (viewer && (viewer as any).shadowRoot) { + // Try different selectors + const selectors = [ + "#logo", + ".logo", + '[id*="logo"]', + '[class*="logo"]', + 'a[href*="spline"]', + ]; + + selectors.forEach((selector) => { + const element = (viewer as any).shadowRoot.querySelector(selector); + }); + + // Also check for any links containing "Built with Spline" + const allElements = (viewer as any).shadowRoot.querySelectorAll("*"); + allElements.forEach((el: any) => { + if (el.textContent && el.textContent.includes("Built with Spline")) { + el.remove(); + console.log('Removed element containing "Built with Spline"'); + } + }); + } + }; + + // Try removing at different intervals to catch dynamically added elements + setTimeout(remove, 100); + setTimeout(remove, 500); + setTimeout(remove, 1000); + setTimeout(remove, 2000); + } + + + useEffect(() => { + // Ensure the Spline scene is loaded before trying to remove + const interval = setInterval(() => { + if (splineRef.current && splineRef.current.spline) { + onLoad(Spline); + clearInterval(interval); + } + }, 100); + return () => clearInterval(interval); + }, []); return ( -
+
{/* Elegant gradient background */}
@@ -13,26 +66,17 @@ export function Hero() {
-
-
-
- Gitea Mirror Logo - Gitea Mirror Logo -
-
- -

- - Keep Your Code - + {/* spline object */} +
+ +
+ {/* div to avoid clipping in lower screen heights */} + +
+

+ Keep Your Code
Safe & Synced @@ -40,8 +84,9 @@ export function Hero() {

- Automatically mirror your GitHub repositories to self-hosted Gitea. - Never lose access to your code with continuous backup and synchronization. + Automatically mirror your GitHub repositories to self-hosted Gitea. + Never lose access to your code with continuous backup and + synchronization.

@@ -59,20 +104,32 @@ export function Hero() {
+ {/* Call to action buttons */}

); -} \ No newline at end of file +} diff --git a/www/src/styles/global.css b/www/src/styles/global.css index 6a0ea6c..4e6cf6d 100644 --- a/www/src/styles/global.css +++ b/www/src/styles/global.css @@ -1,10 +1,10 @@ -@import 'tailwindcss'; +@import "tailwindcss"; @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @custom-media --xs (width >= 475px); -@import 'tailwindcss/theme' layer(theme); +@import "tailwindcss/theme" layer(theme); @theme inline { --radius-sm: calc(var(--radius) - 4px); @@ -134,78 +134,92 @@ /* Custom gradient utilities */ @layer utilities { .bg-gradient-radial { - background-image: radial-gradient(circle at center, var(--tw-gradient-stops)); + background-image: radial-gradient( + circle at center, + var(--tw-gradient-stops) + ); } - + .text-gradient { @apply bg-gradient-to-r bg-clip-text text-transparent; } - + .gradient-border { position: relative; - background: linear-gradient(var(--background), var(--background)) padding-box, - linear-gradient(to right, var(--tw-gradient-stops)) border-box; + background: linear-gradient(var(--background), var(--background)) + padding-box, + linear-gradient(to right, var(--tw-gradient-stops)) border-box; border: 2px solid transparent; } - + .glow-sm { box-shadow: 0 0 20px -5px var(--tw-shadow-color); } - + .glow-md { box-shadow: 0 0 40px -10px var(--tw-shadow-color); } - + .glow-lg { box-shadow: 0 0 60px -15px var(--tw-shadow-color); } - + /* Accent color utilities */ .text-accent-purple { color: var(--accent-purple); } - + .text-accent-teal { color: var(--accent-teal); } - + .text-accent-coral { color: var(--accent-coral); } - + .bg-accent-purple { background-color: var(--accent-purple); } - + .bg-accent-teal { background-color: var(--accent-teal); } - + .bg-accent-coral { background-color: var(--accent-coral); } - + .from-accent-purple\/10 { --tw-gradient-from: oklch(from var(--accent-purple) l c h / 0.1); } - + .from-accent-teal\/10 { --tw-gradient-from: oklch(from var(--accent-teal) l c h / 0.1); } - + .from-accent-coral\/10 { --tw-gradient-from: oklch(from var(--accent-coral) l c h / 0.1); } - + .to-accent-purple\/10 { --tw-gradient-to: oklch(from var(--accent-purple) l c h / 0.1); } - + .to-accent-teal\/10 { --tw-gradient-to: oklch(from var(--accent-teal) l c h / 0.1); } - + .to-accent-coral\/10 { --tw-gradient-to: oklch(from var(--accent-coral) l c h / 0.1); } + + @media (width >= 135rem /* 2160px */) { + .spline-object { + max-height: 70rem /* 960px */; + @apply -translate-y-40; + } + .clip-avoid { + height: 25rem /* 320px */; + } + } } From 87ca3bc12fc7fb0996d2f2cd8edde0238936ad4c Mon Sep 17 00:00:00 2001 From: abhrajitray77 Date: Tue, 5 Aug 2025 13:27:09 +0530 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=A7cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- www/src/components/Hero.tsx | 52 ------------------------------------- 1 file changed, 52 deletions(-) diff --git a/www/src/components/Hero.tsx b/www/src/components/Hero.tsx index d6942d4..291ab6b 100644 --- a/www/src/components/Hero.tsx +++ b/www/src/components/Hero.tsx @@ -1,62 +1,10 @@ -import React, { useRef, useEffect } from "react"; import { Button } from "./ui/button"; import { ArrowRight, Shield, RefreshCw } from "lucide-react"; import { GitHubLogoIcon } from "@radix-ui/react-icons"; import Spline from "@splinetool/react-spline"; export function Hero() { - const splineRef = useRef(null); - function onLoad(spline: any) { - splineRef.current = spline; - - // - try multiple selectors - const remove = () => { - // Try the spline-viewer element - const viewer = document.querySelector("spline-viewer"); - if (viewer && (viewer as any).shadowRoot) { - // Try different selectors - const selectors = [ - "#logo", - ".logo", - '[id*="logo"]', - '[class*="logo"]', - 'a[href*="spline"]', - ]; - - selectors.forEach((selector) => { - const element = (viewer as any).shadowRoot.querySelector(selector); - }); - - // Also check for any links containing "Built with Spline" - const allElements = (viewer as any).shadowRoot.querySelectorAll("*"); - allElements.forEach((el: any) => { - if (el.textContent && el.textContent.includes("Built with Spline")) { - el.remove(); - console.log('Removed element containing "Built with Spline"'); - } - }); - } - }; - - // Try removing at different intervals to catch dynamically added elements - setTimeout(remove, 100); - setTimeout(remove, 500); - setTimeout(remove, 1000); - setTimeout(remove, 2000); - } - - - useEffect(() => { - // Ensure the Spline scene is loaded before trying to remove - const interval = setInterval(() => { - if (splineRef.current && splineRef.current.spline) { - onLoad(Spline); - clearInterval(interval); - } - }, 100); - return () => clearInterval(interval); - }, []); return (
{/* Elegant gradient background */}