forked from 77media/video-flow
更新 banner自动收起
This commit is contained in:
parent
95ec751dcf
commit
170c061063
@ -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"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user