diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 6670bb18..df004ec1 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -23,8 +23,8 @@ const config: Config = { // Google Analytics and Theme Scripts scripts: [ { - src: '/theme-init.js', - async: false, // Load synchronously to prevent flash + src: '/instant-theme.js', + async: false, }, { src: 'https://www.googletagmanager.com/gtag/js?id=G-W02Z2VJYCR', @@ -80,11 +80,12 @@ const config: Config = { colorMode: { defaultMode: 'light', disableSwitch: false, - respectPrefersColorScheme: false, + respectPrefersColorScheme: false, // Let users manually control theme }, navbar: { - + title:"Recode Hive", logo: { + alt: "RecodeHive Logo", src: "img/logo.png", }, @@ -97,7 +98,7 @@ const config: Config = { { type: "html", value: `
- Tutorials + Tutorials
SQL Python @@ -113,7 +114,7 @@ const config: Config = { { type: "html", value: `
- Courses + Courses
git Postman @@ -128,7 +129,7 @@ const config: Config = { { type: "html", value: `
- Interview Prep + Interview Prep
Technical
Behavioral diff --git a/src/components/navbar/NavbarIcon.tsx b/src/components/navbar/NavbarIcon.tsx index 5064297b..1a06566f 100644 --- a/src/components/navbar/NavbarIcon.tsx +++ b/src/components/navbar/NavbarIcon.tsx @@ -1,52 +1,20 @@ import React from "react"; -import { - Book, - Eye, - LayoutDashboard, - DollarSign, - User, - Newspaper, - MoreHorizontal, - Github, - BadgeCheck, - FileText, - Users, - Tv, - Mic, - Lightbulb, - Puzzle, -} from "lucide-react"; +import { NAVBAR_CONFIG, type NavbarIconName } from "../../constants/navbarConfig"; -const iconMap: Record = { - Docs: , - Showcase: , - Dashboard: , - Donate: , - Devfolio: , - Blogs: , - More: , - GitHub: , - Badges: , - Ebooks: , - Roadmap: , - Community: , - Broadcast: , - Podcast: , - Behavioral: , - Technical: , -}; +interface NavbarIconProps { + name: NavbarIconName; +} + +export default function NavbarIcon({ name }: NavbarIconProps) { + const IconComponent = NAVBAR_CONFIG[name]; + + if (!IconComponent) { + return null; + } -export default function NavbarIcon({ name }: { name: string }) { return ( - - {iconMap[name] || null} + + ); } diff --git a/src/components/navbar/NavbarIconInjector.tsx b/src/components/navbar/NavbarIconInjector.tsx index b9fdbf0c..1a314a51 100644 --- a/src/components/navbar/NavbarIconInjector.tsx +++ b/src/components/navbar/NavbarIconInjector.tsx @@ -1,36 +1,36 @@ import React, { useEffect } from "react"; +import { createRoot } from "react-dom/client"; import NavbarIcon from "./NavbarIcon"; - -const iconMap = [ - { id: "nav-docs", name: "Docs" }, - { id: "nav-showcase", name: "Showcase" }, - { id: "nav-dashboard", name: "Dashboard" }, - { id: "nav-donate", name: "Donate" }, - { id: "nav-devfolio", name: "Devfolio" }, - { id: "nav-blogs", name: "Blogs" }, - { id: "nav-more", name: "More" }, - // Sub nav items - { id: "nav-github", name: "GitHub" }, - { id: "nav-badges", name: "Badges" }, - { id: "nav-ebooks", name: "Ebooks" }, - { id: "nav-roadmap", name: "Roadmap" }, - { id: "nav-community", name: "Community" }, - { id: "nav-broadcast", name: "Broadcast" }, - { id: "nav-podcast", name: "Podcast" }, - { id: "nav-technical", name: "Technical" }, - { id: "nav-behavioral", name: "Behavioral" }, -]; +import { NAVBAR_ICONS, type NavbarIconName } from "../../constants/navbarConfig"; export default function NavbarIconInjector() { useEffect(() => { - iconMap.forEach(({ id, name }) => { - const el = document.getElementById(id); - if (el && el.childNodes.length === 0) { - import("react-dom").then((ReactDOM) => { - (ReactDOM.default as any).render(, el); - }); + const roots = new Map(); + + NAVBAR_ICONS.forEach((name: NavbarIconName) => { + const id = `nav-${name.toLowerCase()}`; + try { + const el = document.getElementById(id); + if (el && !roots.has(id)) { + const root = createRoot(el); + root.render(); + roots.set(id, root); + } + } catch (error) { + console.warn(`Failed to inject navbar icon for ${name}:`, error); } }); + + return () => { + roots.forEach((root, id) => { + try { + root.unmount(); + } catch (error) { + console.warn(`Failed to unmount navbar icon for ${id}:`, error); + } + }); + }; }, []); + return null; } diff --git a/src/components/navbar/docs.tsx b/src/components/navbar/docs.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/ui/FirebaseAuthGithub.tsx b/src/components/ui/FirebaseAuthGithub.tsx index eb8d80b3..8923a70e 100644 --- a/src/components/ui/FirebaseAuthGithub.tsx +++ b/src/components/ui/FirebaseAuthGithub.tsx @@ -52,7 +52,7 @@ const FirebaseAuthGithub: React.FC = () => {
); diff --git a/src/components/ui/NavbarFirebaseAuthGithub.tsx b/src/components/ui/NavbarFirebaseAuthGithub.tsx index dbb474f7..83cb7ee4 100644 --- a/src/components/ui/NavbarFirebaseAuthGithub.tsx +++ b/src/components/ui/NavbarFirebaseAuthGithub.tsx @@ -1,34 +1,15 @@ -import React, { useEffect } from "react"; -import ReactDOM from "react-dom/client"; +import React, { useEffect, useState } from "react"; +import { createPortal } from "react-dom"; import FirebaseAuthGithub from "./FirebaseAuthGithub"; const NavbarFirebaseAuthGithub: React.FC = () => { - useEffect(() => { - const container = document.getElementById("firebase-auth-github-navbar"); - if (container && !container.hasChildNodes()) { - const root = ReactDOM.createRoot(container); - root.render(); - - // Force visibility on mobile after rendering - const ensureVisibility = () => { - const navbarItem = container.closest('.navbar__item'); - if (navbarItem) { - navbarItem.style.display = 'block'; - navbarItem.style.visibility = 'visible'; - navbarItem.style.opacity = '1'; - } - container.style.display = 'block'; - container.style.visibility = 'visible'; - container.style.opacity = '1'; - }; + const [container, setContainer] = useState(null); - // Ensure visibility immediately and after a short delay - ensureVisibility(); - setTimeout(ensureVisibility, 100); - setTimeout(ensureVisibility, 500); - } + useEffect(() => { + setContainer(document.getElementById("firebase-auth-github-navbar")); }, []); - return null; + + return container ? createPortal(, container) : null; }; export default NavbarFirebaseAuthGithub; \ No newline at end of file diff --git a/src/constants/navbarConfig.ts b/src/constants/navbarConfig.ts new file mode 100644 index 00000000..f37ac4c5 --- /dev/null +++ b/src/constants/navbarConfig.ts @@ -0,0 +1,27 @@ +import { + Book, Eye, LayoutDashboard, DollarSign, User, Newspaper, + MoreHorizontal, Github, BadgeCheck, FileText, Users, + Tv, Mic, Lightbulb, Puzzle, Map +} from "lucide-react"; + +export const NAVBAR_CONFIG = { + Docs: Book, + Showcase: Eye, + Dashboard: LayoutDashboard, + Donate: DollarSign, + Devfolio: User, + Blogs: Newspaper, + More: MoreHorizontal, + GitHub: Github, + Badges: BadgeCheck, + Ebooks: FileText, + Roadmap: Map, + Community: Users, + Broadcast: Tv, + Podcast: Mic, + Technical: Puzzle, + Behavioral: Lightbulb +} as const; + +export const NAVBAR_ICONS = Object.keys(NAVBAR_CONFIG) as (keyof typeof NAVBAR_CONFIG)[]; +export type NavbarIconName = keyof typeof NAVBAR_CONFIG; \ No newline at end of file diff --git a/src/css/custom.css b/src/css/custom.css index f0512874..8f79eb33 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -4,7 +4,7 @@ .dropdown-content a.border-r, .dropdown-content a.col-span-1, .dropdown-content a.col-span-2 { - color: #111 !important; + color: var(--ifm-font-color-base); } /* You can override the default Infima variables here. */ @@ -212,78 +212,20 @@ html[data-theme="dark"] .menu__link--active::after { color: #68d391; } -/* ===== INSTANT THEME TRANSITIONS ===== */ -html { - transition: background-color 0.15s ease, color 0.15s ease !important; -} - -body { - transition: background-color 0.15s ease, color 0.15s ease !important; -} - -/* Instant transitions for theme-sensitive elements - exclude stat icons */ -*:not(.stat-icon):not(.stat-icon *):not(svg.lucide):not(svg.lucide *), -*:not(.stat-icon):not(.stat-icon *):not(svg.lucide):not(svg.lucide *)::before, -*:not(.stat-icon):not(.stat-icon *):not(svg.lucide):not(svg.lucide *)::after { - transition: background-color 0.15s ease, color 0.15s ease, - border-color 0.15s ease, box-shadow 0.15s ease !important; -} - -/* Completely disable styling for stat icons and Lucide SVGs */ -.stat-icon, -.stat-icon *, -.stat-icon svg, -.stat-icon svg *, -svg.lucide, -svg.lucide *, -[class*="lucide"], -[class*="lucide"] * { - transition: none !important; - border: 0 !important; - outline: 0 !important; - box-shadow: none !important; - background: transparent !important; - padding: 0 !important; - margin: 0 !important; -} - -/* Very fast transitions for interactive elements - exclude SVG icons */ -button:not(.stat-icon):not(.stat-icon *), -.button:not(.stat-icon):not(.stat-icon *), -a:not(.stat-icon):not(.stat-icon *), -input:not(.stat-icon):not(.stat-icon *), -select:not(.stat-icon):not(.stat-icon *), -textarea:not(.stat-icon):not(.stat-icon *) { - transition: all 0.1s ease !important; -} - -/* Disable all transitions and borders for stat icons */ -.stat-icon, -.stat-icon *, -.stat-icon svg, -.stat-icon svg *, -svg.lucide, -svg.lucide * { - transition: none !important; - border: none !important; - outline: none !important; - box-shadow: none !important; - background: transparent !important; -} - /* Navbar styling and alignment */ .navbar, .navbar__inner, .navbar__brand, .navbar__item, .navbar__link { - transition: background-color 0.1s ease, color 0.1s ease !important; + transition: background-color var(--ifm-transition-fast) ease, + color var(--ifm-transition-fast) ease; } /* Fix navbar alignment and spacing */ .navbar { - padding: 0.2rem 1rem; - height: auto; + padding: 0.5rem 1rem; + height: 60px; display: flex; align-items: center; } @@ -292,33 +234,41 @@ svg.lucide * { display: flex; align-items: center; margin-right: 1rem; - margin-left: 0.9rem; + margin-left: 0; + flex-shrink: 0; } .navbar__logo { - height: 3rem; + height: 2.2rem; margin-right: 0.5rem; } +.navbar__title { + font-size: 1rem; + font-weight: 600; + white-space: nowrap; +} + .navbar__items { display: flex; align-items: center; - gap: 0 !important; + gap: 0.3rem !important; margin: 0 !important; padding: 0 !important; } /* Adjust individual navbar items */ .navbar__items > .navbar__item { - padding: 0.5rem 0.4rem !important; + padding: 0.2rem 0.3rem !important; margin: 0 !important; } .navbar__item { display: flex; align-items: center; - padding: 0.5rem; - font-size: 1rem; + padding: 0.3rem 0.5rem; + font-size: 0.85rem; + line-height: 1.2; } .navbar__link { @@ -334,33 +284,73 @@ svg.lucide * { vertical-align: middle; } -/* Fix dropdown menu spacing and alignment */ +/* ===== CRITICAL FIX: DROPDOWN HOVER BEHAVIOR ===== */ .dropdown { display: inline-flex !important; align-items: center !important; margin: 0 !important; padding: 0 !important; + position: relative !important; +} + +/* Create hover bridge between trigger and menu */ +.dropdown::after { + content: "" !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + right: 0 !important; + height: 10px !important; + background: transparent !important; + z-index: 999 !important; +} + +/* Show dropdown on hover with delay */ +.dropdown:hover .dropdown__menu { + display: block !important; + visibility: visible !important; + opacity: 1 !important; + transition-delay: 0s !important; +} + +/* Keep dropdown visible when hovering over menu itself */ +.dropdown__menu:hover { + display: block !important; + visibility: visible !important; + opacity: 1 !important; } .dropdown__menu { + display: none !important; + visibility: hidden !important; + opacity: 0 !important; min-width: max-content !important; - margin-top: 0.5rem !important; - padding: 0.25rem 0 !important; + margin-top: 10px !important; + padding: 0.5rem 0 !important; + position: absolute !important; + top: 100% !important; + left: 0 !important; + z-index: 1000 !important; + background: var(--ifm-background-color) !important; + border: 1px solid var(--ifm-color-emphasis-300) !important; + border-radius: 6px !important; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important; + transition: opacity 0.15s ease 0.3s, visibility 0.15s ease 0.3s !important; } .dropdown__link { display: flex !important; align-items: center !important; - padding: 0.4rem 0.75rem !important; + padding: 0.6rem 1rem !important; margin: 0 !important; width: 100% !important; font-size: 0.9rem !important; + transition: background-color 0.15s ease !important; + white-space: nowrap !important; } -/* Remove extra spacing between dropdown items */ -.dropdown__menu > .dropdown__link { - padding: 0.4rem 0.75rem !important; - margin: 0 !important; +.dropdown__link:hover { + background-color: var(--ifm-color-emphasis-200) !important; } /* Fix spacing between icon and text in dropdown */ @@ -370,25 +360,6 @@ svg.lucide * { margin-left: 0 !important; } -/* Force instant theme updates for key elements */ -[data-theme="light"] .navbar { - background-color: #ffffff !important; - color: #1a202c !important; -} - -[data-theme="dark"] .navbar { - background-color: #121212 !important; - color: #ffffff !important; -} - -[data-theme="light"] .navbar__link { - color: #1a202c !important; -} - -[data-theme="dark"] .navbar__link { - color: #ffffff !important; -} - :root { --ifm-color-primary: #2e8555; --ifm-color-primary-dark: #29784c; @@ -399,15 +370,34 @@ svg.lucide * { --ifm-color-primary-lightest: #3cad6e; --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); - --ifm-color-primary-text: white; - --ifm-color-secondary-text: #edf2f7; + --ifm-transition-fast: 150ms; + --ifm-transition-slow: 300ms; +} - /* Light theme defaults */ - --ifm-background-color: #ffffff; - --ifm-font-color-base: #000000; +/* Smooth theme transitions */ +html, +body { + transition: background-color 150ms ease, color 150ms ease; +} + +.navbar, +.footer, +.sidebar, +.main-wrapper { + transition: background-color 150ms ease, color 150ms ease, + border-color 150ms ease; +} + +/* Navbar icon styling */ +.navbar-icon { + display: inline-flex; + align-items: center; + gap: 4px; + margin-right: 4px; + min-width: 18px; + min-height: 18px; } -/* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme="dark"] { --ifm-color-primary: #25c2a0; --ifm-color-primary-dark: #21af90; @@ -417,62 +407,36 @@ svg.lucide * { --ifm-color-primary-lighter: #32d8b4; --ifm-color-primary-lightest: #4fddbf; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); - --ifm-color-primary-text: #ffffff; - --ifm-color-secondary-text: #edf2f7; - - /* Dark theme background and text */ - --ifm-background-color: #121212; - --ifm-font-color-base: #ffffff; - - /* Standardized Dark Theme Colors */ - --dark-bg-primary: #121212; - --dark-bg-secondary: #1a1a1a; - --dark-bg-tertiary: #2d2d2d; - --dark-text-primary: #ffffff; - --dark-text-secondary: #edf2f7; - --dark-text-muted: #a0aec0; - --dark-border: #2d2d2d; - --dark-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), - 0 2px 4px -1px rgba(0, 0, 0, 0.2); - --dark-shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.4), - 0 10px 10px -5px rgba(0, 0, 0, 0.2); - - /* Card and component backgrounds */ - --dark-card-bg: #1a1a1a; - --dark-card-hover-bg: #2d2d2d; - - /* Form elements */ - --dark-input-bg: #2d2d2d; - --dark-input-border: #4a5568; - --dark-input-focus-border: #25c2a0; -} - -/* Mobile navigation styles */ +} + +/* ===== CRITICAL FIX: MOBILE NAVBAR BEHAVIOR ===== */ @media screen and (max-width: 996px) { - /* Hide text in navbar */ - .navbar__items .navbar__item span, - .navbar__items .navbar__link span, - span[id^="nav-"] { + /* Hide TOP navbar items on mobile (not sidebar) */ + .navbar__items:not(.navbar__items--right) + .navbar__item:not(.navbar__toggle):not(.navbar__brand) { display: none !important; } - /* Hide text but keep icons visible */ - .navbar__items - .navbar__item:not(.navbar__toggle):not(.navbar__brand):not( - .quickstart-icons - ), - .navbar__items - .navbar__link:not(.navbar__toggle):not(.navbar__brand):not( - .quickstart-icons - ) { - font-size: 0 !important; - padding: 0.4rem !important; + /* Keep sidebar items visible */ + .navbar-sidebar .navbar__item, + .navbar-sidebar .navbar__link, + .navbar-sidebar .dropdown { + display: block !important; } - /* Layout for mobile navbar */ + /* Only show essential elements in TOP navbar */ + .navbar__toggle, + .navbar__brand, + .navbar__search, + #firebase-auth-github-navbar, + .colorModeToggle { + display: flex !important; + } + + /* Clean mobile navbar layout - prevent overflow */ .navbar { - justify-content: flex-start !important; - padding: 0.3rem 0.5rem !important; + padding: 0.5rem 0.5rem !important; + height: 56px !important; } .navbar__inner { @@ -482,54 +446,90 @@ svg.lucide * { justify-content: space-between !important; } - /* Essential elements visibility and styling */ - .navbar__toggle, - .navbar__search, - .navbar-sidebar__brand, - .navbar__brand, - .navbar-sidebar .navbar__item, - .quickstart-icons { + /* Right side items - only essential ones with proper spacing */ + .navbar__items--right { display: flex !important; align-items: center !important; + justify-content: space-between; + gap: 0.2rem !important; + margin-left: auto !important; + flex-shrink: 0 !important; } - /* Icon sizes and visibility */ - .navbar__toggle svg, - .navbar__search svg, - .navbar__link svg, - .navbar__link img, - .quickstart-icons svg, - .quickstart-icons img { - display: block !important; - width: 24px !important; - height: 24px !important; - margin: 0 !important; - opacity: 1 !important; - color: currentColor !important; + /* Logo and brand adjustments */ + .navbar__brand { + margin-right: 1.5rem !important; } - /* Toggle and search button styling */ - .navbar__toggle { - transform: scale(1.2) !important; - padding: 0.6rem !important; - margin-right: 0.5rem !important; + .navbar__logo { + height: 32px !important; } - .navbar__search { - margin-left: 0.5rem !important; + .navbar__title { + font-size: 1rem !important; } - /* Right side items */ - .navbar__items--right { + /* Mobile search button - fixed spacing */ + .DocSearch-Button { + min-width: 36px !important; + width: 36px !important; + height: 36px !important; + padding: 0.3rem !important; + margin: 0 0.25rem !important; + flex-shrink: 0 !important; + box-sizing: border-box !important; + } + + .DocSearch-Button-Placeholder, + .DocSearch-Button-Keys { + display: none !important; + } + + /* Mobile GitHub button - fixed spacing */ + #firebase-auth-github-navbar { + display: flex !important; + flex-shrink: 0 !important; + position: relative !important; + } + + #firebase-auth-github-navbar button { + height: 36px !important; + width: 36px !important; + min-width: 36px !important; + padding: 0.3rem !important; + font-size: 0 !important; + margin: 0 0.25rem !important; + flex-shrink: 0 !important; + position: relative !important; display: flex !important; align-items: center !important; - gap: 0.8rem !important; - margin-left: auto !important; + justify-content: center !important; + box-sizing: border-box !important; } - /* Logo size */ - .navbar__logo { - height: 40px !important; + #firebase-auth-github-navbar button svg { + margin-right: 0 !important; + } + + /* Mobile theme toggle - fixed spacing */ + .colorModeToggle { + width: 36px !important; + height: 36px !important; + min-width: 36px !important; + padding: 0.3rem !important; + margin: 0 0.25rem !important; + flex-shrink: 0 !important; + position: relative !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + box-sizing: border-box !important; + } + + /* Ensure sidebar toggle is always visible */ + .navbar__toggle { + display: block !important; + margin-right: 0.5rem !important; } } @@ -545,17 +545,58 @@ svg.lucide * { } } +/* ===== TABLET AND DESKTOP NAVBAR (997px+) ===== */ +@media (min-width: 997px) { + /* Enhanced dropdown hover behavior */ + .dropdown:hover .dropdown__menu { + display: block !important; + visibility: visible !important; + opacity: 1 !important; + transition-delay: 0s !important; + } + + /* Slower hide transition to prevent accidental closing */ + .dropdown:not(:hover) .dropdown__menu { + transition-delay: 0.5s !important; + } + + /* Expand hover area for easier navigation */ + .dropdown { + padding-bottom: 10px !important; + } + + /* Better spacing for desktop navbar */ + .navbar__inner { + max-width: 1400px; + margin: 0 auto; + width: 100%; + padding: 0 1rem; + } + + .navbar__items:not(.navbar__items--right) { + flex: 1; + justify-content: flex-start; + margin-left: 0; + margin-right: 2rem; + } + + /* Ensure proper spacing between left and right items */ + .navbar__items--right { + margin-left: auto !important; + } +} + /* Icon-only navbar design for tablets and smaller screens */ -@media (max-width: 1200px) { +@media (max-width: 1200px) and (min-width: 997px) { /* Right navbar container with proper spacing */ .navbar .navbar__inner .navbar__items.navbar__items--right { display: flex !important; align-items: center; - gap: 20px; - margin: auto auto; + gap: 0.5rem; + margin-left: auto; flex-shrink: 0; height: 100%; - padding: 8px 0; + padding: 0; } /* Make all right navbar items visible with consistent layout */ @@ -570,28 +611,19 @@ svg.lucide * { /* GitHub auth button - improved styling */ #firebase-auth-github-navbar button { - width: 30x !important; - height: 45px !important; - padding: 5px !important; - padding-left: 10px !important; - font-size: 0 !important; - /* Hide text */ + height: 36px !important; + padding: 0.5rem 0.75rem !important; + font-size: 0.8rem !important; display: flex !important; justify-content: center !important; align-items: center !important; - border-radius: 12px !important; + border-radius: 6px !important; background-color: #24292e !important; border: 1px solid rgba(255, 255, 255, 0.1) !important; - - /* Increase sidebar width for better spacing */ - .navbar-sidebar { - width: 270px !important; - min-width: 270px !important; - max-width: 320px !important; - } - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.15) !important; - transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important; + transition: all 0.2s ease !important; cursor: pointer !important; + white-space: nowrap !important; } #firebase-auth-github-navbar button:hover { @@ -602,26 +634,27 @@ svg.lucide * { } #firebase-auth-github-navbar button svg { - width: 24px !important; - height: 24px !important; + width: 16px !important; + height: 16px !important; color: white !important; flex-shrink: 0 !important; + margin-right: 0.5rem !important; } /* Search button - consistent styling */ .DocSearch-Button { - width: 48px !important; - height: 48px !important; - padding: 12px !important; - border-radius: 10px !important; + height: 36px !important; + min-width: 180px !important; + padding: 0.5rem 0.75rem !important; + border-radius: 6px !important; margin: 0 !important; display: flex !important; - justify-content: center !important; + justify-content: flex-start !important; align-items: center !important; background-color: var(--ifm-color-emphasis-200) !important; border: 1px solid var(--ifm-color-emphasis-300) !important; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12) !important; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important; + transition: all 0.2s ease !important; cursor: pointer !important; } @@ -638,28 +671,40 @@ svg.lucide * { } .DocSearch-Search-Icon { - width: 24px !important; - height: 24px !important; - margin: 0 !important; - color: var(--ifm-color-emphasis-800) !important; + width: 16px !important; + height: 16px !important; + margin-right: 0.5rem !important; + color: var(--ifm-color-emphasis-600) !important; flex-shrink: 0 !important; } + .DocSearch-Button-Placeholder { + display: block !important; + font-size: 0.8rem !important; + color: var(--ifm-color-emphasis-600) !important; + } + + .DocSearch-Button-Keys { + display: flex !important; + margin-left: auto !important; + } + /* Theme toggle - improved styling */ .colorModeToggle { display: flex !important; - width: 52px !important; - height: 52px !important; - padding: 14px !important; - border-radius: 12px !important; + width: 36px !important; + height: 36px !important; + padding: 0.5rem !important; + border-radius: 6px !important; margin: 0 !important; background-color: var(--ifm-color-emphasis-200) !important; border: 1px solid var(--ifm-color-emphasis-300) !important; - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.15) !important; - transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important; + transition: all 0.2s ease !important; justify-content: center !important; align-items: center !important; cursor: pointer !important; + flex-shrink: 0 !important; } .colorModeToggle:hover { @@ -670,9 +715,9 @@ svg.lucide * { } .colorModeToggle svg { - width: 24px !important; - height: 24px !important; - color: var(--ifm-color-emphasis-800) !important; + width: 16px !important; + height: 16px !important; + color: var(--ifm-color-emphasis-700) !important; flex-shrink: 0 !important; } @@ -704,11 +749,74 @@ svg.lucide * { } } -/* Tablet and medium screen adjustments */ +/* ===== MOBILE SIDEBAR IMPROVEMENTS ===== */ @media (max-width: 996px) { + /* Ensure sidebar is fully functional */ + .navbar-sidebar { + display: block !important; + } + + .navbar-sidebar .navbar__items { + display: block !important; + } + + .navbar-sidebar .navbar__item { + display: block !important; + margin: 0.25rem 0 !important; + } + + .navbar-sidebar .navbar__link { + display: block !important; + padding: 0.2rem 0.4rem !important; + border-radius: 6px !important; + transition: background-color 0.2s ease !important; + } + + .navbar-sidebar .navbar__link:hover { + background-color: var(--ifm-color-emphasis-200) !important; + } + + /* Improve sidebar dropdown behavior */ + .navbar-sidebar .dropdown { + display: block !important; + } + + .navbar-sidebar .dropdown__menu { + position: static !important; + display: block !important; + box-shadow: none !important; + border: none !important; + margin: 0 !important; + padding: 0.5rem 0 !important; + background: transparent !important; + } + + .navbar-sidebar .dropdown__link { + padding: 0.5rem 1rem 0.5rem 2rem !important; + border-radius: 4px !important; + margin: 2px 0 !important; + font-size: 0.9rem !important; + } + + .navbar-sidebar .dropdown__link:hover { + background-color: var(--ifm-color-emphasis-300) !important; + } + + /* Right side items spacing */ .navbar .navbar__inner .navbar__items.navbar__items--right { - gap: 18px !important; - margin-right: 60px !important; + gap: 0.55rem !important; + margin-right: 0 !important; + } + + /* Hide GitHub button text on mobile - show only icon */ + #firebase-auth-github-navbar .github-text { + display: none !important; + } + + #firebase-auth-github-navbar button { + padding: 0.5rem !important; + min-width: 44px !important; + justify-content: center !important; } } @@ -716,15 +824,15 @@ svg.lucide * { .dropdown-content a, .navbar__item, .navbar__link { - color: #111 !important; + color: var(--ifm-font-color-base); transition: color 0.2s ease, background 0.2s ease; } .dropdown-content a:hover, .navbar__item:hover, .navbar__link:hover { - color: #2e8555 !important; - background: none !important; + color: var(--ifm-color-primary); + background: none; border-radius: 0; box-shadow: none; transform: none; @@ -747,7 +855,7 @@ svg.lucide * { bottom: 0; width: 100%; height: 2px; - background: #2e8555; + background: var(--ifm-color-primary); transform: scaleX(0); transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); } @@ -760,23 +868,12 @@ svg.lucide * { [data-theme="dark"] .navbar__item:hover:not(:has(img)):not(:has(svg)), [data-theme="dark"] .navbar__link:hover:not(:has(img)):not(:has(svg)), [data-theme="dark"] .dropdown-content a:hover:not(:has(img)):not(:has(svg)) { - color: #25c2a0 !important; + color: var(--ifm-color-primary); } [data-theme="dark"] .navbar__item:not(:has(img)):not(:has(svg))::after, [data-theme="dark"] .navbar__link:not(:has(img)):not(:has(svg))::after, [data-theme="dark"] .dropdown-content a:not(:has(img)):not(:has(svg))::after { - background: #25c2a0; -} - -[data-theme="dark"] .dropdown-content a:hover, -[data-theme="dark"] .navbar__item:hover, -[data-theme="dark"] .navbar__link:hover { - color: #fff !important; - background: #164e63; - border-radius: 8px; - box-shadow: 0 4px 12px rgba(44, 62, 80, 0.18); - transform: translateY(-1px) scale(1.01); - text-decoration: underline; + background: var(--ifm-color-primary); } /* Mobile screen adjustments */ @@ -846,28 +943,36 @@ svg.lucide * { .dropbtn { width: 110px; background-color: transparent; - color: #111 !important; + color: var(--ifm-font-color-base); padding: 14px; font-size: 18px; border: none; cursor: pointer; - border-right: 1px solid #4e8da0db; + border-right: 1px solid var(--ifm-color-emphasis-300); margin: 2px; } /* Fix navbar icon and text alignment */ .navbar__items .navbar__link { display: inline-flex !important; align-items: center !important; - gap: 0.2rem !important; - height: 40px !important; /* Consistent height */ - padding: 0.5rem 0.8rem !important; + gap: 0.25rem !important; + height: 32px !important; + padding: 0.3rem 0.5rem !important; + font-size: 0.85rem !important; + line-height: 1.2 !important; + border-radius: 4px !important; + transition: background-color 0.2s ease !important; +} + +.navbar__link:hover { + background-color: var(--ifm-color-emphasis-200) !important; } /* Fix specific icon alignment in navbar */ .navbar__link img, .navbar__link svg { - width: 20px !important; - height: 20px !important; + width: 16px !important; + height: 16px !important; margin: 0 !important; vertical-align: middle !important; } @@ -876,17 +981,19 @@ svg.lucide * { .navbar__link span { display: inline-flex !important; align-items: center !important; - line-height: 1 !important; + line-height: 1.2 !important; } /* Adjust dropdown items alignment */ .dropdown__link { display: inline-flex !important; align-items: center !important; - gap: 0.2rem !important; + gap: 0.25rem !important; + font-size: 0.8rem !important; + padding: 0.4rem 0.6rem !important; } .nav__icons { - color: #111 !important; + color: var(--ifm-font-color-base); text-decoration: none; } .nav__icons img { @@ -900,18 +1007,18 @@ svg.lucide * { min-width: 180px; } .dropdown-content a { - color: #111 !important; + color: var(--ifm-font-color-base); transition: background 0.2s, color 0.2s; } .dropdown-content .border-r, .dropdown-content .col-span-1, .dropdown-content .col-span-2 { - color: #111 !important; + color: var(--ifm-font-color-base); } .dropdown-content a:hover { - color: #fff !important; - background: #222 !important; + color: var(--ifm-font-color-base-inverse); + background: var(--ifm-color-emphasis-600); border-radius: 8px; } .no-scrollbar::-webkit-scrollbar { @@ -936,37 +1043,6 @@ svg.lucide * { [role="tab"] { text-align: left !important; justify-content: flex-start !important; - - .dropdown-content a:hover, - .navbar__item:hover, - .navbar__link:hover { - color: #222 !important; - background: #f3f4f6; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); - transform: translateY(-2px) scale(1.04); - } - - /* Subnav items (dropdown inner links) */ - .dropdown-content .grid.grid-cols-3.gap-4 a:hover, - .dropdown-content .grid.grid-cols-1.col-span-2 a:hover { - color: #2e8555 !important; - background: none !important; - border-radius: 0; - box-shadow: none; - transform: none; - position: relative; - } -} - -[data-theme="dark"] .dropdown-content .grid.grid-cols-3.gap-4 a:hover, -[data-theme="dark"] .dropdown-content .grid.grid-cols-1.col-span-2 a:hover { - color: #25c2a0 !important; - background: none !important; - border-radius: 0; - box-shadow: none; - transform: none; - position: relative; } /* Active tab styles */ @@ -1014,600 +1090,6 @@ svg.lucide * { color: transparent; } -/* ===== THEME OVERRIDES - CLEAN APPROACH ===== */ - -/* Light theme - Clean background */ -[data-theme="light"] { - --ifm-background-color: #ffffff; - --ifm-font-color-base: #1a202c; - --ifm-card-background-color: #ffffff; -} - -[data-theme="light"] body { - background-color: var(--ifm-background-color) !important; - color: var(--ifm-font-color-base) !important; -} - -/* Dark theme - Clean background */ -[data-theme="dark"] { - --ifm-background-color: #121212; - --ifm-font-color-base: #ffffff; - --ifm-card-background-color: #1a1a1a; -} - -[data-theme="dark"] body { - background-color: var(--ifm-background-color) !important; - color: var(--ifm-font-color-base) !important; -} - -/* Global dark theme utilities */ -[data-theme="dark"] .dark-bg-primary { - background-color: var(--dark-bg-primary) !important; -} - -[data-theme="dark"] .dark-bg-secondary { - background-color: var(--dark-bg-secondary) !important; -} - -[data-theme="dark"] .dark-bg-tertiary { - background-color: var(--dark-bg-tertiary) !important; -} - -[data-theme="dark"] .dark-text-primary { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .dark-text-secondary { - color: var(--dark-text-secondary) !important; -} - -[data-theme="dark"] .dark-text-muted { - color: var(--dark-text-muted) !important; -} - -[data-theme="dark"] .dark-border { - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .dark-shadow { - box-shadow: var(--dark-shadow) !important; -} - -[data-theme="dark"] .dark-shadow-lg { - box-shadow: var(--dark-shadow-lg) !important; -} - -/* Form elements dark theme */ -[data-theme="dark"] input, -[data-theme="dark"] textarea, -[data-theme="dark"] select { - background-color: var(--dark-input-bg) !important; - border-color: var(--dark-input-border) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] input:focus, -[data-theme="dark"] textarea:focus, -[data-theme="dark"] select:focus { - border-color: var(--dark-input-focus-border) !important; - box-shadow: 0 0 0 2px rgba(37, 194, 160, 0.2) !important; -} - -[data-theme="dark"] input::placeholder, -[data-theme="dark"] textarea::placeholder { - color: var(--dark-text-muted) !important; -} - -/* ===== CLEAN BUTTON FIXES ===== */ - -/* Remove conflicting button styles - let Docusaurus handle it naturally */ -[data-theme="light"] .button--outline, -[data-theme="light"] .button--secondary { - background-color: transparent !important; - color: var(--ifm-font-color-base) !important; - border: 1px solid var(--ifm-color-emphasis-300) !important; -} - -[data-theme="dark"] .button--outline, -[data-theme="dark"] .button--secondary { - background-color: transparent !important; - color: var(--ifm-font-color-base) !important; - border: 1px solid var(--ifm-color-emphasis-300) !important; -} - -/* ===== MINIMAL THEME FIXES ===== */ - -/* Only fix specific problematic elements */ -[data-theme="light"] .card { - background-color: var(--ifm-card-background-color) !important; - color: var(--ifm-font-color-base) !important; -} - -[data-theme="dark"] .card { - background-color: var(--ifm-card-background-color) !important; - color: var(--ifm-font-color-base) !important; -} - -/* Card components dark theme */ -[data-theme="dark"] .card { - background-color: var(--dark-card-bg) !important; - border-color: var(--dark-border) !important; - color: var(--dark-text-primary) !important; - box-shadow: var(--dark-shadow) !important; -} - -[data-theme="dark"] .card:hover { - background-color: var(--dark-card-hover-bg) !important; - box-shadow: var(--dark-shadow-lg) !important; -} - -/* Table dark theme */ -[data-theme="dark"] table { - background-color: var(--dark-bg-secondary) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] th { - background-color: var(--dark-bg-tertiary) !important; - color: var(--dark-text-primary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] td { - border-color: var(--dark-border) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] tr:hover { - background-color: var(--dark-card-hover-bg) !important; -} - -/* Navigation dark theme */ -[data-theme="dark"] .navbar { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .navbar__item { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .navbar__link:hover { - color: var(--ifm-color-primary) !important; -} - -/* Footer - keeping original styling */ - -/* Modal dark theme */ -[data-theme="dark"] .modal { - background-color: var(--dark-bg-secondary) !important; - color: var(--dark-text-primary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .modal-header { - background-color: var(--dark-bg-tertiary) !important; - border-color: var(--dark-border) !important; -} - -/* Dropdown dark theme */ -[data-theme="dark"] .dropdown { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; - box-shadow: var(--dark-shadow-lg) !important; -} - -[data-theme="dark"] .dropdown__link { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .dropdown__link:hover { - background-color: var(--dark-card-hover-bg) !important; - color: var(--ifm-color-primary) !important; -} - -/* Code blocks dark theme */ -[data-theme="dark"] pre { - background-color: var(--dark-bg-tertiary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] code { - background-color: var(--dark-bg-tertiary) !important; - color: var(--dark-text-primary) !important; -} - -/* ===== DOCUSAURUS DOCUMENTATION PAGES DARK THEME ===== */ - -/* Main documentation layout - EXCLUDE community page */ -[data-theme="dark"] body:not(:has(.community-page)) .main-wrapper { - background-color: var(--dark-bg-primary) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] body:not(:has(.community-page)) .docusaurus-wrapper { - background-color: var(--dark-bg-primary) !important; -} - -/* Documentation content area - EXCLUDE community page */ -[data-theme="dark"] body:not(:has(.community-page)) .container { - background-color: var(--dark-bg-primary) !important; -} - -[data-theme="dark"] body:not(:has(.community-page)) .row { - background-color: var(--dark-bg-primary) !important; -} - -[data-theme="dark"] body:not(:has(.community-page)) .col { - background-color: var(--dark-bg-primary) !important; -} - -/* Documentation sidebar */ -[data-theme="dark"] .theme-doc-sidebar-container { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .theme-doc-sidebar-menu { - background-color: var(--dark-bg-secondary) !important; -} - -[data-theme="dark"] .menu__link { - color: var(--dark-text-secondary) !important; -} - -[data-theme="dark"] .menu__link:hover { - background-color: var(--dark-card-hover-bg) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .menu__link--active { - background-color: var(--ifm-color-primary) !important; - color: white !important; -} - -[data-theme="dark"] .menu__list-item-collapsible { - background-color: var(--dark-bg-secondary) !important; -} - -[data-theme="dark"] .menu__caret { - color: var(--dark-text-muted) !important; -} - -/* Documentation content */ -[data-theme="dark"] .theme-doc-markdown { - background-color: var(--dark-bg-primary) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .markdown { - background-color: var(--dark-bg-primary) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .markdown h1, -[data-theme="dark"] .markdown h2, -[data-theme="dark"] .markdown h3, -[data-theme="dark"] .markdown h4, -[data-theme="dark"] .markdown h5, -[data-theme="dark"] .markdown h6 { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .markdown p { - color: var(--dark-text-secondary) !important; -} - -[data-theme="dark"] .markdown li { - color: var(--dark-text-secondary) !important; -} - -[data-theme="dark"] .markdown a { - color: var(--ifm-color-primary) !important; -} - -[data-theme="dark"] .markdown a:hover { - color: var(--ifm-color-primary-light) !important; -} - -/* Documentation breadcrumbs */ -[data-theme="dark"] .breadcrumbs { - background-color: var(--dark-bg-primary) !important; -} - -[data-theme="dark"] .breadcrumbs__link { - color: var(--dark-text-muted) !important; -} - -[data-theme="dark"] .breadcrumbs__link:hover { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .breadcrumbs__item--active .breadcrumbs__link { - color: var(--dark-text-primary) !important; -} - -/* Documentation table of contents */ -[data-theme="dark"] .table-of-contents { - background-color: var(--dark-bg-primary) !important; -} - -[data-theme="dark"] .table-of-contents__link { - color: var(--dark-text-muted) !important; -} - -[data-theme="dark"] .table-of-contents__link:hover { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .table-of-contents__link--active { - color: var(--ifm-color-primary) !important; -} - -/* Documentation pagination */ -[data-theme="dark"] .pagination-nav { - background-color: var(--dark-bg-primary) !important; -} - -[data-theme="dark"] .pagination-nav__link { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .pagination-nav__link:hover { - background-color: var(--dark-card-hover-bg) !important; - border-color: var(--ifm-color-primary) !important; -} - -[data-theme="dark"] .pagination-nav__sublabel { - color: var(--dark-text-muted) !important; -} - -[data-theme="dark"] .pagination-nav__label { - color: var(--dark-text-primary) !important; -} - -/* Documentation admonitions (info, warning, etc.) */ -[data-theme="dark"] .admonition { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .admonition-heading { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .admonition-content { - color: var(--dark-text-secondary) !important; -} - -/* Documentation tabs */ -[data-theme="dark"] .tabs-container { - background-color: var(--dark-bg-primary) !important; -} - -[data-theme="dark"] .tabs { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .tabs__item { - background-color: var(--dark-bg-secondary) !important; - color: var(--dark-text-muted) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .tabs__item:hover { - background-color: var(--dark-card-hover-bg) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .tabs__item--active { - background-color: var(--dark-bg-primary) !important; - color: var(--ifm-color-primary) !important; - border-bottom-color: var(--ifm-color-primary) !important; -} - -[data-theme="dark"] .tabpanel { - background-color: var(--dark-bg-primary) !important; - color: var(--dark-text-primary) !important; -} - -/* Documentation code blocks */ -[data-theme="dark"] .prism-code { - background-color: var(--dark-bg-tertiary) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .codeBlockTitle { - background-color: var(--dark-bg-tertiary) !important; - color: var(--dark-text-primary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .codeBlockLines { - background-color: var(--dark-bg-tertiary) !important; -} - -[data-theme="dark"] .token-line { - color: var(--dark-text-primary) !important; -} - -/* Documentation blockquotes */ -[data-theme="dark"] blockquote { - background-color: var(--dark-bg-secondary) !important; - border-left-color: var(--ifm-color-primary) !important; - color: var(--dark-text-secondary) !important; -} - -/* Documentation details/summary */ -[data-theme="dark"] details { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] summary { - background-color: var(--dark-bg-tertiary) !important; - color: var(--dark-text-primary) !important; -} - -/* Documentation search */ -[data-theme="dark"] .DocSearch { - --docsearch-primary-color: var(--ifm-color-primary) !important; - --docsearch-text-color: var(--dark-text-primary) !important; - --docsearch-muted-color: var(--dark-text-muted) !important; - --docsearch-container-background: rgba(18, 18, 18, 0.8) !important; - --docsearch-modal-background: var(--dark-bg-secondary) !important; - --docsearch-searchbox-background: var(--dark-bg-tertiary) !important; - --docsearch-searchbox-focus-background: var(--dark-bg-tertiary) !important; - --docsearch-hit-color: var(--dark-text-primary) !important; - --docsearch-hit-active-color: var(--dark-text-primary) !important; - --docsearch-hit-background: var(--dark-bg-tertiary) !important; - --docsearch-hit-shadow: var(--dark-shadow) !important; - --docsearch-key-gradient: linear-gradient( - -225deg, - var(--dark-bg-tertiary), - var(--dark-bg-secondary) - ) !important; - --docsearch-key-shadow: inset 0 -2px 0 0 var(--dark-border), - inset 0 0 1px 1px var(--dark-border), 0 1px 2px 1px rgba(0, 0, 0, 0.3) !important; - --docsearch-footer-background: var(--dark-bg-tertiary) !important; - --docsearch-footer-shadow: var(--dark-shadow) !important; -} - -/* Documentation edit page link */ -[data-theme="dark"] .theme-edit-this-page { - color: var(--dark-text-muted) !important; -} - -[data-theme="dark"] .theme-edit-this-page:hover { - color: var(--ifm-color-primary) !important; -} - -/* Documentation last updated */ -[data-theme="dark"] .theme-last-updated { - color: var(--dark-text-muted) !important; -} - -/* Documentation category cards */ -[data-theme="dark"] .card { - background-color: var(--dark-card-bg) !important; - border-color: var(--dark-border) !important; - color: var(--dark-text-primary) !important; - box-shadow: var(--dark-shadow) !important; -} - -[data-theme="dark"] .card:hover { - background-color: var(--dark-card-hover-bg) !important; - box-shadow: var(--dark-shadow-lg) !important; -} - -[data-theme="dark"] .card__header { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .card__body { - color: var(--dark-text-secondary) !important; -} - -[data-theme="dark"] .card__footer { - border-color: var(--dark-border) !important; -} - -/* Documentation hero banner */ -[data-theme="dark"] .hero { - background-color: var(--dark-bg-secondary) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .hero__title { - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .hero__subtitle { - color: var(--dark-text-secondary) !important; -} - -/* Documentation alert/callout boxes */ -[data-theme="dark"] .alert { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .alert--primary { - background-color: rgba(37, 194, 160, 0.1) !important; - border-color: var(--ifm-color-primary) !important; -} - -[data-theme="dark"] .alert--secondary { - background-color: var(--dark-bg-tertiary) !important; - border-color: var(--dark-border) !important; -} - -[data-theme="dark"] .alert--success { - background-color: rgba(34, 197, 94, 0.1) !important; - border-color: #22c55e !important; -} - -[data-theme="dark"] .alert--info { - background-color: rgba(59, 130, 246, 0.1) !important; - border-color: #3b82f6 !important; -} - -[data-theme="dark"] .alert--warning { - background-color: rgba(245, 158, 11, 0.1) !important; - border-color: #f59e0b !important; -} - -[data-theme="dark"] .alert--danger { - background-color: rgba(239, 68, 68, 0.1) !important; - border-color: #ef4444 !important; -} - -/* Documentation inline code */ -[data-theme="dark"] code:not([class*="language-"]) { - background-color: var(--dark-bg-tertiary) !important; - color: var(--ifm-color-primary) !important; - border: 1px solid var(--dark-border) !important; -} - -/* Documentation horizontal rules */ -[data-theme="dark"] hr { - border-color: var(--dark-border) !important; -} - -/* Documentation images */ -[data-theme="dark"] .markdown img { - border-radius: 8px; - box-shadow: var(--dark-shadow); -} - -/* Fix for any remaining white backgrounds */ -[data-theme="dark"] .theme-doc-version-banner { - background-color: var(--dark-bg-secondary) !important; - border-color: var(--dark-border) !important; - color: var(--dark-text-primary) !important; -} - -[data-theme="dark"] .theme-doc-version-badge { - background-color: var(--dark-bg-tertiary) !important; - color: var(--dark-text-primary) !important; -} - -/* Ensure all text is readable */ -[data-theme="dark"] * { - border-color: var(--dark-border); -} - -[data-theme="dark"] .theme-doc-markdown > div, -[data-theme="dark"] .theme-doc-markdown > section, -[data-theme="dark"] .theme-doc-markdown > article { - background-color: var(--dark-bg-primary) !important; - color: var(--dark-text-primary) !important; -} html.theme-light .bg-white { background-color: #ffffff !important; } @@ -1926,13 +1408,11 @@ html { color: white; } -.interview-prep-discord-btn{ - color:white; - +.interview-prep-discord-btn { + color: white; } -.interview-prep-discord-btn:hover{ - color:white; - +.interview-prep-discord-btn:hover { + color: white; } [data-theme="dark"] .overview-sidebar-blue { @@ -1947,75 +1427,105 @@ html { [data-theme="dark"] .overview-sidebar-purple { border-color: #a855f7; } -[data-theme='dark'] .technical-outer{ - border-color: #3b82f6 - +[data-theme="dark"] .technical-outer { + border-color: #3b82f6; } -[data-theme='dark'] .technical-inner{ - border-color: #374151 - +[data-theme="dark"] .technical-inner { + border-color: #374151; } -[data-theme='dark'] .technical-inner-success{ - border-color: #92400e +[data-theme="dark"] .technical-inner-success { + border-color: #92400e; } -[data-theme='dark'] .question-bank-purple{ - border-color: #a855f7 +[data-theme="dark"] .question-bank-purple { + border-color: #a855f7; } -[data-theme='dark'] .question-bank-blue{ - border-color: #3b82f6 +[data-theme="dark"] .question-bank-blue { + border-color: #3b82f6; } -[data-theme='dark'] .question-bank-green{ - border-color: #22c55e +[data-theme="dark"] .question-bank-green { + border-color: #22c55e; } -[data-theme='dark'] .question-bank-orange{ - border-color: v +[data-theme="dark"] .question-bank-orange { + border-color: #f97316; } -.technical-btn{ +.technical-btn { color: white; } -.technical-btn:hover{ - color:white; +.technical-btn:hover { + color: white; } /* Dark mode border overrides for Technical tab subtopic cards */ /* Purple */ -[data-theme='dark'] .question-bank-subtopic-purple { +[data-theme="dark"] .question-bank-subtopic-purple { border-color: #a855f7 !important; /* purple-500 */ } /* Blue */ -[data-theme='dark'] .question-bank-subtopic-blue { +[data-theme="dark"] .question-bank-subtopic-blue { border-color: #3b82f6 !important; /* blue-500 */ } /* Green */ -[data-theme='dark'] .question-bank-subtopic-green { +[data-theme="dark"] .question-bank-subtopic-green { border-color: #22c55e !important; /* green-500 */ } /* Orange */ -[data-theme='dark'] .question-bank-subtopic-orange { +[data-theme="dark"] .question-bank-subtopic-orange { border-color: #f97316 !important; /* orange-500 */ } /* Pink */ -[data-theme='dark'] .question-bank-subtopic-pink { +[data-theme="dark"] .question-bank-subtopic-pink { border-color: #ec4899 !important; /* pink-500 */ } /* Cyan */ -[data-theme='dark'] .question-bank-subtopic-cyan { +[data-theme="dark"] .question-bank-subtopic-cyan { border-color: #06b6d4 !important; /* cyan-500 */ } +.explore-btn { + color: white; +} -.explore-btn{ - color:white; +.explore-btn:hover { + color: white; +} +/* Global alignment fix for navbar right elements */ +.navbar .navbar__inner .navbar__items--right { + display: flex !important; + align-items: center !important; + gap: 1rem !important; + margin-right: 1rem !important; + padding-right: 0 !important; + /* transform: translateX(-60px) !important; */ +} + +@media (min-width: 997px) { + .navbar .navbar__inner .navbar__items--right { + margin-right: 1.5rem !important; + transform: none !important; + gap: 0.5rem !important; + } } -.explore-btn:hover{ - color:white; -} \ No newline at end of file +.navbar__items--right .navbar__item { + display: flex !important; + align-items: center !important; + height: 36px !important; +} + +.DocSearch-Button, +#firebase-auth-github-navbar button, +.colorModeToggle { + height: 36px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + box-sizing: border-box !important; +} diff --git a/src/pages/dashboard/dashboard.css b/src/pages/dashboard/dashboard.css index 9a5bb06d..f8c6c421 100644 --- a/src/pages/dashboard/dashboard.css +++ b/src/pages/dashboard/dashboard.css @@ -2219,6 +2219,15 @@ color: var(--ifm-color-emphasis-900); } +/* Light theme page title */ +[data-theme="light"] .leaderboard-page-title { + color: #1a202c !important; +} + +[data-theme="light"] .leaderboard-page-subtitle { + color: #4a5568 !important; +} + .leaderboard-page-title .highlight { background: linear-gradient(135deg, #ffd700, #ff8c00); -webkit-background-clip: text; @@ -2298,6 +2307,32 @@ color: var(--ifm-font-color-base); } +/* Light theme loading and error states */ +[data-theme="light"] .loading-container { + background: #ffffff; + border: 1px solid #e2e8f0; + color: #1a202c; +} + +[data-theme="light"] .loading-text { + color: #4a5568 !important; +} + +[data-theme="light"] .error-container { + background: #fef2f2; + border: 1px solid #fecaca; + color: #1a202c; +} + +[data-theme="light"] .error-container h3 { + color: #dc2626 !important; +} + +[data-theme="light"] .error-container p, +[data-theme="light"] .error-help { + color: #374151 !important; +} + .retry-button { background: var(--ifm-color-danger); color: white; @@ -2346,6 +2381,21 @@ font-weight: 500; } +/* Light theme leaderboard stats */ +[data-theme="light"] .leaderboard-stats { + background: #ffffff; + border: 1px solid #e2e8f0; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); +} + +[data-theme="light"] .leaderboard-stats .stat-number { + color: var(--ifm-color-primary) !important; +} + +[data-theme="light"] .leaderboard-stats .stat-label { + color: #4a5568 !important; +} + /* Leaderboard Grid */ .leaderboard-grid { display: grid; @@ -2362,6 +2412,20 @@ transition: all 0.3s ease; position: relative; overflow: hidden; + color: var(--ifm-font-color-base); +} + +/* Light theme specific styles */ +[data-theme="light"] .leaderboard-item { + background: #ffffff; + border: 1px solid #e2e8f0; + color: #1a202c; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); +} + +[data-theme="light"] .leaderboard-item:hover { + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); + border-color: var(--ifm-color-primary); } .leaderboard-item::before { @@ -2462,6 +2526,19 @@ font-style: italic; } +/* Light theme text visibility fixes */ +[data-theme="light"] .user-name { + color: #1a202c !important; +} + +[data-theme="light"] .user-username { + color: #4a5568 !important; +} + +[data-theme="light"] .leaderboard-item .user-info { + color: #1a202c; +} + /* Score Display */ .score-display { margin-bottom: 1.5rem; @@ -2481,6 +2558,15 @@ letter-spacing: 0.5px; } +/* Light theme score visibility */ +[data-theme="light"] .score-number { + color: var(--ifm-color-primary) !important; +} + +[data-theme="light"] .score-label { + color: #4a5568 !important; +} + /* User Stats */ .user-stats { display: grid; @@ -2512,6 +2598,20 @@ letter-spacing: 0.5px; } +/* Light theme stats visibility */ +[data-theme="light"] .user-stats .stat { + background: #f7fafc; + border: 1px solid #e2e8f0; +} + +[data-theme="light"] .stat-value { + color: var(--ifm-color-primary) !important; +} + +[data-theme="light"] .stat-text { + color: #4a5568 !important; +} + /* Achievements */ .achievements { display: flex; @@ -2532,6 +2632,13 @@ white-space: nowrap; } +/* Light theme achievement tags */ +[data-theme="light"] .achievement-tag { + background: #e6fffa; + color: #234e52; + border: 1px solid #81e6d9; +} + /* Actions Section */ .actions-section { text-align: center; @@ -2579,6 +2686,21 @@ margin-bottom: 0; } +/* Light theme empty state */ +[data-theme="light"] .empty-state { + background: #ffffff; + border: 1px solid #e2e8f0; + color: #4a5568; +} + +[data-theme="light"] .empty-state h3 { + color: #1a202c !important; +} + +[data-theme="light"] .empty-state p { + color: #4a5568 !important; +} + /* Responsive Design */ @media (max-width: 768px) { .leaderboard-page-title { @@ -3230,6 +3352,21 @@ margin: 1rem 0; } +/* Light theme rate limit warning */ +[data-theme="light"] .rate-limit-warning { + background: #fef3c7; + border: 1px solid #f59e0b; +} + +[data-theme="light"] .rate-limit-warning h4, +[data-theme="light"] .rate-limit-warning p { + color: #92400e !important; +} + +[data-theme="light"] .rate-limit-timer { + color: #dc2626 !important; +} + @media (max-width: 768px) { .leaderboard-header-controls { flex-direction: column; @@ -3251,3 +3388,295 @@ opacity: 0.6; pointer-events: none; } + +/* Light theme comprehensive fixes */ +[data-theme="light"] .leaderboard-page-container { + color: #1a202c; +} + +[data-theme="light"] .leaderboard-content { + color: #1a202c; +} + +[data-theme="light"] .leaderboard-item * { + color: inherit; +} + +[data-theme="light"] .leaderboard-item .user-info * { + color: inherit; +} + +/* Ensure all text in leaderboard is visible in light theme */ +[data-theme="light"] .leaderboard-item, +[data-theme="light"] .leaderboard-item .user-info, +[data-theme="light"] .leaderboard-item .user-stats, +[data-theme="light"] .leaderboard-item .achievements { + color: #1a202c !important; +} + +[data-theme="light"] .leaderboard-item .user-name, +[data-theme="light"] .leaderboard-item .user-username, +[data-theme="light"] .leaderboard-item .stat-text { + color: inherit !important; +} + +/* Force visibility for all leaderboard text elements */ +[data-theme="light"] .leaderboard-page-container * { + color: inherit; +} + +[data-theme="light"] .leaderboard-page-container h1, +[data-theme="light"] .leaderboard-page-container h2, +[data-theme="light"] .leaderboard-page-container h3, +[data-theme="light"] .leaderboard-page-container h4, +[data-theme="light"] .leaderboard-page-container p { + color: #1a202c !important; +} + +/* Keep giveaway page text white in light theme, but table text black */ +[data-theme="light"] + .min-h-screen.bg-gradient-to-br + *:not(table):not(th):not(td) { + color: white !important; +} +[data-theme="light"] .min-h-screen.bg-gradient-to-br table th, +[data-theme="light"] .min-h-screen.bg-gradient-to-br table td { + color: black !important; +} + +/* ===== CONTRIBUTORS PAGE STYLING ===== */ + +.contributors-page-container { + max-width: 1200px; + margin: 0 auto; + padding: 2rem; +} + +.contributors-hero .hero-content { + text-align: center; + margin-bottom: 3rem; +} + +.contributors-content { + margin-top: 3rem; +} + +.contributors-header { + text-align: center; + margin-bottom: 3rem; +} + +.contributors-header h2 { + font-size: 2.5rem; + font-weight: 700; + color: var(--ifm-color-emphasis-900); + margin-bottom: 1rem; +} + +.contributors-header p { + font-size: 1.2rem; + color: var(--ifm-color-emphasis-600); +} + +.contributors-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 2rem; + margin-top: 2rem; +} + +.contributor-card { + background: var(--ifm-card-background-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 12px; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); +} + +.contributor-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); + border-color: var(--ifm-color-primary); +} + +.contributor-avatar { + width: 80px; + height: 80px; + border-radius: 50%; + margin-bottom: 1rem; + border: 3px solid var(--ifm-color-primary-light); +} + +.contributor-avatar.placeholder { + background: var(--ifm-color-primary-lightest); + display: flex; + align-items: center; + justify-content: center; + font-size: 2rem; + color: var(--ifm-color-primary); + margin: 0 auto 1rem; +} + +.contributor-card h3 { + font-size: 1.25rem; + font-weight: 600; + color: var(--ifm-color-emphasis-900); + margin-bottom: 0.5rem; +} + +.contributor-card p { + color: var(--ifm-color-emphasis-600); + margin-bottom: 1rem; + font-size: 0.9rem; +} + +.contributor-stats { + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 0.5rem; +} + +.contributor-stats span { + background: var(--ifm-color-primary-lightest); + color: var(--ifm-color-primary-darker); + padding: 0.25rem 0.75rem; + border-radius: 20px; + font-size: 0.8rem; + font-weight: 500; +} + +/* Dark theme support for contributors */ +[data-theme="dark"] .contributor-card { + background: var(--ifm-background-surface-color); + border-color: var(--ifm-color-emphasis-300); +} + +[data-theme="dark"] .contributor-avatar.placeholder { + background: var(--ifm-color-primary-darkest); +} + +[data-theme="dark"] .contributor-stats span { + background: var(--ifm-color-primary-darkest); + color: var(--ifm-color-primary-lighter); +} + +/* Responsive design for contributors */ +@media (max-width: 768px) { + .contributors-page-container { + padding: 1rem; + } + + .contributors-grid { + grid-template-columns: 1fr; + gap: 1.5rem; + } + + .contributors-header h2 { + font-size: 2rem; + } +} + +/* Light theme github buttons */ +[data-theme="light"] .github-profile-btn, +[data-theme="light"] .github-link { + background: var(--ifm-color-primary); + color: white !important; +} + +[data-theme="light"] .github-profile-btn:hover, +[data-theme="light"] .github-link:hover { + background: var(--ifm-color-primary-darker); + color: white !important; + text-decoration: none; +} + +/* Light theme refresh button */ +[data-theme="light"] .refresh-button { + background: var(--ifm-color-primary); + color: white !important; +} + +[data-theme="light"] .refresh-button:hover:not(:disabled) { + background: var(--ifm-color-primary-darker); + color: white !important; +} + +/* Light theme rate limit status */ +[data-theme="light"] .rate-limit-status { + color: #4a5568 !important; +} + +/* ===== COMPREHENSIVE LIGHT THEME LEADERBOARD FIXES ===== */ + +/* Force all leaderboard text to be visible in light theme */ +[data-theme="light"] .leaderboard-page-container, +[data-theme="light"] .leaderboard-page-container *, +[data-theme="light"] .leaderboard-content, +[data-theme="light"] .leaderboard-content *, +[data-theme="light"] .leaderboard-grid, +[data-theme="light"] .leaderboard-grid *, +[data-theme="light"] .leaderboard-item, +[data-theme="light"] .leaderboard-item * { + color: #1a202c !important; +} + +/* Override specific elements that need different colors */ +[data-theme="light"] .score-display, +[data-theme="light"] .score-display * { + color: white !important; +} + +[data-theme="light"] .rank-badge, +[data-theme="light"] .rank-badge * { + color: white !important; +} + +[data-theme="light"] .github-profile-btn, +[data-theme="light"] .github-profile-btn *, +[data-theme="light"] .github-link, +[data-theme="light"] .github-link * { + color: white !important; +} + +[data-theme="light"] .refresh-button, +[data-theme="light"] .refresh-button * { + color: white !important; +} + +/* Ensure primary colored elements remain visible */ +[data-theme="light"] .stat-value, +[data-theme="light"] .score-number { + color: var(--ifm-color-primary) !important; +} + +/* Fix any remaining invisible text */ +[data-theme="light"] .leaderboard-page-header *, +[data-theme="light"] .leaderboard-stats *, +[data-theme="light"] .user-info *, +[data-theme="light"] .user-stats *, +[data-theme="light"] .achievements * { + color: inherit !important; +} + +/* Ensure proper contrast for all interactive elements */ +[data-theme="light"] .filter-button { + color: var(--ifm-color-primary) !important; + border-color: var(--ifm-color-primary) !important; +} + +[data-theme="light"] .filter-button.active { + background: var(--ifm-color-primary) !important; + color: white !important; +} + +/* Final fallback for any missed elements */ +[data-theme="light"] .dashboard-main * { + color: inherit; +} + +[data-theme="light"] .dashboard-main { + color: #1a202c; +} diff --git a/src/pages/dashboard/giveaway/index.tsx b/src/pages/dashboard/giveaway/index.tsx index 038e6d6b..be38eb3d 100644 --- a/src/pages/dashboard/giveaway/index.tsx +++ b/src/pages/dashboard/giveaway/index.tsx @@ -1,98 +1,79 @@ -import React, { useEffect, useState } from 'react'; -import Layout from '@theme/Layout'; -import Head from '@docusaurus/Head'; +import React, { useState } from "react"; +import Layout from "@theme/Layout"; +import Head from "@docusaurus/Head"; +import { motion } from "framer-motion"; +import SlotCounter from "react-slot-counter"; import NavbarIcon from "../../../components/navbar/NavbarIcon"; import { useHistory } from "@docusaurus/router"; -import type confettiType from 'canvas-confetti'; import "../dashboard.css"; const GiveawayPage: React.FC = () => { const history = useHistory(); const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false); const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false); - const [timeLeft, setTimeLeft] = useState({ - days: "--", - hours: "--", - minutes: "--", - seconds: "--", - }); - const countdownTarget = new Date('2025-08-15T23:59:59').getTime(); - - // Countdown Timer Effect - useEffect(() => { - const interval = setInterval(() => { - const now = new Date().getTime(); - const distance = countdownTarget - now; - - if (distance <= 0) { - clearInterval(interval); - setTimeLeft({ - days: "00", - hours: "00", - minutes: "00", - seconds: "00", - }); - return; - } - - setTimeLeft({ - days: String(Math.floor(distance / (1000 * 60 * 60 * 24))), - hours: String( - Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) - ), - minutes: String( - Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) - ), - seconds: String(Math.floor((distance % (1000 * 60)) / 1000)), - }); - }, 1000); - - return () => clearInterval(interval); - }, []); - - // Confetti Effect - useEffect(() => { - const runConfetti = async () => { - const module = await import("canvas-confetti"); - const confetti = module.default as typeof confettiType; - - confetti({ - particleCount: 150, - spread: 70, - origin: { y: 0.6 }, - }); - }; - - const timer = setTimeout(runConfetti, 1000); - - return () => clearTimeout(timer); - }, []); - - const handleTabChange = (tab: "home" | "discuss" | "leaderboard" | "giveaway") => { + const handleTabChange = ( + tab: "home" | "discuss" | "leaderboard" | "contributors" | "giveaway" + ) => { setIsMobileSidebarOpen(false); if (tab === "discuss") { history.push("/dashboard#discuss"); } else if (tab === "leaderboard") { history.push("/dashboard#leaderboard"); + } else if (tab === "contributors") { + history.push("/dashboard#contributors"); } else if (tab === "home") { history.push("/dashboard"); } }; + const StatCard: React.FC<{ + icon: string; + title: string; + value: number; + valueText: string; + description: string; + }> = ({ icon, title, value, valueText, description }) => ( + +
{icon}
+
+

{title}

+
+ +
+

{description}

+
+
+ ); + return ( 🎁 RecodeHive Giveaway -
+
{/* Mobile Menu Button */} -
    -
  • handleTabChange("home")} - > +
  • handleTabChange("home")}> Home
  • -
  • handleTabChange("discuss")} - > +
  • handleTabChange("discuss")}> @@ -141,14 +116,21 @@ const GiveawayPage: React.FC = () => { Leaderboard
  • -
  • +
  • Giveaway
  • +
  • handleTabChange("contributors")} + > + + + + Contributors +
- {rateLimitInfo.remaining && ( -

- API calls remaining: {rateLimitInfo.remaining}/ - {rateLimitInfo.limit} -

- )} -
- - {/* Filter Buttons positioned to the right */} - +
+

+ Community Dashboard +

+

+ Track our community's growth, celebrate top contributors, + and explore project statistics +

- - - {/* Rate Limit Warning */} - + - {/* Loading State */} - {isLoadingLeaderboard && ( - -
-

- Fetching latest contributor data... -

-
- )} + {/* Stats Grid */} + +
+ + + + +
+
- {/* Error State */} - {leaderboardError && !isLoadingLeaderboard && ( - -
⚠️
-

Unable to Load Latest Data

-

{leaderboardError}

- {!rateLimitInfo.isLimited && ( - - )} -

- Showing cached data below. The leaderboard will - automatically refresh when possible. + {/* Leaderboard Section */} + +

+

+ 🏆 Top Contributors{" "} + Leaderboard +

+

+ Celebrating our most active community members who make + RecodeHive awesome!

- - )} +
- {/* Leaderboard Content */} - {!isLoadingLeaderboard && filteredLeaderboardData.length > 0 && ( - -
-
- - {filteredLeaderboardData.length} - - Participants -
-
- - {getContributionCount( - filteredLeaderboardData[0], - filterPeriod - ) || 0} - - - Top{" "} - {filterPeriod.charAt(0).toUpperCase() + - filterPeriod.slice(1)} - -
-
- - {Math.round( - filteredLeaderboardData.reduce( - (acc, user) => - acc + getContributionCount(user, filterPeriod), - 0 - ) / filteredLeaderboardData.length - )} - - - Avg{" "} - {filterPeriod.charAt(0).toUpperCase() + - filterPeriod.slice(1)} - +
+ {error && ( +
+

⚠️ Some data may be cached or incomplete

-
- -
- {filteredLeaderboardData.map((entry, index) => ( - - {/* Streak Display */} - {entry.streak && entry.streak > 1 && ( -
- {entry.streak} Day Streak -
- )} + )} -
-
- #{entry.rank} -
-
- -
- {entry.name} -
- -
-

{entry.name}

- {entry.username && entry.username !== entry.name && ( -

@{entry.username}

- )} - -
- - {getContributionCount(entry, filterPeriod)} - - - {filterPeriod === "weekly" - ? "this week" - : filterPeriod === "monthly" - ? "this month" - : "total"} - -
- -
-
- - {entry.contributions} - - Total PRs -
-
- - {entry.repositories} - - Repos -
-
- - {entry.achievements.length > 0 && ( -
- {entry.achievements.map((achievement, i) => ( - - {achievement} - - ))} -
- )} -
- - -
- ))} -
- - )} - - {/* Empty State */} - {!isLoadingLeaderboard && - !leaderboardError && - filteredLeaderboardData.length === 0 && ( - -

📊 No data available

-

The leaderboard is empty. Check back later!

-
- )} -
- ) : activeTab === "home" ? ( - // Home tab content -
- -
-

- Community Dashboard -

-

- Track our community's growth, celebrate top contributors, - and explore project statistics -

-
-
- - {/* Stats Grid */} - -
- - - - -
-
- - {/* Leaderboard Section */} - -
-

- 🏆 Top Contributors{" "} - Leaderboard -

-

- Celebrating our most active community members who make - RecodeHive awesome! -

-
- -
- {error && ( -
-

⚠️ Some data may be cached or incomplete

-
- )} - - {dashboardStats.topContributors.map((entry, index) => ( - - ))} -
-
+ {dashboardStats.topContributors.map((entry, index) => ( + + ))} +
+ {/* Call to Action */} { animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.6 }} > -
-

- Community Discussions +
+

+ Community{" "} + + Discussions +

-

- Join the conversation, ask questions, and share your thoughts with the RecodeHive community. +

+ Join the conversation, ask questions, and share your thoughts + with the RecodeHive community.

@@ -1440,7 +1275,11 @@ const DashboardContent: React.FC = () => { />

- @@ -1505,7 +1344,8 @@ const DashboardContent: React.FC = () => { { transition={{ duration: 1 }} > {/* Animated Background Elements */} -
+
{[...Array(6)].map((_, i) => ( { > Ready to Join the Conversation? - + { animate={{ opacity: 0.95 }} transition={{ duration: 0.8, delay: 0.4 }} > - Share your thoughts, ask questions, or help others in our community. + Share your thoughts, ask questions, or help others in our + community. -
+
{[ - { emoji: "❓", text: "Ask a Question", url: "https://github.com/recodehive/recode-website/discussions/new?category=q-a", gradient: "linear-gradient(135deg, #ff6b6b, #ff8e8e)", shadow: "#ff6b6b" }, - { emoji: "💡", text: "Share an Idea", url: "https://github.com/recodehive/recode-website/discussions/new?category=ideas", gradient: "linear-gradient(135deg, #4ecdc4, #44a08d)", shadow: "#4ecdc4" }, - { emoji: "🎉", text: "Show Your Work", url: "https://github.com/recodehive/recode-website/discussions/new?category=show-and-tell", gradient: "linear-gradient(135deg, #45b7d1, #96c93d)", shadow: "#45b7d1" } + { + emoji: "❓", + text: "Ask a Question", + url: "https://github.com/recodehive/recode-website/discussions/new?category=q-a", + gradient: "linear-gradient(135deg, #ff6b6b, #ff8e8e)", + shadow: "#ff6b6b", + }, + { + emoji: "💡", + text: "Share an Idea", + url: "https://github.com/recodehive/recode-website/discussions/new?category=ideas", + gradient: "linear-gradient(135deg, #4ecdc4, #44a08d)", + shadow: "#4ecdc4", + }, + { + emoji: "🎉", + text: "Show Your Work", + url: "https://github.com/recodehive/recode-website/discussions/new?category=show-and-tell", + gradient: "linear-gradient(135deg, #45b7d1, #96c93d)", + shadow: "#45b7d1", + }, ].map((item, index) => ( { }} initial={{ opacity: 0, y: 50, rotateX: 45 }} animate={{ opacity: 1, y: 0, rotateX: 0 }} - transition={{ duration: 0.8, delay: 0.6 + index * 0.2 }} + transition={{ + duration: 0.8, + delay: 0.6 + index * 0.2, + }} > { whileHover={{ opacity: 0.1 }} transition={{ duration: 0.3 }} /> - + {/* Floating particles */} -
+
{[...Array(3)].map((_, i) => ( { fontSize: "3rem", position: "relative", zIndex: 2, - filter: "drop-shadow(0 4px 8px rgba(0,0,0,0.2))", + filter: + "drop-shadow(0 4px 8px rgba(0,0,0,0.2))", }} animate={{ rotate: [0, 5, -5, 0], @@ -1728,11 +1619,12 @@ const DashboardContent: React.FC = () => { left: "-100%", width: "100%", height: "100%", - background: "linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent)", + background: + "linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent)", borderRadius: "24px", }} animate={{ - left: ['-100%', '100%'], + left: ["-100%", "100%"], }} transition={{ duration: 3, @@ -1767,73 +1659,283 @@ const DashboardContent: React.FC = () => { animate={{ opacity: [0.7, 1, 0.7] }} transition={{ duration: 3, repeat: Infinity }} > - Join thousands of developers sharing knowledge and building together 🚀 + Join thousands of developers sharing knowledge and + building together 🚀 )} - ) : ( - // Giveaway tab content -
- + -
-

- 🎁 Giveaway -

-

- Participate in exclusive giveaways and win exciting prizes! -

-
-
- - {/* Giveaway Stats Grid */} - + 🎁 Giveaway + + +
+ ) : activeTab === "contributors" ? ( + /* Contributors Tab - Shows the list of contributors */ +
+ -
- - - - +

+ 👥 RecodeHive Contributors +

+

+ Live rankings from RecodeHive GitHub Organization • Updated + automatically +

+ + {/* Header Controls: Refresh Button + Filter Buttons */} +
+
+ + {rateLimitInfo.remaining && ( +

+ API calls remaining: {rateLimitInfo.remaining}/ + {rateLimitInfo.limit} +

+ )} +
+ + {/* Filter Buttons positioned to the right */} +
- + + + {/* Rate Limit Warning */} + + + {/* Loading State */} + {isLoadingLeaderboard && ( + +
+

+ Fetching latest contributor data... +

+
+ )} + + {/* Error State */} + {leaderboardError && !isLoadingLeaderboard && ( + +
⚠️
+

Unable to Load Latest Data

+

{leaderboardError}

+ {!rateLimitInfo.isLimited && ( + + )} +

+ Showing cached data below. The leaderboard will + automatically refresh when possible. +

+
+ )} + + {/* Contributors Content */} + {!isLoadingLeaderboard && filteredLeaderboardData.length > 0 && ( + +
+
+ + {filteredLeaderboardData.length} + + Contributors +
+
+ + {getContributionCount( + filteredLeaderboardData[0], + filterPeriod + ) || 0} + + + Top{" "} + {filterPeriod.charAt(0).toUpperCase() + + filterPeriod.slice(1)} + +
+
+ + {Math.round( + filteredLeaderboardData.reduce( + (acc, user) => + acc + getContributionCount(user, filterPeriod), + 0 + ) / filteredLeaderboardData.length + )} + + + Avg{" "} + {filterPeriod.charAt(0).toUpperCase() + + filterPeriod.slice(1)} + +
+
+ +
+ {filteredLeaderboardData.map((entry, index) => ( + + {/* Streak Display */} + {entry.streak && entry.streak > 1 && ( +
+ {entry.streak} Day Streak +
+ )} + +
+
+ #{entry.rank} +
+
+ +
+ {entry.name} +
+ +
+

{entry.name}

+ {entry.username && entry.username !== entry.name && ( +

@{entry.username}

+ )} + +
+ + {getContributionCount(entry, filterPeriod)} + + + {filterPeriod === "weekly" + ? "this week" + : filterPeriod === "monthly" + ? "this month" + : "total"} + +
+ +
+
+ + {entry.contributions} + + Total PRs +
+
+ + {entry.repositories} + + Repos +
+
+ + {entry.achievements.length > 0 && ( +
+ {entry.achievements.map((achievement, i) => ( + + {achievement} + + ))} +
+ )} +
+ + +
+ ))} +
+
+ )} + + {/* Empty State */} + {!isLoadingLeaderboard && + !leaderboardError && + filteredLeaderboardData.length === 0 && ( + +

📊 No data available

+

No contributors found. Check back later!

+
+ )}
- )} + ) : null}
diff --git a/src/theme/ColorModeToggle/index.tsx b/src/theme/ColorModeToggle/index.tsx index 65b0c9d8..35f09a56 100644 --- a/src/theme/ColorModeToggle/index.tsx +++ b/src/theme/ColorModeToggle/index.tsx @@ -6,28 +6,8 @@ export default function ColorModeToggle(): JSX.Element { const toggleColorMode = () => { const newMode = colorMode === 'dark' ? 'light' : 'dark'; - - // INSTANT theme change - update all elements immediately - document.documentElement.setAttribute('data-theme', newMode); - document.body.setAttribute('data-theme', newMode); - document.body.className = document.body.className.replace(/theme-\w+/g, '') + ` theme-${newMode}`; - - // Force immediate CSS variable updates - if (newMode === 'light') { - document.documentElement.style.setProperty('--ifm-background-color', '#ffffff'); - document.documentElement.style.setProperty('--ifm-font-color-base', '#1a202c'); - document.body.style.backgroundColor = '#ffffff'; - document.body.style.color = '#1a202c'; - } else { - document.documentElement.style.setProperty('--ifm-background-color', '#121212'); - document.documentElement.style.setProperty('--ifm-font-color-base', '#ffffff'); - document.body.style.backgroundColor = '#121212'; - document.body.style.color = '#ffffff'; - } - - // Update Docusaurus state (this can be slower) + // Only use Docusaurus's setColorMode - it handles everything properly setColorMode(newMode); - localStorage.setItem('theme', newMode); }; return ( diff --git a/src/theme/Navbar/Content/index.tsx b/src/theme/Navbar/Content/index.tsx index f8ebe925..94d59d46 100644 --- a/src/theme/Navbar/Content/index.tsx +++ b/src/theme/Navbar/Content/index.tsx @@ -1,4 +1,4 @@ -import React, {type ReactNode} from 'react'; +import React, {type ReactNode, useMemo} from 'react'; import {useThemeConfig, ErrorCauseBoundary} from '@docusaurus/theme-common'; import { splitNavbarItems, @@ -14,27 +14,29 @@ import NavbarSearch from '@theme/Navbar/Search'; import styles from './styles.module.css'; function useNavbarItems() { - // TODO temporary casting until ThemeConfig type is improved return useThemeConfig().navbar.items as NavbarItemConfig[]; } function NavbarItems({items}: {items: NavbarItemConfig[]}): ReactNode { return ( <> - {items.map((item, i) => ( - - new Error( - `A theme navbar item failed to render. + {items.map((item, i) => { + const key = `${item.label || item.to || item.href || 'item'}-${i}`; + return ( + + new Error( + `A theme navbar item failed to render. Please double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config: ${JSON.stringify(item, null, 2)}`, - {cause: error}, - ) - }> - - - ))} + {cause: error}, + ) + }> + + + ); + })} ); } @@ -56,11 +58,10 @@ function NavbarContentLayout({ export default function NavbarContent(): ReactNode { const mobileSidebar = useNavbarMobileSidebar(); - const items = useNavbarItems(); - const [leftItems, rightItems] = splitNavbarItems(items); - - const searchBarItem = items.find((item) => item.type === 'search'); + + const [leftItems, rightItems] = useMemo(() => splitNavbarItems(items), [items]); + const searchBarItem = useMemo(() => items.find((item) => item.type === 'search'), [items]); return ( ; -} +// This file can be removed as it's just a pass-through wrapper +// Docusaurus will use the original NavbarItem component directly +export { default } from "@theme-original/NavbarItem"; \ No newline at end of file diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index dc237b3d..503d8b3a 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -1,17 +1,8 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { Analytics } from '@vercel/analytics/react'; // Default implementation, that you can customize export default function Root({children}) { - useEffect(() => { - // Ensure theme is properly set on client-side hydration - const savedTheme = localStorage.getItem('theme'); - // Force light as default, ignore system preference unless user has manually set a preference - const theme = savedTheme || 'light'; - - document.documentElement.setAttribute('data-theme', theme); - }, []); - return ( <> {children} diff --git a/src/utils/navbarUtils.ts b/src/utils/navbarUtils.ts new file mode 100644 index 00000000..e5955f84 --- /dev/null +++ b/src/utils/navbarUtils.ts @@ -0,0 +1,21 @@ +import { type NavbarIconName } from "../constants/navbarConfig"; + +/** + * Generates HTML string for navbar items with icons + * @param iconName - The name of the icon from NAVBAR_CONFIG + * @param label - The text label for the navbar item + * @returns HTML string with icon placeholder and label + */ +export function createNavbarItemHTML(iconName: NavbarIconName, label: string): string { + return ` ${label}`; +} + +/** + * Generates HTML string for simple navbar items with icons (no inline styles) + * @param iconName - The name of the icon from NAVBAR_CONFIG + * @param label - The text label for the navbar item + * @returns HTML string with icon placeholder and label + */ +export function createSimpleNavbarItemHTML(iconName: NavbarIconName, label: string): string { + return ` ${label}`; +} \ No newline at end of file diff --git a/static/instant-theme.js b/static/instant-theme.js new file mode 100644 index 00000000..b9d99e8c --- /dev/null +++ b/static/instant-theme.js @@ -0,0 +1,15 @@ +(function() { + 'use strict'; + + // Simple theme flash prevention - let Docusaurus handle the rest + function preventFlash() { + // Check Docusaurus's preferred storage key first + const docusaurusTheme = localStorage.getItem('theme'); + if (docusaurusTheme) { + document.documentElement.setAttribute('data-theme', docusaurusTheme); + } + } + + // Only prevent flash, don't override Docusaurus + preventFlash(); +})(); \ No newline at end of file diff --git a/static/theme-init.js b/static/theme-init.js index 7c3316f9..2af421dc 100644 --- a/static/theme-init.js +++ b/static/theme-init.js @@ -1,83 +1,21 @@ -// Theme initialization script +// Minimal theme initialization - let Docusaurus handle theme management (function() { 'use strict'; - // Function to set theme INSTANTLY - function setTheme(theme) { - // Immediate DOM updates - document.documentElement.setAttribute('data-theme', theme); - document.body.setAttribute('data-theme', theme); - document.body.className = document.body.className.replace(/theme-\w+/g, '') + ` theme-${theme}`; - - // Force immediate CSS variable updates - if (theme === 'light') { - document.documentElement.style.setProperty('--ifm-background-color', '#ffffff'); - document.documentElement.style.setProperty('--ifm-font-color-base', '#1a202c'); - document.body.style.backgroundColor = '#ffffff'; - document.body.style.color = '#1a202c'; - } else { - document.documentElement.style.setProperty('--ifm-background-color', '#121212'); - document.documentElement.style.setProperty('--ifm-font-color-base', '#ffffff'); - document.body.style.backgroundColor = '#121212'; - document.body.style.color = '#ffffff'; - } - - localStorage.setItem('theme', theme); - } - - // Function to get system preference - function getSystemTheme() { - return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; - } - - // Initialize theme - FORCE LIGHT FIRST TIME - function initializeTheme() { + // Only set default theme if none exists, then let Docusaurus take over + function initializeDefaultTheme() { try { - // Clear any existing theme to force light + // Only set default if no theme preference exists if (!localStorage.getItem('theme')) { - localStorage.removeItem('theme'); + localStorage.setItem('theme', 'light'); + document.documentElement.setAttribute('data-theme', 'light'); } - - const savedTheme = localStorage.getItem('theme'); - const theme = savedTheme || 'light'; - - // Force set the theme - document.documentElement.setAttribute('data-theme', theme); - document.body.setAttribute('data-theme', theme); - localStorage.setItem('theme', theme); - - console.log('🌞 Theme initialized:', theme); } catch (error) { + // Fallback to light theme document.documentElement.setAttribute('data-theme', 'light'); - document.body.setAttribute('data-theme', 'light'); } } - // Listen for system theme changes - function setupSystemThemeListener() { - try { - const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); - mediaQuery.addEventListener('change', function(e) { - // Only update if no manual theme preference is saved - if (!localStorage.getItem('theme')) { - const newTheme = e.matches ? 'dark' : 'light'; - setTheme(newTheme); - console.log('🌙 System theme changed to:', newTheme); - } - }); - } catch (error) { - console.warn('Failed to setup system theme listener:', error); - } - } - - // Run immediately if DOM is ready, otherwise wait - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', function() { - initializeTheme(); - setupSystemThemeListener(); - }); - } else { - initializeTheme(); - setupSystemThemeListener(); - } + // Run once to set default, then let Docusaurus handle everything + initializeDefaultTheme(); })();