Update src/providers/themeProvider/ThemeProvider.tsx

This commit is contained in:
2026-02-27 13:10:51 +00:00
parent 88480cd881
commit 5742310b25

View File

@@ -1,25 +1,107 @@
"use client";
'use client';
import { createContext, useContext } from "react";
import type { ThemeConfig, ThemeProviderProps } from "./config/types";
import { borderRadiusMap, borderRadiusCappedMap, contentWidthMap, expandedContentWidthMap, baseVwMap, textSizingMap, backgroundComponents, headingFontWeightMap } from "./config/constants";
import { cardStyleMap, getGradientBorderedPseudo } from "./styles/cardStyles";
import { primaryButtonStyleMap } from "./styles/primaryButtonStyles";
import { secondaryButtonStyleMap } from "./styles/secondaryButtonStyles";
import React, { useState } from 'react';
const ThemeContext = createContext<ThemeConfig | undefined>(undefined);
interface SocialLink {
platform: string;
url: string;
icon: string;
}
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error(
"useTheme must be used within a ThemeProvider. Wrap your sections in <ThemeProvider> at the app/page level."
);
}
return context;
};
interface TeamMember {
id: string;
name: string;
role: string;
image: string;
socialLinks: SocialLink[];
}
export const ThemeProvider = ({
interface TeamCardProps {
member: TeamMember;
}
function TeamCard({ member }: TeamCardProps) {
const [isFlipped, setIsFlipped] = useState(false);
return (
<div
className="h-80 w-full cursor-pointer perspective"
onMouseEnter={() => setIsFlipped(true)}
onMouseLeave={() => setIsFlipped(false)}
>
<div
className="relative w-full h-full transition-transform duration-500 transform-gpu"
style={{
transformStyle: 'preserve-3d',
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
}}
>
{/* Front Side */}
<div
className="absolute w-full h-full bg-gradient-to-br from-slate-900 to-slate-800 rounded-lg p-6 flex flex-col items-center justify-center border border-slate-700"
style={{ backfaceVisibility: 'hidden' }}
>
<div className="w-24 h-24 rounded-full bg-slate-700 mb-4 overflow-hidden flex items-center justify-center">
<img
src={member.image}
alt={member.name}
className="w-full h-full object-cover"
/>
</div>
<h3 className="text-xl font-semibold text-white text-center">
{member.name}
</h3>
<p className="text-sm text-slate-400 text-center mt-2">
{member.role}
</p>
</div>
{/* Back Side */}
<div
className="absolute w-full h-full bg-gradient-to-br from-blue-900 to-blue-800 rounded-lg p-6 flex flex-col items-center justify-center border border-blue-700"
style={{
backfaceVisibility: 'hidden',
transform: 'rotateY(180deg)',
}}
>
<h4 className="text-white font-semibold mb-4 text-center">
Connect
</h4>
<div className="flex flex-wrap gap-3 justify-center">
{member.socialLinks.map((link) => (
<a
key={link.platform}
href={link.url}
target="_blank"
rel="noopener noreferrer"
className="w-10 h-10 rounded-full bg-white bg-opacity-20 hover:bg-opacity-30 flex items-center justify-center transition-all duration-300 text-white text-sm font-bold"
title={link.platform}
>
{link.icon}
</a>
))}
</div>
</div>
</div>
</div>
);
}
interface ThemeProviderProps {
children: React.ReactNode;
defaultButtonVariant?: string;
defaultTextAnimation?: string;
borderRadius?: string;
contentWidth?: string;
sizing?: string;
background?: string;
cardStyle?: string;
primaryButtonStyle?: string;
secondaryButtonStyle?: string;
headingFontWeight?: string;
}
export function ThemeProvider({
children,
defaultButtonVariant,
defaultTextAnimation,
@@ -31,96 +113,54 @@ export const ThemeProvider = ({
primaryButtonStyle,
secondaryButtonStyle,
headingFontWeight,
}: ThemeProviderProps) => {
const themeConfig: ThemeConfig = {
defaultButtonVariant,
defaultTextAnimation,
borderRadius,
contentWidth,
sizing,
background,
cardStyle,
primaryButtonStyle,
secondaryButtonStyle,
headingFontWeight,
}: ThemeProviderProps) {
const backgroundClasses = {
aurora: 'bg-gradient-to-br from-slate-950 via-purple-900 to-slate-950',
light: 'bg-white',
dark: 'bg-slate-900',
};
const borderRadiusValue = borderRadiusMap[borderRadius];
const borderRadiusCappedValue = borderRadiusCappedMap[borderRadius];
const contentWidthValues = contentWidthMap[contentWidth];
const expandedContentWidthValues = expandedContentWidthMap[contentWidth];
const baseVwValues = baseVwMap[sizing];
const textSizingValues = textSizingMap[sizing];
const BackgroundComponent = backgroundComponents[background];
const headingFontWeightValue = headingFontWeightMap[headingFontWeight];
const borderRadiusClasses = {
soft: 'rounded-lg',
sharp: 'rounded-none',
smooth: 'rounded-2xl',
};
const cardStyles = cardStyleMap[cardStyle];
const primaryButtonStyles = primaryButtonStyleMap[primaryButtonStyle];
const secondaryButtonStyles = secondaryButtonStyleMap[secondaryButtonStyle];
const contentWidthClasses = {
small: 'max-w-2xl',
medium: 'max-w-6xl',
large: 'max-w-7xl',
};
const gradientBorderedPseudo = getGradientBorderedPseudo(cardStyle);
const styleString = `
:root {
--theme-border-radius: ${borderRadiusValue};
--theme-border-radius-capped: ${borderRadiusCappedValue};
--width-content-width: ${contentWidthValues.desktop};
--width-content-width-expanded: ${expandedContentWidthValues.desktop};
--vw: ${baseVwValues.desktop};
--heading-font-weight: ${headingFontWeightValue};
--text-2xs: ${textSizingValues.desktop.text2xs};
--text-xs: ${textSizingValues.desktop.textXs};
--text-sm: ${textSizingValues.desktop.textSm};
--text-base: ${textSizingValues.desktop.textBase};
--text-lg: ${textSizingValues.desktop.textLg};
--text-xl: ${textSizingValues.desktop.textXl};
--text-2xl: ${textSizingValues.desktop.text2xl};
--text-3xl: ${textSizingValues.desktop.text3xl};
--text-4xl: ${textSizingValues.desktop.text4xl};
--text-5xl: ${textSizingValues.desktop.text5xl};
--text-6xl: ${textSizingValues.desktop.text6xl};
--text-7xl: ${textSizingValues.desktop.text7xl};
--text-8xl: ${textSizingValues.desktop.text8xl};
--text-9xl: ${textSizingValues.desktop.text9xl};
}
@media (max-width: 768px) {
:root {
--width-content-width: ${contentWidthValues.mobile};
--width-content-width-expanded: ${expandedContentWidthValues.mobile};
--vw: ${baseVwValues.mobile};
--text-2xs: ${textSizingValues.mobile.text2xs};
--text-xs: ${textSizingValues.mobile.textXs};
--text-sm: ${textSizingValues.mobile.textSm};
--text-base: ${textSizingValues.mobile.textBase};
--text-lg: ${textSizingValues.mobile.textLg};
--text-xl: ${textSizingValues.mobile.textXl};
--text-2xl: ${textSizingValues.mobile.text2xl};
--text-3xl: ${textSizingValues.mobile.text3xl};
--text-4xl: ${textSizingValues.mobile.text4xl};
--text-5xl: ${textSizingValues.mobile.text5xl};
--text-6xl: ${textSizingValues.mobile.text6xl};
--text-7xl: ${textSizingValues.mobile.text7xl};
--text-8xl: ${textSizingValues.mobile.text8xl};
--text-9xl: ${textSizingValues.mobile.text9xl};
}
}
.card {
${cardStyles}
}
${gradientBorderedPseudo}
.primary-button {
${primaryButtonStyles}
}
.secondary-button {
${secondaryButtonStyles}
}
`;
const bgClass = backgroundClasses[background as keyof typeof backgroundClasses] || backgroundClasses.aurora;
const radiusClass = borderRadiusClasses[borderRadius as keyof typeof borderRadiusClasses] || borderRadiusClasses.soft;
const widthClass = contentWidthClasses[contentWidth as keyof typeof contentWidthClasses] || contentWidthClasses.medium;
return (
<ThemeContext.Provider value={themeConfig}>
<style>{styleString}</style>
{BackgroundComponent && <BackgroundComponent />}
{children}
</ThemeContext.Provider>
<div
className={`${bgClass} min-h-screen transition-colors duration-300`}
style={{
'--default-button-variant': defaultButtonVariant,
'--default-text-animation': defaultTextAnimation,
'--card-style': cardStyle,
'--primary-button-style': primaryButtonStyle,
'--secondary-button-style': secondaryButtonStyle,
'--heading-font-weight': headingFontWeight,
} as React.CSSProperties}
>
<div className={`${widthClass} mx-auto px-4 sm:px-6 lg:px-8`}>
{children}
</div>
</div>
);
};
}
export function TeamCardGrid({ members }: { members: TeamMember[] }) {
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 py-12">
{members.map((member) => (
<TeamCard key={member.id} member={member} />
))}
</div>
);
}