✨ refactor(home): redesign hero section to dual-column layout with compliant copywriting
Redesigns the hero section into a balanced horizontal dual-column layout: - Left Column: Features title, clean legal-compliant descriptions, CTA buttons with BookOpen Docs link, and enlarged supported apps buttons (Cherry Studio and CC Switch with lobe icons) - Right Column: Smoothly integrates the terminal API demo with top horizontal alignment - i18n: Configures compliance translations for en, zh, fr, ja, ru, and vi locales
This commit is contained in:
@@ -163,7 +163,11 @@ const API_DEMOS: ApiDemoConfig[] = [
|
||||
const CYCLE_INTERVAL = 4500
|
||||
const TRANSITION_MS = 220
|
||||
|
||||
export function HeroTerminalDemo() {
|
||||
interface HeroTerminalDemoProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function HeroTerminalDemo(props: HeroTerminalDemoProps) {
|
||||
const [activeIndex, setActiveIndex] = useState(0)
|
||||
const [transitioning, setTransitioning] = useState(false)
|
||||
const intervalRef = useRef<ReturnType<typeof setInterval>>(undefined)
|
||||
@@ -202,7 +206,7 @@ export function HeroTerminalDemo() {
|
||||
const accent = ACCENT_CLASSES[demo.accent]
|
||||
|
||||
return (
|
||||
<div className='mx-auto mt-16 w-full max-w-2xl'>
|
||||
<div className={cn('mx-auto w-full max-w-2xl', props.className)}>
|
||||
<div
|
||||
className={cn(
|
||||
'overflow-hidden rounded-2xl border backdrop-blur-sm',
|
||||
|
||||
+191
-58
@@ -17,9 +17,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import { Link } from '@tanstack/react-router'
|
||||
import { ArrowRight } from 'lucide-react'
|
||||
import { ArrowRight, BookOpen } from 'lucide-react'
|
||||
import { CherryStudio } from '@lobehub/icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useStatus } from '@/hooks/use-status'
|
||||
import { HeroTerminalDemo } from '../hero-terminal-demo'
|
||||
|
||||
interface HeroProps {
|
||||
@@ -27,11 +29,59 @@ interface HeroProps {
|
||||
isAuthenticated?: boolean
|
||||
}
|
||||
|
||||
// Stylized three-dots indicator representing "More"
|
||||
const MoreIcon = () => (
|
||||
<svg
|
||||
className='size-6 shrink-0 text-muted-foreground/60 transition-colors group-hover:text-foreground'
|
||||
viewBox='0 0 24 24'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<circle cx='6' cy='12' r='2' fill='currentColor' />
|
||||
<circle cx='12' cy='12' r='2' fill='currentColor' />
|
||||
<circle cx='18' cy='12' r='2' fill='currentColor' />
|
||||
</svg>
|
||||
)
|
||||
|
||||
export function Hero(props: HeroProps) {
|
||||
const { t } = useTranslation()
|
||||
const { status } = useStatus()
|
||||
const docsUrl = (status?.docs_link as string | undefined) || 'https://docs.newapi.pro'
|
||||
|
||||
const renderDocsButton = () => {
|
||||
const isExternal = docsUrl.startsWith('http')
|
||||
if (isExternal) {
|
||||
return (
|
||||
<Button
|
||||
variant='outline'
|
||||
className='group border-border/50 hover:border-border hover:bg-muted/50 rounded-lg h-11 px-5 text-sm font-medium inline-flex items-center gap-1.5'
|
||||
render={
|
||||
<a
|
||||
href={docsUrl}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
/>
|
||||
}
|
||||
>
|
||||
<BookOpen className='size-4 text-muted-foreground/80 group-hover:text-foreground transition-colors duration-200' />
|
||||
<span>{t('Docs')}</span>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
variant='outline'
|
||||
className='group border-border/50 hover:border-border hover:bg-muted/50 rounded-lg h-11 px-5 text-sm font-medium inline-flex items-center gap-1.5'
|
||||
render={<Link to={docsUrl} />}
|
||||
>
|
||||
<BookOpen className='size-4 text-muted-foreground/80 group-hover:text-foreground transition-colors duration-200' />
|
||||
<span>{t('Docs')}</span>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<section className='relative z-10 flex flex-col items-center overflow-hidden px-6 pt-28 pb-16 md:pt-36 md:pb-24'>
|
||||
<section className='relative z-10 overflow-hidden px-6 pt-24 pb-16 md:pt-32 md:pb-24 lg:pt-36 lg:pb-28'>
|
||||
{/* Radial gradient background */}
|
||||
<div
|
||||
aria-hidden
|
||||
@@ -50,63 +100,146 @@ export function Hero(props: HeroProps) {
|
||||
className='absolute inset-0 -z-10 bg-[linear-gradient(to_right,var(--border)_1px,transparent_1px),linear-gradient(to_bottom,var(--border)_1px,transparent_1px)] [mask-image:radial-gradient(ellipse_60%_50%_at_50%_30%,black_20%,transparent_100%)] bg-[size:4rem_4rem] opacity-[0.08]'
|
||||
/>
|
||||
|
||||
<div className='flex max-w-3xl flex-col items-center text-center'>
|
||||
<h1
|
||||
className='landing-animate-fade-up text-[clamp(2rem,5.5vw,3.5rem)] leading-[1.15] font-bold tracking-tight'
|
||||
style={{ animationDelay: '0ms' }}
|
||||
>
|
||||
{t('Unified API Gateway for')}
|
||||
<br />
|
||||
<span className='bg-gradient-to-r from-blue-400 via-violet-400 to-purple-500 bg-clip-text text-transparent'>
|
||||
{t('All Your AI Models')}
|
||||
</span>
|
||||
</h1>
|
||||
<p
|
||||
className='landing-animate-fade-up text-muted-foreground/80 mt-5 max-w-lg text-base leading-relaxed opacity-0 md:text-lg'
|
||||
style={{ animationDelay: '80ms' }}
|
||||
>
|
||||
{t(
|
||||
'Power AI applications, manage digital assets, connect the Future'
|
||||
)}
|
||||
</p>
|
||||
<div
|
||||
className='landing-animate-fade-up mt-8 flex items-center gap-3 opacity-0'
|
||||
style={{ animationDelay: '160ms' }}
|
||||
>
|
||||
{props.isAuthenticated ? (
|
||||
<Button
|
||||
className='group rounded-lg'
|
||||
render={<Link to='/dashboard' />}
|
||||
>
|
||||
{t('Go to Dashboard')}
|
||||
<ArrowRight className='ml-1 size-3.5 transition-transform duration-200 group-hover:translate-x-0.5' />
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
className='group rounded-lg'
|
||||
render={<Link to='/sign-up' />}
|
||||
>
|
||||
{t('Get Started')}
|
||||
<ArrowRight className='ml-1 size-3.5 transition-transform duration-200 group-hover:translate-x-0.5' />
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='border-border/50 hover:border-border hover:bg-muted/50 rounded-lg'
|
||||
render={<Link to='/pricing' />}
|
||||
>
|
||||
{t('View Pricing')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className='mx-auto grid max-w-6xl grid-cols-1 items-start gap-12 lg:grid-cols-12 lg:gap-8'>
|
||||
{/* Left Column: Title, description, action buttons and application support */}
|
||||
<div className='flex flex-col items-start text-left lg:col-span-6'>
|
||||
{/* Top Pill Badge */}
|
||||
<div
|
||||
className='landing-animate-fade-up mb-5 inline-flex items-center gap-1.5 rounded-full border border-blue-500/20 bg-blue-500/5 px-3 py-1.5 text-[11px] font-medium text-blue-600 dark:border-blue-400/20 dark:bg-blue-400/5 dark:text-blue-400 opacity-0 shadow-xs'
|
||||
style={{ animationDelay: '0ms' }}
|
||||
>
|
||||
<span className='relative flex size-1.5'>
|
||||
<span className='absolute inline-flex h-full w-full animate-ping rounded-full bg-blue-400 opacity-75' />
|
||||
<span className='relative inline-flex size-1.5 rounded-full bg-blue-500 dark:bg-blue-400' />
|
||||
</span>
|
||||
<span>{t('AI Application Infrastructure Foundation')}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className='landing-animate-fade-up w-full opacity-0'
|
||||
style={{ animationDelay: '300ms' }}
|
||||
>
|
||||
<HeroTerminalDemo />
|
||||
<h1
|
||||
className='landing-animate-fade-up text-[clamp(2.25rem,4.5vw,3.25rem)] leading-[1.15] font-bold tracking-tight'
|
||||
style={{ animationDelay: '60ms' }}
|
||||
>
|
||||
{t('Unified API Gateway for')}
|
||||
<br />
|
||||
<span className='bg-gradient-to-r from-blue-400 via-violet-400 to-purple-500 bg-clip-text text-transparent'>
|
||||
{t('Vast Range of AI Models')}
|
||||
</span>
|
||||
</h1>
|
||||
<p
|
||||
className='landing-animate-fade-up text-muted-foreground/80 mt-5 max-w-xl text-base leading-relaxed opacity-0 md:text-[15px]'
|
||||
style={{ animationDelay: '120ms' }}
|
||||
>
|
||||
{t(
|
||||
'Access a vast selection of models via a standard, unified API protocol. Power AI applications, manage digital assets, and connect the Future.'
|
||||
)}
|
||||
</p>
|
||||
|
||||
<div
|
||||
className='landing-animate-fade-up mt-8 flex flex-wrap items-center gap-3 opacity-0'
|
||||
style={{ animationDelay: '180ms' }}
|
||||
>
|
||||
{props.isAuthenticated ? (
|
||||
<>
|
||||
<Button
|
||||
className='group rounded-lg h-11 px-5 text-sm font-medium'
|
||||
render={<Link to='/dashboard' />}
|
||||
>
|
||||
{t('Go to Dashboard')}
|
||||
<ArrowRight className='ml-1.5 size-4 transition-transform duration-200 group-hover:translate-x-0.5' />
|
||||
</Button>
|
||||
{renderDocsButton()}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
className='group rounded-lg h-11 px-5 text-sm font-medium'
|
||||
render={<Link to='/sign-up' />}
|
||||
>
|
||||
{t('Get Started')}
|
||||
<ArrowRight className='ml-1.5 size-4 transition-transform duration-200 group-hover:translate-x-0.5' />
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='border-border/50 hover:border-border hover:bg-muted/50 rounded-lg h-11 px-5 text-sm font-medium'
|
||||
render={<Link to='/pricing' />}
|
||||
>
|
||||
{t('View Pricing')}
|
||||
</Button>
|
||||
{renderDocsButton()}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Supported Apps (参考图二样式,进行卡片化和信息扩充设计,增加视觉高度) */}
|
||||
<div
|
||||
className='landing-animate-fade-up mt-10 w-full max-w-xl opacity-0'
|
||||
style={{ animationDelay: '240ms' }}
|
||||
>
|
||||
<div className='flex flex-col gap-1 mb-4'>
|
||||
<span className='text-[10px] font-bold tracking-[0.15em] text-muted-foreground/50 uppercase'>
|
||||
{t('Supported Applications')}
|
||||
</span>
|
||||
<p className='text-xs text-muted-foreground/60 leading-relaxed'>
|
||||
{t('Supports one-click configuration and perfectly adapts to NewAPI multi-protocol configuration.')}
|
||||
</p>
|
||||
</div>
|
||||
<div className='flex flex-wrap items-center gap-3'>
|
||||
{/* Cherry Studio */}
|
||||
<a
|
||||
href='https://cherry-ai.com'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='group flex items-center gap-3 rounded-full border border-border/40 bg-muted/15 px-5 py-2.5 text-sm font-medium text-foreground/80 shadow-[0_1px_2.5px_rgba(0,0,0,0.01)] backdrop-blur-xs transition-all duration-300 hover:border-border hover:bg-muted/30 hover:text-foreground hover:scale-[1.02]'
|
||||
>
|
||||
<CherryStudio.Color size={24} className='shrink-0' />
|
||||
<span>Cherry Studio</span>
|
||||
</a>
|
||||
|
||||
{/* CC Switch */}
|
||||
<a
|
||||
href='https://ccswitch.io'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='group flex items-center gap-3 rounded-full border border-border/40 bg-muted/15 px-5 py-2.5 text-sm font-medium text-foreground/80 shadow-[0_1px_2.5px_rgba(0,0,0,0.01)] backdrop-blur-xs transition-all duration-300 hover:border-border hover:bg-muted/30 hover:text-foreground hover:scale-[1.02]'
|
||||
>
|
||||
<img
|
||||
src='https://ccswitch.io/favicon.png'
|
||||
alt='CC Switch'
|
||||
className='size-6 shrink-0 rounded-md object-contain'
|
||||
onError={(e) => {
|
||||
// Fallback to a styled text avatar if the remote favicon fails to load in sandbox or local environments
|
||||
e.currentTarget.style.display = 'none'
|
||||
const fallback = e.currentTarget.nextSibling as HTMLElement
|
||||
if (fallback) fallback.style.display = 'flex'
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
style={{ display: 'none' }}
|
||||
className='size-6 shrink-0 items-center justify-center rounded-md bg-blue-500/10 text-[10px] font-bold text-blue-600 dark:bg-blue-400/10 dark:text-blue-400'
|
||||
>
|
||||
CC
|
||||
</span>
|
||||
<span>CC Switch</span>
|
||||
</a>
|
||||
|
||||
{/* "更多" */}
|
||||
<div
|
||||
className='group flex items-center gap-2.5 rounded-full border border-border/40 bg-muted/15 px-5 py-2.5 text-sm font-medium text-foreground/55 shadow-[0_1px_2.5px_rgba(0,0,0,0.01)] backdrop-blur-xs transition-all duration-300 hover:border-border hover:bg-muted/30 hover:text-foreground hover:scale-[1.02] cursor-default'
|
||||
>
|
||||
<MoreIcon />
|
||||
<span>{t('More Apps')}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Hero Terminal API Demo */}
|
||||
<div
|
||||
className='landing-animate-fade-up flex justify-center w-full opacity-0 lg:col-span-6'
|
||||
style={{ animationDelay: '320ms' }}
|
||||
>
|
||||
<HeroTerminalDemo className='mt-8 lg:mt-0' />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user