Update components/tailwind-cdn-client.tsx
This commit is contained in:
parent
3799e5cfed
commit
efdedb0697
|
|
@ -0,0 +1,150 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CRITICAL COMPONENT: Loads Tailwind v4 CDN on client-side only
|
||||||
|
* ⚠️ DO NOT REMOVE OR MODIFY WITHOUT CAREFUL TESTING ⚠️
|
||||||
|
*
|
||||||
|
* This component prevents hydration mismatches by loading Tailwind CDN
|
||||||
|
* only after React hydration is complete. It's essential for CodeSandbox
|
||||||
|
* environments where we use Tailwind v4 CDN instead of compiled CSS.
|
||||||
|
*
|
||||||
|
* Without this component, you'll get hydration errors because server
|
||||||
|
* and client would render different HTML/styles.
|
||||||
|
*
|
||||||
|
* NEVER load CDN styles in layout.tsx with conditional logic based on
|
||||||
|
* process.env as this causes hydration mismatches.
|
||||||
|
*/
|
||||||
|
export function TailwindCDNClient() {
|
||||||
|
useEffect(() => {
|
||||||
|
// Show content immediately on Vercel (CSS is already compiled)
|
||||||
|
if (process.env.NEXT_PUBLIC_VERCEL) {
|
||||||
|
document.body.classList.add('css-loaded');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only load CDN if not on Vercel
|
||||||
|
if (!process.env.NEXT_PUBLIC_VERCEL) {
|
||||||
|
// Check if already loaded
|
||||||
|
const existingScript = document.querySelector('script[src*="@tailwindcss/browser"]');
|
||||||
|
const existingStyle = document.querySelector('style[type="text/tailwindcss"]');
|
||||||
|
|
||||||
|
if (!existingScript && !existingStyle) {
|
||||||
|
// Add Tailwind config
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.setAttribute('type', 'text/tailwindcss');
|
||||||
|
style.textContent = `
|
||||||
|
@variant dark (&:where(.dark, .dark *));
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--radius: 0.625rem;
|
||||||
|
--color-neutral-50: rgb(250 250 250);
|
||||||
|
--color-neutral-100: rgb(245 245 245);
|
||||||
|
--color-neutral-200: rgb(229 229 229);
|
||||||
|
--color-neutral-300: rgb(212 212 212);
|
||||||
|
--color-neutral-400: rgb(163 163 163);
|
||||||
|
--color-neutral-500: rgb(115 115 115);
|
||||||
|
--color-neutral-600: rgb(82 82 82);
|
||||||
|
--color-neutral-700: rgb(64 64 64);
|
||||||
|
--color-neutral-800: rgb(38 38 38);
|
||||||
|
--color-neutral-900: rgb(23 23 23);
|
||||||
|
--color-primary: #020022;
|
||||||
|
--color-muted: rgb(82 82 82);
|
||||||
|
--color-muted-dark: rgb(212 212 212);
|
||||||
|
--animate-scroll: scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite;
|
||||||
|
--animate-marquee: marquee var(--marquee-duration) linear infinite;
|
||||||
|
--animate-fade-in: fade-in 0.5s linear forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scroll {
|
||||||
|
to { transform: translate(calc(-50% - 0.5rem)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes marquee {
|
||||||
|
100% { transform: translateY(-50%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-derek {
|
||||||
|
box-shadow: 0px 0px 0px 1px rgb(0 0 0 / 0.06),
|
||||||
|
0px 1px 1px -0.5px rgb(0 0 0 / 0.06),
|
||||||
|
0px 3px 3px -1.5px rgb(0 0 0 / 0.06),
|
||||||
|
0px 6px 6px -3px rgb(0 0 0 / 0.06),
|
||||||
|
0px 12px 12px -6px rgb(0 0 0 / 0.06),
|
||||||
|
0px 24px 24px -12px rgb(0 0 0 / 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-aceternity {
|
||||||
|
box-shadow: 0px 2px 3px -1px rgba(0,0,0,0.1),
|
||||||
|
0px 1px 0px 0px rgba(25,28,33,0.02),
|
||||||
|
0px 0px 0px 1px rgba(25,28,33,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gradient-radial {
|
||||||
|
background-image: radial-gradient(var(--tw-gradient-stops));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gradient-conic {
|
||||||
|
background-image: conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops));
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
// Add Tailwind script
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = 'https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4';
|
||||||
|
script.onload = () => {
|
||||||
|
// Show content when CDN is loaded and processed
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.classList.add('css-loaded');
|
||||||
|
}, 50); // Small delay for CDN to process styles
|
||||||
|
};
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
// Add dark mode styles
|
||||||
|
const darkModeStyle = document.createElement('style');
|
||||||
|
darkModeStyle.textContent = `
|
||||||
|
/* Manual dark:bg-neutral-* classes for Tailwind v4 CDN */
|
||||||
|
.dark .dark\\:bg-neutral-50 { background-color: rgb(250 250 250); }
|
||||||
|
.dark .dark\\:bg-neutral-100 { background-color: rgb(245 245 245); }
|
||||||
|
.dark .dark\\:bg-neutral-200 { background-color: rgb(229 229 229); }
|
||||||
|
.dark .dark\\:bg-neutral-300 { background-color: rgb(212 212 212); }
|
||||||
|
.dark .dark\\:bg-neutral-400 { background-color: rgb(163 163 163); }
|
||||||
|
.dark .dark\\:bg-neutral-500 { background-color: rgb(115 115 115); }
|
||||||
|
.dark .dark\\:bg-neutral-600 { background-color: rgb(82 82 82); }
|
||||||
|
.dark .dark\\:bg-neutral-700 { background-color: rgb(64 64 64); }
|
||||||
|
.dark .dark\\:bg-neutral-800 { background-color: rgb(38 38 38); }
|
||||||
|
.dark .dark\\:bg-neutral-900 { background-color: rgb(23 23 23); }
|
||||||
|
|
||||||
|
.dark .dark\\:text-neutral-50 { color: rgb(250 250 250); }
|
||||||
|
.dark .dark\\:text-neutral-100 { color: rgb(245 245 245); }
|
||||||
|
.dark .dark\\:text-neutral-200 { color: rgb(229 229 229); }
|
||||||
|
.dark .dark\\:text-neutral-300 { color: rgb(212 212 212); }
|
||||||
|
.dark .dark\\:text-neutral-400 { color: rgb(163 163 163); }
|
||||||
|
.dark .dark\\:text-neutral-500 { color: rgb(115 115 115); }
|
||||||
|
.dark .dark\\:text-neutral-600 { color: rgb(82 82 82); }
|
||||||
|
.dark .dark\\:text-neutral-700 { color: rgb(64 64 64); }
|
||||||
|
.dark .dark\\:text-neutral-800 { color: rgb(38 38 38); }
|
||||||
|
.dark .dark\\:text-neutral-900 { color: rgb(23 23 23); }
|
||||||
|
|
||||||
|
.dark .dark\\:border-neutral-600 { border-color: rgb(82 82 82); }
|
||||||
|
.dark .dark\\:border-neutral-700 { border-color: rgb(64 64 64); }
|
||||||
|
.dark .dark\\:border-neutral-800 { border-color: rgb(38 38 38); }
|
||||||
|
|
||||||
|
.dark .dark\\:hover\\:bg-neutral-800:hover { background-color: rgb(38 38 38); }
|
||||||
|
.dark .dark\\:hover\\:bg-neutral-700:hover { background-color: rgb(64 64 64); }
|
||||||
|
|
||||||
|
.dark .dark\\:text-muted-dark { color: rgb(212 212 212); }
|
||||||
|
`;
|
||||||
|
document.head.appendChild(darkModeStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue