This commit is contained in:
Your Name committed 2026-10-04 19:56:23 +07:00
1 parent e349ef5b84
commit 8d415ecef7
14 files changed
+372 -119

No files matched your search

+30 -10
View File
@@ -139,12 +139,25 @@ export function getHeroPositionClasses(mobilePos: string, desktopPos: string) {
};
}
export function getHeroContainerWidthClasses(contentWidth?: string) {
switch (contentWidth) {
case 'full':
return 'w-full max-w-none px-6 md:px-12 lg:px-16';
case 'compact':
return 'w-full max-w-4xl mx-auto px-6';
case 'standard':
default:
return 'w-full max-w-7xl mx-auto px-6 md:px-10 lg:px-12';
}
}
export default function DynamicHero({ payload }: DynamicHeroProps) {
const { t, i18n } = useTranslation();
const lang = i18n.language;
const { imageUrl, buttonLink } = payload;
const desktopPosition = (payload as any).buttonPosition || 'center';
const mobilePosition = (payload as any).mobileButtonPosition || desktopPosition;
const contentWidth = (payload as any).contentWidth || 'standard';
const focalPoint = typeof payload.focalPoint === 'object' && payload.focalPoint ? (payload.focalPoint as { x: string, y: string }) : undefined;
// Localized values
@@ -167,6 +180,9 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
? rawButtonText.trim()
: t('hero.exploreCollection');
const textColorScheme = (payload as any).textColorScheme || 'light';
const isDarkText = textColorScheme === 'dark';
const renderTitle = (text: string) => {
if (!text) return null;
return text.split('[').map((part, i) => {
@@ -174,7 +190,7 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
const [accent, rest] = part.split(']');
return (
<span key={i}>
<span className="text-pop-yellow font-medium italic">
<span className={`${isDarkText ? 'text-pop-pink' : 'text-pop-yellow'} font-medium italic`}>
{accent}
</span>
{rest}
@@ -201,7 +217,7 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
return (
<div
className="absolute inset-0 transition-opacity duration-300"
style={{ backgroundColor: `rgba(0, 0, 0, ${opacityRatio})` }}
style={{ backgroundColor: isDarkText ? `rgba(255, 255, 255, ${opacityRatio})` : `rgba(0, 0, 0, ${opacityRatio})` }}
/>
);
}
@@ -211,18 +227,22 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
const midAlpha = opacityRatio;
const topAlpha = Math.max(0, opacityRatio * 0.65);
const rgb = isDarkText ? '255, 255, 255' : '0, 0, 0';
return (
<div
className="absolute inset-0 transition-opacity duration-300"
style={{
background: `linear-gradient(to top, rgba(0, 0, 0, ${bottomAlpha}) 0%, rgba(0, 0, 0, ${midAlpha}) 50%, rgba(0, 0, 0, ${topAlpha}) 100%)`,
background: `linear-gradient(to top, rgba(${rgb}, ${bottomAlpha}) 0%, rgba(${rgb}, ${midAlpha}) 50%, rgba(${rgb}, ${topAlpha}) 100%)`,
}}
/>
);
};
const containerClasses = getHeroContainerWidthClasses(contentWidth);
return (
<section className="relative w-full min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9] flex bg-night-950 overflow-hidden">
<section className={`relative w-full min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9] flex overflow-hidden ${isDarkText ? 'bg-surface-page' : 'bg-night-950'}`}>
<div className="absolute inset-0 w-full h-full z-0">
<img
src={imageUrl || `${import.meta.env.VITE_API_URL.replace('/api', '')}/assets/hero.png`}
@@ -233,24 +253,24 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
(e.target as HTMLImageElement).style.display = 'none';
}}
/>
{/* Dynamic Dark Gradient / Solid Overlay */}
{/* Dynamic Dark / Light Gradient / Solid Overlay */}
{renderOverlay()}
</div>
<div className={`relative z-10 w-full min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${wrapperClasses} animate-fade-in`}>
<div className={`relative z-10 min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${containerClasses} ${wrapperClasses} animate-fade-in`}>
<div className={`w-full max-w-3xl flex flex-col space-y-5 ${contentClasses}`}>
{tagline && (
<p className="text-pop-yellow font-semibold tracking-[0.3em] text-xs md:text-sm uppercase drop-shadow-md">
<p className={`${isDarkText ? 'text-pop-pink' : 'text-pop-yellow'} font-semibold tracking-[0.3em] text-xs md:text-sm uppercase drop-shadow-md`}>
{tagline}
</p>
)}
{title && (
<h1 className="ui-hero-title !text-white drop-shadow-lg">
<h1 className={`ui-hero-title ${isDarkText ? '!text-pop-black' : '!text-white'} drop-shadow-lg`}>
{renderTitle(title)}
</h1>
)}
{description && (
<p className={`ui-hero-copy !text-white/90 drop-shadow-md !pb-2 ${contentClasses.includes('text-left') ? '!mx-0' : contentClasses.includes('text-right') ? '!ml-auto !mr-0' : '!mx-auto'}`}>
<p className={`ui-hero-copy ${isDarkText ? '!text-pop-black/85' : '!text-white/90'} drop-shadow-md !pb-2 ${contentClasses.includes('text-left') ? '!mx-0' : contentClasses.includes('text-right') ? '!ml-auto !mr-0' : '!mx-auto'}`}>
{description}
</p>
)}
@@ -265,7 +285,7 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
)}
<a
href="#categories"
className="ui-dark-link group flex items-center gap-1.5 drop-shadow-md hover:underline"
className={`group flex items-center gap-1.5 drop-shadow-md hover:underline ${isDarkText ? 'text-pop-black hover:text-pop-pink' : 'ui-dark-link'}`}
>
<span>{t('hero.learnMore')}</span>
<span className="group-hover:translate-x-1 transition-transform">&rarr;</span>