更新 banner自动收起

This commit is contained in:
moux1024 2025-10-18 14:27:16 +08:00
parent 95ec751dcf
commit 170c061063
2 changed files with 110 additions and 53 deletions

View File

@ -39,7 +39,7 @@ const FamousTemplate: React.FC = () => {
<section data-alt="famous-template" className="w-full"> <section data-alt="famous-template" className="w-full">
<div data-alt="famous-template-header" className="mb-4 flex items-center"> <div data-alt="famous-template-header" className="mb-4 flex items-center">
<h2 data-alt="famous-template-title" className="text-xl py-4 font-semibold text-white"> <h2 data-alt="famous-template-title" className="text-xl py-4 font-semibold text-white">
Scene Sparks Hot Templates
</h2> </h2>
<div data-alt="template-tabs" className="flex items-center gap-2 ml-4"> <div data-alt="template-tabs" className="flex items-center gap-2 ml-4">
{(["all", "music", "animation", "thriller"] as const).map((tab) => ( {(["all", "music", "animation", "thriller"] as const).map((tab) => (
@ -50,7 +50,7 @@ const FamousTemplate: React.FC = () => {
onClick={() => setActiveTab(tab)} onClick={() => setActiveTab(tab)}
className={`px-3 py-1 italic rounded-none text-sm transition-colors border ${ className={`px-3 py-1 italic rounded-none text-sm transition-colors border ${
activeTab === tab activeTab === tab
? "border-white/60 bg-white/80 text-slate-900" ? "border-white/60 bg-white/60 text-slate-900"
: "border-white/20 text-white/80 hover:border-white/40 hover:bg-white/10" : "border-white/20 text-white/80 hover:border-white/40 hover:bg-white/10"
}`} }`}
> >

View File

@ -1,7 +1,9 @@
"use client"; "use client";
import { useEffect, useState } from "react"; import { useEffect, useState, useRef } from "react";
import { fetchSettingByCode } from "@/api/serversetting"; import { fetchSettingByCode } from "@/api/serversetting";
import { X, Eclipse } from "lucide-react";
import { ChatInputBox } from "@/components/ChatInputBox/ChatInputBox";
export const HOME_BANNER_CODE = "homeBanner"; export const HOME_BANNER_CODE = "homeBanner";
@ -34,6 +36,32 @@ export default function HomeBanner() {
const [config, setConfig] = useState<HomeBannerConfig | null>(null); const [config, setConfig] = useState<HomeBannerConfig | null>(null);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [isFlying, setIsFlying] = useState<boolean>(false);
const autoCollapseTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const handleDismiss = () => {
setIsFlying(true);
};
const handleBannerClick = () => {
if (isFlying) {
setIsFlying(false);
}
};
// Auto collapse after mount (3s)
useEffect(() => {
if (autoCollapseTimerRef.current) return;
autoCollapseTimerRef.current = setTimeout(() => {
setIsFlying(true);
}, 3000);
return () => {
if (autoCollapseTimerRef.current) {
clearTimeout(autoCollapseTimerRef.current);
autoCollapseTimerRef.current = null;
}
};
}, []);
useEffect(() => { useEffect(() => {
let active = true; let active = true;
@ -98,62 +126,91 @@ export default function HomeBanner() {
} }
return ( return (
<section <div data-alt="home-banner-wrapper" className="relative w-full mx-auto p-0 overflow-hidden">
data-alt="home-banner" {/* Banner overlay - stacked above */}
className="relative isolate overflow-hidden rounded-3xl px-6 py-16 text-white border-2 border-transparent hover:border-custom-blue/50 transition-all duration-300" <section
aria-label="Home banner" data-alt="home-banner"
> className={`absolute inset-0 z-10 isolate overflow-hidden rounded-3xl px-6 py-6 text-white border-2 border-transparent hover:border-custom-blue/50 transition-all duration-500 ease-in-out ${
{backgroundImage ? ( isFlying
<img ? "cursor-pointer translate-x-[90%] -translate-y-[70%] scale-[0.85] opacity-95 rotate-3"
data-alt="background-image" : "translate-x-0 translate-y-0 scale-100 opacity-100 rotate-0"
src={backgroundImage} }`}
className="absolute inset-0 h-full w-full object-cover" aria-label="Home banner"
/>
) : null}
{backgroundImage ? (
<div data-alt="background-overlay" className="absolute inset-0 bg-black/40" />
) : null}
<div
data-alt="banner-content"
className="relative flex max-w-4xl flex-col items-center gap-4 text-center md:items-start md:text-left"
> >
{eyebrow ? ( {backgroundImage ? (
<span data-alt="banner-eyebrow" className="text-xs font-semibold uppercase tracking-[0.3em] text-white/70"> <img
{eyebrow} data-alt="background-image"
</span> src={backgroundImage}
className="absolute inset-0 h-full w-full object-cover"
/>
) : null} ) : null}
{title ? ( {backgroundImage ? (
<h1 data-alt="banner-title" className="text-3xl font-semibold leading-tight md:text-5xl"> <div data-alt="background-overlay" className="absolute inset-0 bg-black/40" />
{title}
</h1>
) : null} ) : null}
{subtitle ? (
<p data-alt="banner-subtitle" className="text-lg text-white/80 md:text-xl">{subtitle}</p> <div
) : null} data-alt="banner-content"
{description ? ( className="relative flex flex-col items-center gap-4 text-center md:items-start md:text-left"
<p data-alt="banner-description" className="max-w-2xl text-base text-white/70">{description}</p> >
) : null} {/* Dismiss button */}
{ctaLabel ? ( <div className="absolute right-0 top-0">
ctaHref ? (
<a
data-alt="cta-link"
href={ctaHref}
className="inline-flex items-center justify-center rounded-full border border-white/30 bg-white/10 px-6 py-2 text-sm font-medium text-white transition hover:border-white hover:bg-white hover:text-slate-900"
>
{ctaLabel}
</a>
) : (
<button <button
data-alt="cta-button" data-alt="banner-dismiss"
type="button" type="button"
className="inline-flex items-center justify-center rounded-full border border-white/30 bg-white/10 px-6 py-2 text-sm font-medium text-white transition hover:border-white hover:bg-white hover:text-slate-900" onClick={handleDismiss}
className="text-white hover:bg-white/20 rounded-full p-2"
aria-label="Dismiss banner"
> >
{ctaLabel} <X className="h-5 w-5" />
</button> </button>
) </div>
) : null} {isFlying ? (
<button type="button" onClick={handleBannerClick} className="absolute left-[-15px] bottom-[-20px] h-5 w-5">
<Eclipse className="inset-0 h-5 w-5" />
</button>
) : null}
{eyebrow ? (
<span data-alt="banner-eyebrow" className="text-xs font-semibold uppercase tracking-[0.3em] text-white/70">
{eyebrow}
</span>
) : null}
{title ? (
<h1 data-alt="banner-title" className="text-3xl font-semibold leading-tight md:text-5xl">
{title}
</h1>
) : null}
{subtitle ? (
<p data-alt="banner-subtitle" className="text-lg text-white/80 md:text-xl">{subtitle}</p>
) : null}
{description ? (
<p data-alt="banner-description" className="max-w-2xl text-base text-white/70">{description}</p>
) : null}
{ctaLabel ? (
ctaHref ? (
<a
data-alt="cta-link"
href={ctaHref}
className="inline-flex items-center justify-center rounded-full border border-white/30 bg-white/10 px-6 py-2 text-sm font-medium text-white transition hover:border-white hover:bg-white hover:text-slate-900"
>
{ctaLabel}
</a>
) : (
<button
data-alt="cta-button"
type="button"
className="inline-flex items-center justify-center rounded-full border border-white/30 bg-white/10 px-6 py-2 text-sm font-medium text-white transition hover:border-white hover:bg-white hover:text-slate-900"
>
{ctaLabel}
</button>
)
) : null}
</div>
</section>
{/* Base content - always present under the banner */}
<div data-alt="home-banner-base" className="relative bg-transparent py-6 min-h-[300px]">
<ChatInputBox noData={false} />
</div> </div>
</section> </div>
); );
} }