feat(website): homepage makeover
This commit is contained in:
30
package-lock.json
generated
30
package-lock.json
generated
@@ -1782,6 +1782,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-icons": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-id": {
|
"node_modules/@radix-ui/react-id": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
|
||||||
@@ -7179,6 +7188,25 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-icons": {
|
||||||
|
"version": "16.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-16.2.0.tgz",
|
||||||
|
"integrity": "sha512-SCV4cAX8O2M2WQ3QJm+3k4QdcUIJiBiwKNViQiOwPjWbFWgypzelviW+Bp0A2ij6r/DIEZpTTDcLgD/BE4aexQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/simple-icons"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/simple-icons"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "CC0-1.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/slice-ansi": {
|
"node_modules/slice-ansi": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz",
|
||||||
@@ -8169,6 +8197,7 @@
|
|||||||
"name": "@page-agent/website",
|
"name": "@page-agent/website",
|
||||||
"version": "0.0.15",
|
"version": "0.0.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-separator": "^1.1.8",
|
"@radix-ui/react-separator": "^1.1.8",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
"@radix-ui/react-switch": "^1.2.6",
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
@@ -8179,6 +8208,7 @@
|
|||||||
"motion": "^12.23.26",
|
"motion": "^12.23.26",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"rough-notation": "^0.5.1",
|
"rough-notation": "^0.5.1",
|
||||||
|
"simple-icons": "^16.2.0",
|
||||||
"sonner": "^2.0.7",
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^3.4.0"
|
"tailwind-merge": "^3.4.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"wouter": "^3.8.1"
|
"wouter": "^3.8.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-separator": "^1.1.8",
|
"@radix-ui/react-separator": "^1.1.8",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
"@radix-ui/react-switch": "^1.2.6",
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
"motion": "^12.23.26",
|
"motion": "^12.23.26",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"rough-notation": "^0.5.1",
|
"rough-notation": "^0.5.1",
|
||||||
|
"simple-icons": "^16.2.0",
|
||||||
"sonner": "^2.0.7",
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^3.4.0"
|
"tailwind-merge": "^3.4.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { siGithub } from 'simple-icons'
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
@@ -19,8 +20,13 @@ export default function Footer() {
|
|||||||
className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors duration-200"
|
className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors duration-200"
|
||||||
aria-label={t('footer.github_label')}
|
aria-label={t('footer.github_label')}
|
||||||
>
|
>
|
||||||
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
<svg
|
||||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
className="w-5 h-5 fill-current"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d={siGithub.path} />
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
import { BookOpen, Menu, X } from 'lucide-react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { siGithub } from 'simple-icons'
|
||||||
import { Link } from 'wouter'
|
import { Link } from 'wouter'
|
||||||
|
|
||||||
import LanguageSwitcher from './LanguageSwitcher'
|
import LanguageSwitcher from './LanguageSwitcher'
|
||||||
import ThemeSwitcher from './ThemeSwitcher'
|
import ThemeSwitcher from './ThemeSwitcher'
|
||||||
import { BookIcon, CloseIcon, GithubIcon, MenuIcon } from './icons'
|
import { HyperText } from './ui/hyper-text'
|
||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
@@ -34,9 +36,14 @@ export default function Header() {
|
|||||||
<span className="text-base sm:text-xl font-bold text-gray-900 dark:text-white block leading-tight">
|
<span className="text-base sm:text-xl font-bold text-gray-900 dark:text-white block leading-tight">
|
||||||
page-agent
|
page-agent
|
||||||
</span>
|
</span>
|
||||||
<p className="hidden sm:block text-xs text-gray-600 dark:text-gray-300">
|
<HyperText
|
||||||
|
as="p"
|
||||||
|
className="hidden sm:block text-xs text-gray-600 dark:text-gray-300 py-0 font-normal overflow-visible"
|
||||||
|
duration={600}
|
||||||
|
animateOnHover={true}
|
||||||
|
>
|
||||||
{t('header.slogan')}
|
{t('header.slogan')}
|
||||||
</p>
|
</HyperText>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
@@ -51,7 +58,7 @@ export default function Header() {
|
|||||||
className="p-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 shrink-0"
|
className="p-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 shrink-0"
|
||||||
aria-label={t('header.nav_docs')}
|
aria-label={t('header.nav_docs')}
|
||||||
>
|
>
|
||||||
<BookIcon className="w-5 h-5" />
|
<BookOpen className="w-5 h-5" />
|
||||||
</Link>
|
</Link>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/alibaba/page-agent"
|
href="https://github.com/alibaba/page-agent"
|
||||||
@@ -60,7 +67,14 @@ export default function Header() {
|
|||||||
className="p-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 shrink-0"
|
className="p-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 shrink-0"
|
||||||
aria-label={t('header.nav_source')}
|
aria-label={t('header.nav_source')}
|
||||||
>
|
>
|
||||||
<GithubIcon className="w-5 h-5" />
|
<svg
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
className="w-5 h-5 fill-current"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d={siGithub.path} />
|
||||||
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -74,7 +88,7 @@ export default function Header() {
|
|||||||
href="/docs/introduction/overview"
|
href="/docs/introduction/overview"
|
||||||
className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
||||||
>
|
>
|
||||||
<BookIcon />
|
<BookOpen className="w-4 h-4" />
|
||||||
{t('header.nav_docs')}
|
{t('header.nav_docs')}
|
||||||
</Link>
|
</Link>
|
||||||
<a
|
<a
|
||||||
@@ -84,7 +98,14 @@ export default function Header() {
|
|||||||
className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
||||||
aria-label={t('header.nav_source')}
|
aria-label={t('header.nav_source')}
|
||||||
>
|
>
|
||||||
<GithubIcon />
|
<svg
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
className="w-4 h-4 fill-current"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d={siGithub.path} />
|
||||||
|
</svg>
|
||||||
{t('header.nav_source')}
|
{t('header.nav_source')}
|
||||||
</a>
|
</a>
|
||||||
<ThemeSwitcher />
|
<ThemeSwitcher />
|
||||||
@@ -100,7 +121,7 @@ export default function Header() {
|
|||||||
aria-controls="mobile-menu"
|
aria-controls="mobile-menu"
|
||||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||||
>
|
>
|
||||||
{mobileMenuOpen ? <CloseIcon /> : <MenuIcon />}
|
{mobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -116,7 +137,7 @@ export default function Header() {
|
|||||||
className="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
className="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
onClick={() => setMobileMenuOpen(false)}
|
||||||
>
|
>
|
||||||
<BookIcon className="w-5 h-5" />
|
<BookOpen className="w-5 h-5" />
|
||||||
{t('header.nav_docs')}
|
{t('header.nav_docs')}
|
||||||
</Link>
|
</Link>
|
||||||
<a
|
<a
|
||||||
@@ -126,7 +147,14 @@ export default function Header() {
|
|||||||
className="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
className="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
||||||
aria-label={t('header.nav_source')}
|
aria-label={t('header.nav_source')}
|
||||||
>
|
>
|
||||||
<GithubIcon className="w-5 h-5" />
|
<svg
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
className="w-5 h-5 fill-current"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d={siGithub.path} />
|
||||||
|
</svg>
|
||||||
{t('header.nav_source')}
|
{t('header.nav_source')}
|
||||||
</a>
|
</a>
|
||||||
<div className="flex items-center gap-3 px-3 py-2">
|
<div className="flex items-center gap-3 px-3 py-2">
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
// SVG图标组件集合,用于Header等地方复用
|
|
||||||
|
|
||||||
interface IconProps {
|
|
||||||
className?: string
|
|
||||||
'aria-hidden'?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export function BookIcon({ className = 'w-4 h-4', ...props }: IconProps) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className={className}
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
aria-hidden="true"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={2}
|
|
||||||
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function GithubIcon({ className = 'w-4 h-4', ...props }: IconProps) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className={className}
|
|
||||||
fill="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
aria-hidden="true"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function MenuIcon({ className = 'w-6 h-6', ...props }: IconProps) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className={className}
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
aria-hidden="true"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={2}
|
|
||||||
d="M4 6h16M4 12h16M4 18h16"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function CloseIcon({ className = 'w-6 h-6', ...props }: IconProps) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className={className}
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
aria-hidden="true"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
91
packages/website/src/components/ui/bento-grid.tsx
Normal file
91
packages/website/src/components/ui/bento-grid.tsx
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import { ArrowRightIcon } from '@radix-ui/react-icons'
|
||||||
|
import { ComponentPropsWithoutRef, ReactNode } from 'react'
|
||||||
|
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
interface BentoGridProps extends ComponentPropsWithoutRef<'div'> {
|
||||||
|
children: ReactNode
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BentoCardProps extends ComponentPropsWithoutRef<'div'> {
|
||||||
|
name: string
|
||||||
|
className: string
|
||||||
|
background: ReactNode
|
||||||
|
Icon: React.ElementType
|
||||||
|
description: string
|
||||||
|
href: string
|
||||||
|
cta: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const BentoGrid = ({ children, className, ...props }: BentoGridProps) => {
|
||||||
|
return (
|
||||||
|
<div className={cn('grid w-full auto-rows-[22rem] grid-cols-3 gap-4', className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const BentoCard = ({
|
||||||
|
name,
|
||||||
|
className,
|
||||||
|
background,
|
||||||
|
Icon,
|
||||||
|
description,
|
||||||
|
href,
|
||||||
|
cta,
|
||||||
|
...props
|
||||||
|
}: BentoCardProps) => (
|
||||||
|
<div
|
||||||
|
key={name}
|
||||||
|
className={cn(
|
||||||
|
'group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl',
|
||||||
|
// light styles
|
||||||
|
'bg-background [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]',
|
||||||
|
// dark styles
|
||||||
|
'dark:bg-background transform-gpu dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset] dark:[border:1px_solid_rgba(255,255,255,.1)]',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div>{background}</div>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="pointer-events-none z-10 flex transform-gpu flex-col gap-1 transition-all duration-300 lg:group-hover:-translate-y-10">
|
||||||
|
<Icon className="h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75" />
|
||||||
|
<h3 className="text-xl font-semibold text-neutral-700 dark:text-neutral-300">{name}</h3>
|
||||||
|
<p className="max-w-lg text-neutral-400">{description}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'pointer-events-none flex w-full translate-y-0 transform-gpu flex-row items-center transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100 lg:hidden'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Button variant="link" asChild size="sm" className="pointer-events-auto p-0">
|
||||||
|
<a href={href}>
|
||||||
|
{cta}
|
||||||
|
<ArrowRightIcon className="ms-2 h-4 w-4 rtl:rotate-180" />
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'pointer-events-none absolute bottom-0 hidden w-full translate-y-10 transform-gpu flex-row items-center p-4 opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100 lg:flex'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Button variant="link" asChild size="sm" className="pointer-events-auto p-0">
|
||||||
|
<a href={href}>
|
||||||
|
{cta}
|
||||||
|
<ArrowRightIcon className="ms-2 h-4 w-4 rtl:rotate-180" />
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
export { BentoCard, BentoGrid }
|
||||||
79
packages/website/src/components/ui/blur-fade.tsx
Normal file
79
packages/website/src/components/ui/blur-fade.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import {
|
||||||
|
AnimatePresence,
|
||||||
|
MotionProps,
|
||||||
|
UseInViewOptions,
|
||||||
|
Variants,
|
||||||
|
motion,
|
||||||
|
useInView,
|
||||||
|
} from 'motion/react'
|
||||||
|
import { useRef } from 'react'
|
||||||
|
|
||||||
|
type MarginType = UseInViewOptions['margin']
|
||||||
|
|
||||||
|
interface BlurFadeProps extends MotionProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
className?: string
|
||||||
|
variant?: {
|
||||||
|
hidden: { y: number }
|
||||||
|
visible: { y: number }
|
||||||
|
}
|
||||||
|
duration?: number
|
||||||
|
delay?: number
|
||||||
|
offset?: number
|
||||||
|
direction?: 'up' | 'down' | 'left' | 'right'
|
||||||
|
inView?: boolean
|
||||||
|
inViewMargin?: MarginType
|
||||||
|
blur?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BlurFade({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
variant,
|
||||||
|
duration = 0.4,
|
||||||
|
delay = 0,
|
||||||
|
offset = 6,
|
||||||
|
direction = 'down',
|
||||||
|
inView = false,
|
||||||
|
inViewMargin = '-50px',
|
||||||
|
blur = '6px',
|
||||||
|
...props
|
||||||
|
}: BlurFadeProps) {
|
||||||
|
const ref = useRef(null)
|
||||||
|
const inViewResult = useInView(ref, { once: true, margin: inViewMargin })
|
||||||
|
const isInView = !inView || inViewResult
|
||||||
|
const defaultVariants: Variants = {
|
||||||
|
hidden: {
|
||||||
|
[direction === 'left' || direction === 'right' ? 'x' : 'y']:
|
||||||
|
direction === 'right' || direction === 'down' ? -offset : offset,
|
||||||
|
opacity: 0,
|
||||||
|
filter: `blur(${blur})`,
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
[direction === 'left' || direction === 'right' ? 'x' : 'y']: 0,
|
||||||
|
opacity: 1,
|
||||||
|
filter: `blur(0px)`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const combinedVariants = variant || defaultVariants
|
||||||
|
return (
|
||||||
|
<AnimatePresence>
|
||||||
|
<motion.div
|
||||||
|
ref={ref}
|
||||||
|
initial="hidden"
|
||||||
|
animate={isInView ? 'visible' : 'hidden'}
|
||||||
|
exit="hidden"
|
||||||
|
variants={combinedVariants}
|
||||||
|
transition={{
|
||||||
|
delay: 0.04 + delay,
|
||||||
|
duration,
|
||||||
|
ease: 'easeOut',
|
||||||
|
}}
|
||||||
|
className={className}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</motion.div>
|
||||||
|
</AnimatePresence>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -108,7 +108,7 @@ export const NeonGradientCard: React.FC<NeonGradientCardProps> = ({
|
|||||||
'--pseudo-element-background-image': `linear-gradient(0deg, ${neonColors.firstColor}, ${neonColors.secondColor})`,
|
'--pseudo-element-background-image': `linear-gradient(0deg, ${neonColors.firstColor}, ${neonColors.secondColor})`,
|
||||||
'--pseudo-element-width': `${dimensions.width + borderSize * 2}px`,
|
'--pseudo-element-width': `${dimensions.width + borderSize * 2}px`,
|
||||||
'--pseudo-element-height': `${dimensions.height + borderSize * 2}px`,
|
'--pseudo-element-height': `${dimensions.height + borderSize * 2}px`,
|
||||||
'--after-blur': `${dimensions.width / 3}px`,
|
'--after-blur': `${dimensions.width / 6}px`,
|
||||||
} as CSSProperties
|
} as CSSProperties
|
||||||
}
|
}
|
||||||
className={cn('relative z-10 size-full rounded-[var(--border-radius)]', className)}
|
className={cn('relative z-10 size-full rounded-[var(--border-radius)]', className)}
|
||||||
@@ -116,7 +116,7 @@ export const NeonGradientCard: React.FC<NeonGradientCardProps> = ({
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative size-full min-h-[inherit] rounded-[var(--card-content-radius)] bg-gray-100 p-6',
|
'relative size-full min-h-[inherit] rounded-[var(--card-content-radius)] bg-gray-100',
|
||||||
'before:absolute before:-top-[var(--border-size)] before:-left-[var(--border-size)] before:-z-10 before:block',
|
'before:absolute before:-top-[var(--border-size)] before:-left-[var(--border-size)] before:-z-10 before:block',
|
||||||
"before:h-[var(--pseudo-element-height)] before:w-[var(--pseudo-element-width)] before:rounded-[var(--border-radius)] before:content-['']",
|
"before:h-[var(--pseudo-element-height)] before:w-[var(--pseudo-element-width)] before:rounded-[var(--border-radius)] before:content-['']",
|
||||||
'before:bg-[linear-gradient(0deg,var(--neon-first-color),var(--neon-second-color))] before:bg-[length:100%_200%]',
|
'before:bg-[linear-gradient(0deg,var(--neon-first-color),var(--neon-second-color))] before:bg-[length:100%_200%]',
|
||||||
|
|||||||
@@ -141,7 +141,9 @@ export const SparklesText: React.FC<SparklesTextProps> = ({
|
|||||||
{sparkles.map((sparkle) => (
|
{sparkles.map((sparkle) => (
|
||||||
<Sparkle key={sparkle.id} {...sparkle} />
|
<Sparkle key={sparkle.id} {...sparkle} />
|
||||||
))}
|
))}
|
||||||
<strong>{children}</strong>
|
<strong className="bg-linear-to-r from-[var(--sparkles-first-color)] to-[var(--sparkles-second-color)] bg-clip-text text-transparent">
|
||||||
|
{children}
|
||||||
|
</strong>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export default {
|
|||||||
badge: 'GUI Agent in your webpage',
|
badge: 'GUI Agent in your webpage',
|
||||||
title_line1: 'The AI Operator',
|
title_line1: 'The AI Operator',
|
||||||
title_line2: 'Living in Your Web App',
|
title_line2: 'Living in Your Web App',
|
||||||
subtitle_emoji: '🪄 One line of CDN',
|
subtitle_emoji: '🪄One line of code',
|
||||||
subtitle_main: ' adds intelligent GUI Agents to your website.',
|
subtitle_main: ' adds intelligent GUI Agents to your website.',
|
||||||
subtitle_detail: 'Users give natural language commands, AI handles the rest.',
|
subtitle_detail: 'Users give natural language commands, AI handles the rest.',
|
||||||
tab_try: '🚀 Try It Now',
|
tab_try: '🚀 Try It Now',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export default {
|
|||||||
badge: 'GUI Agent in your webpage',
|
badge: 'GUI Agent in your webpage',
|
||||||
title_line1: '让你的 Web 应用',
|
title_line1: '让你的 Web 应用',
|
||||||
title_line2: '拥有 AI 操作员',
|
title_line2: '拥有 AI 操作员',
|
||||||
subtitle_emoji: '🪄 一行 CDN 引入',
|
subtitle_emoji: '🪄一行代码',
|
||||||
subtitle_main: ',为你的网站添加 GUI Agent。',
|
subtitle_main: ',为你的网站添加 GUI Agent。',
|
||||||
subtitle_detail: '用户/答疑机器人给出文字指示,AI 帮你操作页面。',
|
subtitle_detail: '用户/答疑机器人给出文字指示,AI 帮你操作页面。',
|
||||||
tab_try: '🚀 立即尝试',
|
tab_try: '🚀 立即尝试',
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable react-dom/no-dangerously-set-innerhtml */
|
/* eslint-disable react-dom/no-dangerously-set-innerhtml */
|
||||||
|
import { Bot, Box, MessageSquare, PlayCircle, Shield, Sparkles, Users, Zap } from 'lucide-react'
|
||||||
import { PageAgent } from 'page-agent'
|
import { PageAgent } from 'page-agent'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@@ -6,6 +7,11 @@ import { Link, useSearchParams } from 'wouter'
|
|||||||
|
|
||||||
import Footer from './components/Footer'
|
import Footer from './components/Footer'
|
||||||
import Header from './components/Header'
|
import Header from './components/Header'
|
||||||
|
import { AnimatedGradientText } from './components/ui/animated-gradient-text'
|
||||||
|
import { Highlighter } from './components/ui/highlighter'
|
||||||
|
import { NeonGradientCard } from './components/ui/neon-gradient-card'
|
||||||
|
import { Particles } from './components/ui/particles'
|
||||||
|
import { SparklesText } from './components/ui/sparkles-text'
|
||||||
import { CDN_CN_URL, CDN_URL } from './constants'
|
import { CDN_CN_URL, CDN_URL } from './constants'
|
||||||
|
|
||||||
function getInjection(useCN?: boolean) {
|
function getInjection(useCN?: boolean) {
|
||||||
@@ -82,19 +88,28 @@ export default function HomePage() {
|
|||||||
<main id="main-content">
|
<main id="main-content">
|
||||||
<section className="relative px-6 py-22 lg:py-28" aria-labelledby="hero-heading">
|
<section className="relative px-6 py-22 lg:py-28" aria-labelledby="hero-heading">
|
||||||
<div className="max-w-7xl mx-auto text-center">
|
<div className="max-w-7xl mx-auto text-center">
|
||||||
{/* Background Pattern */}
|
{/* Background Pattern + Particles */}
|
||||||
<div className="absolute inset-0 opacity-30" aria-hidden="true">
|
<div className="absolute inset-0 opacity-30" aria-hidden="true">
|
||||||
<div className="absolute inset-0 bg-linear-to-r from-blue-400/20 to-purple-400/20 rounded-3xl transform rotate-1"></div>
|
<div className="absolute inset-0 bg-linear-to-r from-blue-400/20 to-purple-400/20 rounded-3xl transform rotate-1"></div>
|
||||||
<div className="absolute inset-0 bg-linear-to-l from-purple-400/20 to-blue-400/20 rounded-3xl transform -rotate-1"></div>
|
<div className="absolute inset-0 bg-linear-to-l from-purple-400/20 to-blue-400/20 rounded-3xl transform -rotate-1"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<Particles
|
||||||
|
className="absolute inset-0"
|
||||||
|
quantity={80}
|
||||||
|
staticity={30}
|
||||||
|
ease={80}
|
||||||
|
color="#6366f1"
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="relative z-10">
|
<div className="relative z-10">
|
||||||
<div className="inline-flex items-center px-4 py-2 mb-8 text-sm font-medium text-blue-700 bg-blue-100 rounded-full dark:text-blue-300 dark:bg-blue-900/30">
|
<div className="inline-flex items-center px-4 py-2 mb-8 text-sm font-medium bg-white/90 dark:bg-gray-800/90 rounded-full shadow-lg border border-gray-200 dark:border-gray-700">
|
||||||
<span
|
<span
|
||||||
className="w-2 h-2 bg-blue-500 rounded-full mr-2 animate-pulse"
|
className="w-2 h-2 bg-blue-500 rounded-full mr-2 animate-pulse"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></span>
|
></span>
|
||||||
{t('home:hero.badge')}
|
<AnimatedGradientText colorFrom="#3b82f6" colorTo="#8b5cf6">
|
||||||
|
{t('home:hero.badge')}
|
||||||
|
</AnimatedGradientText>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1
|
<h1
|
||||||
@@ -107,23 +122,29 @@ export default function HomePage() {
|
|||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="text-xl lg:text-2xl text-gray-600 dark:text-gray-300 mb-12 max-w-4xl mx-auto leading-relaxed">
|
<p className="text-xl lg:text-2xl text-gray-600 dark:text-gray-300 mb-12 max-w-4xl mx-auto leading-relaxed">
|
||||||
<span className="bg-linear-to-r from-blue-500 to-purple-500 bg-clip-text text-transparent font-bold">
|
<Highlighter action="underline" color="#8b5cf6" strokeWidth={2}>
|
||||||
{t('home:hero.subtitle_emoji')}
|
<span className="bg-linear-to-r from-blue-500 to-purple-500 bg-clip-text text-transparent font-bold">
|
||||||
</span>
|
{t('home:hero.subtitle_emoji')}
|
||||||
|
</span>
|
||||||
|
</Highlighter>
|
||||||
{t('home:hero.subtitle_main')}
|
{t('home:hero.subtitle_main')}
|
||||||
<br />
|
<br />
|
||||||
{t('home:hero.subtitle_detail')}
|
{t('home:hero.subtitle_detail')}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Try It Now Section - Tab Card */}
|
{/* Try It Now Section - Tab Card */}
|
||||||
<div className="mt-8 mb-6">
|
<div className="mb-12">
|
||||||
<div className="max-w-3xl mx-auto">
|
<div className="max-w-3xl mx-auto">
|
||||||
<div className="bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
|
<NeonGradientCard
|
||||||
|
borderSize={2}
|
||||||
|
borderRadius={20}
|
||||||
|
neonColors={{ firstColor: '#ff00aa', secondColor: '#00FFF1' }}
|
||||||
|
>
|
||||||
{/* Tab Headers */}
|
{/* Tab Headers */}
|
||||||
<div className="flex border-b border-gray-200 dark:border-gray-700">
|
<div className="flex border-b border-gray-200 dark:border-gray-700">
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveTab('try')}
|
onClick={() => setActiveTab('try')}
|
||||||
className={`flex-1 px-4 py-4 text-lg font-medium transition-colors duration-200 ${
|
className={`flex-1 px-4 py-4 text-lg font-medium transition-colors duration-200 rounded-tl-2xl ${
|
||||||
activeTab === 'try'
|
activeTab === 'try'
|
||||||
? 'bg-linear-to-r from-blue-50 to-purple-50 dark:from-blue-900/30 dark:to-purple-900/30 text-blue-700 dark:text-blue-300 border-b-2 border-blue-500'
|
? 'bg-linear-to-r from-blue-50 to-purple-50 dark:from-blue-900/30 dark:to-purple-900/30 text-blue-700 dark:text-blue-300 border-b-2 border-blue-500'
|
||||||
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-700'
|
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-700'
|
||||||
@@ -133,7 +154,7 @@ export default function HomePage() {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveTab('other')}
|
onClick={() => setActiveTab('other')}
|
||||||
className={`flex-1 px-4 py-4 text-lg font-medium transition-colors duration-200 ${
|
className={`flex-1 px-4 py-4 text-lg font-medium transition-colors duration-200 rounded-tr-2xl ${
|
||||||
activeTab === 'other'
|
activeTab === 'other'
|
||||||
? 'bg-linear-to-r from-green-50 to-blue-50 dark:from-green-900/30 dark:to-blue-900/30 text-green-700 dark:text-green-300 border-b-2 border-green-500'
|
? 'bg-linear-to-r from-green-50 to-blue-50 dark:from-green-900/30 dark:to-blue-900/30 text-green-700 dark:text-green-300 border-b-2 border-green-500'
|
||||||
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-700'
|
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-700'
|
||||||
@@ -272,7 +293,7 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</NeonGradientCard>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -326,10 +347,10 @@ export default function HomePage() {
|
|||||||
role="listitem"
|
role="listitem"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="w-12 h-12 bg-linear-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300"
|
className="w-14 h-14 bg-linear-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<span className="text-white text-xl">📦</span>
|
<Box className="w-7 h-7 text-white" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
||||||
{t('home:features.in_page.title')}
|
{t('home:features.in_page.title')}
|
||||||
@@ -345,10 +366,10 @@ export default function HomePage() {
|
|||||||
role="listitem"
|
role="listitem"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="w-12 h-12 bg-linear-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300"
|
className="w-14 h-14 bg-linear-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<span className="text-white text-xl">⚡</span>
|
<Zap className="w-7 h-7 text-white fill-white" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
||||||
{t('home:features.zero_backend.title')}
|
{t('home:features.zero_backend.title')}
|
||||||
@@ -364,10 +385,10 @@ export default function HomePage() {
|
|||||||
role="listitem"
|
role="listitem"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="w-12 h-12 bg-linear-to-br from-purple-500 to-purple-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300"
|
className="w-14 h-14 bg-linear-to-br from-purple-500 to-purple-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<span className="text-white text-xl">🌈</span>
|
<MessageSquare className="w-7 h-7 text-white" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
||||||
{t('home:features.accessible.title')}
|
{t('home:features.accessible.title')}
|
||||||
@@ -383,10 +404,10 @@ export default function HomePage() {
|
|||||||
role="listitem"
|
role="listitem"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="w-12 h-12 bg-linear-to-br from-orange-500 to-orange-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300"
|
className="w-14 h-14 bg-linear-to-br from-orange-500 to-orange-600 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<span className="text-white text-xl">🔒</span>
|
<Shield className="w-7 h-7 text-white" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
||||||
{t('home:features.secure_integration.title')}
|
{t('home:features.secure_integration.title')}
|
||||||
@@ -403,12 +424,12 @@ export default function HomePage() {
|
|||||||
<section className="px-6 py-20" aria-labelledby="use-cases-heading">
|
<section className="px-6 py-20" aria-labelledby="use-cases-heading">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2
|
<SparklesText
|
||||||
id="use-cases-heading"
|
className="text-4xl lg:text-5xl mb-6"
|
||||||
className="text-4xl lg:text-5xl font-bold mb-6 bg-linear-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"
|
colors={{ first: '#3b82f6', second: '#8b5cf6' }}
|
||||||
>
|
>
|
||||||
{t('home:use_cases.section_title')}
|
{t('home:use_cases.section_title')}
|
||||||
</h2>
|
</SparklesText>
|
||||||
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto">
|
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto">
|
||||||
{t('home:use_cases.section_subtitle')}
|
{t('home:use_cases.section_subtitle')}
|
||||||
</p>
|
</p>
|
||||||
@@ -416,10 +437,10 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<div className="grid lg:grid-cols-2 gap-12" role="list">
|
<div className="grid lg:grid-cols-2 gap-12" role="list">
|
||||||
{/* Use Case 1 */}
|
{/* Use Case 1 */}
|
||||||
<div className="bg-linear-to-br from-blue-100 to-purple-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl">
|
<div className="group bg-linear-to-br from-blue-100 to-purple-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl hover:shadow-xl transition-all duration-300">
|
||||||
<div className="flex items-start space-x-4">
|
<div className="flex items-start space-x-4">
|
||||||
<div className="w-10 h-10 bg-blue-500 rounded-lg flex items-center justify-center shrink-0">
|
<div className="w-12 h-12 bg-linear-to-br from-blue-500 to-purple-500 rounded-xl flex items-center justify-center shrink-0 group-hover:scale-110 transition-transform duration-300 shadow-md">
|
||||||
<span className="text-white font-bold">1</span>
|
<Bot className="w-6 h-6 text-white" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -434,10 +455,10 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Use Case 2 */}
|
{/* Use Case 2 */}
|
||||||
<div className="bg-linear-to-br from-green-100 to-blue-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl">
|
<div className="group bg-linear-to-br from-green-100 to-blue-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl hover:shadow-xl transition-all duration-300">
|
||||||
<div className="flex items-start space-x-4">
|
<div className="flex items-start space-x-4">
|
||||||
<div className="w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center shrink-0">
|
<div className="w-12 h-12 bg-linear-to-br from-green-500 to-blue-500 rounded-xl flex items-center justify-center shrink-0 group-hover:scale-110 transition-transform duration-300 shadow-md">
|
||||||
<span className="text-white font-bold">2</span>
|
<Sparkles className="w-6 h-6 text-white" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-xl font-bold mb-2 text-gray-900 dark:text-white">
|
<h3 className="text-xl font-bold mb-2 text-gray-900 dark:text-white">
|
||||||
@@ -451,10 +472,10 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Use Case 3 */}
|
{/* Use Case 3 */}
|
||||||
<div className="bg-linear-to-br from-purple-100 to-pink-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl">
|
<div className="group bg-linear-to-br from-purple-100 to-pink-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl hover:shadow-xl transition-all duration-300">
|
||||||
<div className="flex items-start space-x-4">
|
<div className="flex items-start space-x-4">
|
||||||
<div className="w-10 h-10 bg-purple-500 rounded-lg flex items-center justify-center shrink-0">
|
<div className="w-12 h-12 bg-linear-to-br from-purple-500 to-pink-500 rounded-xl flex items-center justify-center shrink-0 group-hover:scale-110 transition-transform duration-300 shadow-md">
|
||||||
<span className="text-white font-bold">3</span>
|
<PlayCircle className="w-6 h-6 text-white fill-white/30" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-xl font-bold mb-2 text-gray-900 dark:text-white">
|
<h3 className="text-xl font-bold mb-2 text-gray-900 dark:text-white">
|
||||||
@@ -468,10 +489,10 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Use Case 4 */}
|
{/* Use Case 4 */}
|
||||||
<div className="bg-linear-to-br from-orange-100 to-red-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl">
|
<div className="group bg-linear-to-br from-orange-100 to-red-100 dark:from-gray-700 dark:to-gray-800 p-8 rounded-2xl hover:shadow-xl transition-all duration-300">
|
||||||
<div className="flex items-start space-x-4">
|
<div className="flex items-start space-x-4">
|
||||||
<div className="w-10 h-10 bg-orange-500 rounded-lg flex items-center justify-center shrink-0">
|
<div className="w-12 h-12 bg-linear-to-br from-orange-500 to-red-500 rounded-xl flex items-center justify-center shrink-0 group-hover:scale-110 transition-transform duration-300 shadow-md">
|
||||||
<span className="text-white font-bold">4</span>
|
<Users className="w-6 h-6 text-white" strokeWidth={2.5} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-xl font-bold mb-2 text-gray-900 dark:text-white">
|
<h3 className="text-xl font-bold mb-2 text-gray-900 dark:text-white">
|
||||||
|
|||||||
Reference in New Issue
Block a user