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 290f5ede..9badb46a 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; +} + +/* 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; +} - /* Light theme defaults */ - --ifm-background-color: #ffffff; - --ifm-font-color-base: #000000; +/* 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; + } + + /* Only show essential elements in TOP navbar */ + .navbar__toggle, + .navbar__brand, + .navbar__search, + #firebase-auth-github-navbar, + .colorModeToggle { + display: flex !important; } - /* Layout for mobile navbar */ + /* 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,73 +1427,108 @@ 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; + } +} + + +.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; } .explore-btn:hover{ @@ -2083,4 +1598,5 @@ html { .company-tab-community-link:hover{ color: #fdba74; text-decoration: none; -} \ No newline at end of file +} + 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(); })();