103 lines
4.6 KiB
TypeScript
103 lines
4.6 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import styles from './index.module.css';
|
|
import TopTabs from './TopTabs';
|
|
import { useLocation } from 'react-router-dom';
|
|
import ScrollReveal from '@/components/ScrollReveal';
|
|
|
|
|
|
type Data = {
|
|
tabItems: {
|
|
icon?: string;
|
|
tabName?: string;
|
|
contentTitle?: string;
|
|
contentSubtitle?: string;
|
|
contentText?: string;
|
|
content?: string;
|
|
/** 以 mockData 为准 */
|
|
sideImage?: string;
|
|
path?: string;
|
|
items?: {label: string}[];
|
|
}[]
|
|
backgroundImage?: string;
|
|
titleDirection?: 'row' | 'column';
|
|
}
|
|
|
|
export default function TopTabsSection({ data, className }: { data: Data, className?: string }) {
|
|
const location = useLocation();
|
|
const hash = location.hash;
|
|
const hashId = decodeURIComponent(hash.replace('#', ''));
|
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (hashId && data.tabItems) {
|
|
const index = data.tabItems.findIndex((item) => item.tabName === hashId);
|
|
if (index !== -1) {
|
|
setActiveIndex(index);
|
|
}
|
|
}
|
|
}, [hashId, data.tabItems])
|
|
return (
|
|
<section className={`${styles.topTabsSection} ${className}`} style={{ backgroundImage: `url(${data.backgroundImage})` }}>
|
|
<div aria-hidden="true">
|
|
{data.tabItems.map((item) => (
|
|
<div key={item.tabName} id={item.tabName} style={{ height: 0, overflow: "hidden" }} />
|
|
))}
|
|
</div>
|
|
<TopTabs data={data} activeIndex={activeIndex} setActiveIndex={setActiveIndex} />
|
|
<div className={styles.topTabsContent}>
|
|
{
|
|
data.tabItems[activeIndex]?.items && (data.tabItems[activeIndex]?.items as any).length > 0 ?
|
|
<ul className={styles.topTabsContentItems}>
|
|
{
|
|
(data.tabItems[activeIndex]?.items as any).map((item: {label: string}) => (
|
|
<li key={item.label} className={styles.topTabsContentItem}>
|
|
<span>{item.label}</span>
|
|
</li>
|
|
))
|
|
}
|
|
</ul> : (
|
|
<>
|
|
<div className={styles.topTabsContentLeft}>
|
|
<div className={styles.topTabsContentLeftHead}>
|
|
{
|
|
<ScrollReveal preset="slideRight" delay={0.3} >
|
|
{
|
|
data.tabItems[activeIndex].icon && (
|
|
<img src={data.tabItems[activeIndex].icon} alt="" style={{ width: '6.25rem', height: '6.25rem', marginRight: '1.25rem' }} />
|
|
)
|
|
}
|
|
</ScrollReveal>
|
|
}
|
|
<div className={`${styles.topTabsContentLeftTitle} ${data.titleDirection === 'column' ? styles.columnCenter : ''}`}>
|
|
|
|
<ScrollReveal preset="slideUp" delay={0.5} duration={1.1}>
|
|
<div className={styles.topTabsContentLeftTitleMain}>{data.tabItems[activeIndex].contentTitle}</div>
|
|
</ScrollReveal>
|
|
<ScrollReveal preset="slideUp" delay={0.7} duration={1.1}>
|
|
<div className={styles.topTabsContentLeftTitleSub}>{data.tabItems[activeIndex].contentSubtitle}</div>
|
|
</ScrollReveal>
|
|
</div>
|
|
</div>
|
|
<ScrollReveal preset="slideUp" delay={0.9} duration={1.1}>
|
|
<p className={`${styles.topTabsContentLeftDesc} normal-p`}
|
|
|
|
dangerouslySetInnerHTML={{ __html: data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content as any }}
|
|
>
|
|
{/* {data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content} */}
|
|
</p>
|
|
</ScrollReveal>
|
|
</div>
|
|
<div className={styles.topTabsContentRight}>
|
|
<ScrollReveal preset="slideLeft" delay={0.5} >
|
|
<img src={data.tabItems[activeIndex].sideImage} alt="side-image" />
|
|
</ScrollReveal>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|