Merge pull request #64 from abhrajitray77/hero-redesign

Hero redesign
This commit is contained in:
ARUNAVO RAY
2025-08-05 13:55:40 +05:30
committed by GitHub
4 changed files with 143 additions and 56 deletions

View File

@@ -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",

66
www/pnpm-lock.yaml generated
View File

@@ -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: {}

View File

@@ -1,11 +1,12 @@
import React from 'react';
import { Button } from './ui/button';
import { ArrowRight, Shield, RefreshCw } from 'lucide-react';
import { GitHubLogoIcon } from '@radix-ui/react-icons';
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() {
return (
<section className="relative min-h-[100vh] pt-20 pb-10 flex items-center justify-center px-4 sm:px-6 lg:px-8 overflow-hidden">
<section className="relative min-h-[100vh] pt-20 pb-10 flex flex-col items-center justify-center px-4 sm:px-6 lg:px-8 overflow-hidden">
{/* Elegant gradient background */}
<div className="absolute inset-0 -z-10 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-accent/5"></div>
@@ -13,26 +14,17 @@ export function Hero() {
<div className="absolute -bottom-1/2 -right-1/2 w-full h-full bg-gradient-radial from-accent/10 to-transparent blur-3xl"></div>
</div>
<div className="max-w-7xl mx-auto text-center w-full">
<div className="mb-6 sm:mb-8 flex justify-center">
<div className="relative">
<img
src="/assets/logo-no-bg.png"
alt="Gitea Mirror Logo"
className="relative w-20 h-20 sm:w-24 sm:h-24 md:w-32 md:h-32 dark:hidden"
/>
<img
src="/assets/logo-no-bg.png"
alt="Gitea Mirror Logo"
className="relative w-20 h-20 sm:w-24 sm:h-24 md:w-32 md:h-32 hidden dark:block"
/>
</div>
</div>
<h1 className="text-3xl xs:text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight leading-tight">
<span className="text-foreground">
Keep Your Code
</span>
{/* spline object */}
<div className="spline-object absolute inset-0 max-lg:-z-10 max-h-[40rem] -translate-y-16 md:max-h-[50rem] lg:max-h-[60%] xl:max-h-[70%] 2xl:max-h-[80%] md:-translate-y-24 lg:-translate-y-28 flex items-center justify-center">
<Spline
scene="https://prod.spline.design/jl0aKWbdH9vHQnYV/scene.splinecode"
/>
</div>
{/* div to avoid clipping in lower screen heights */}
<div className="clip-avoid w-full h-[16rem] md:h-[20rem] lg:h-[12rem] 2xl:h-[16rem]" aria-hidden="true"></div>
<div className="max-w-7xl mx-auto pb-20 lg:pb-60 xl:pb-24 text-center w-full">
<h1 className="pt-10 2xl:pt-20 text-3xl xs:text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight leading-tight">
<span className="text-foreground">Keep Your Code</span>
<br />
<span className="text-gradient from-primary via-accent to-accent-purple">
Safe & Synced
@@ -40,8 +32,9 @@ export function Hero() {
</h1>
<p className="mt-4 sm:mt-6 text-base sm:text-lg md:text-xl text-muted-foreground max-w-3xl mx-auto px-4">
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.
</p>
<div className="mt-6 sm:mt-8 flex flex-wrap items-center justify-center gap-3 text-xs sm:text-sm text-muted-foreground px-4">
@@ -59,20 +52,32 @@ export function Hero() {
</div>
</div>
{/* Call to action buttons */}
<div className="mt-8 sm:mt-10 flex flex-col sm:flex-row items-center justify-center gap-3 sm:gap-4 px-4">
<Button size="lg" className="group w-full sm:w-auto min-h-[48px] text-base bg-gradient-to-r from-primary to-accent hover:from-primary/90 hover:to-accent/90 shadow-lg shadow-primary/25 hover:shadow-xl hover:shadow-primary/30 transition-all duration-300" asChild>
<a href="https://github.com/RayLabsHQ/gitea-mirror" target="_blank" rel="noopener noreferrer">
<Button
size="lg"
className="relative group w-full sm:w-auto min-h-[48px] text-base bg-gradient-to-r from-primary to-accent hover:from-primary/90 hover:to-accent/90 shadow-lg shadow-primary/25 hover:shadow-xl hover:shadow-primary/30 transition-all duration-300"
asChild
>
<a
href="https://github.com/RayLabsHQ/gitea-mirror"
target="_blank"
rel="noopener noreferrer"
>
Get Started
<ArrowRight className="ml-2 h-4 w-4 transition-transform group-hover:translate-x-1" />
</a>
</Button>
<Button size="lg" variant="outline" className="w-full sm:w-auto min-h-[48px] text-base border-primary/20 hover:bg-primary/10 hover:border-primary/30 hover:text-foreground transition-all duration-300" asChild>
<a href="#features">
View Features
</a>
<Button
size="lg"
variant="outline"
className="relative w-full sm:w-auto min-h-[48px] text-base border-primary/20 hover:bg-primary/10 hover:border-primary/30 hover:text-foreground transition-all duration-300"
asChild
>
<a href="#features">View Features</a>
</Button>
</div>
</div>
</section>
);
}
}

View File

@@ -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 */;
}
}
}