From b6f0bd1d692406544f991ae820df692e7deef6cd Mon Sep 17 00:00:00 2001 From: gbanyan Date: Thu, 20 Nov 2025 02:46:54 +0800 Subject: [PATCH] Fix search modal z-index and improve text readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use React Portal to render modal at document body level to avoid stacking context issues - Increase z-index to z-[9999] to ensure modal appears on top of all content - Add cleanup function to prevent duplicate Pagefind initializations - Replace CSS class overrides with CSS variables for better maintainability - Enhance search result text colors for improved readability in both light and dark modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- components/search-modal.tsx | 33 ++++++++++++++++--- styles/globals.css | 66 ++++++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 32 deletions(-) diff --git a/components/search-modal.tsx b/components/search-modal.tsx index 4b3303b..54ea09d 100644 --- a/components/search-modal.tsx +++ b/components/search-modal.tsx @@ -1,6 +1,7 @@ 'use client'; import { useEffect, useRef, useState } from 'react'; +import { createPortal } from 'react-dom'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faMagnifyingGlass, faXmark } from '@fortawesome/free-solid-svg-icons'; @@ -17,6 +18,9 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) { useEffect(() => { if (!isOpen) return; + let link: HTMLLinkElement | null = null; + let script: HTMLScriptElement | null = null; + // Load Pagefind UI dynamically when modal opens const loadPagefind = async () => { if (pagefindUIRef.current) { @@ -26,18 +30,19 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) { try { // Load Pagefind UI CSS - const link = document.createElement('link'); + link = document.createElement('link'); link.rel = 'stylesheet'; link.href = '/pagefind/pagefind-ui.css'; document.head.appendChild(link); // Load Pagefind UI JS - const script = document.createElement('script'); + script = document.createElement('script'); script.src = '/pagefind/pagefind-ui.js'; script.onload = () => { if (searchContainerRef.current && (window as any).PagefindUI) { pagefindUIRef.current = new (window as any).PagefindUI({ element: searchContainerRef.current, + bundlePath: '/pagefind/', showSubResults: true, showImages: false, excerptLength: 15, @@ -75,6 +80,20 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) { }; loadPagefind(); + + // Cleanup function to prevent duplicate initializations + return () => { + if (link && link.parentNode) { + link.parentNode.removeChild(link); + } + if (script && script.parentNode) { + script.parentNode.removeChild(script); + } + if (pagefindUIRef.current && pagefindUIRef.current.destroy) { + pagefindUIRef.current.destroy(); + pagefindUIRef.current = null; + } + }; }, [isOpen]); useEffect(() => { @@ -102,9 +121,12 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) { if (!isOpen) return null; - return ( + // Use portal to render modal at document body level to avoid z-index stacking context issues + if (typeof window === 'undefined') return null; + + return createPortal(
- + , + document.body ); } diff --git a/styles/globals.css b/styles/globals.css index 91fef2e..a0c7c9a 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -267,47 +267,59 @@ body { } } -/* Pagefind Search Styles */ -.pagefind-ui__search-input { - @apply w-full rounded-lg border border-slate-200 bg-white px-4 py-3 text-slate-900 placeholder:text-slate-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100 dark:placeholder:text-slate-500 dark:focus:ring-blue-500; +/* Pagefind Search Styles - Use CSS variables to override defaults */ +:root { + --pagefind-ui-scale: 1; + --pagefind-ui-primary: #2563eb; + --pagefind-ui-text: #0f172a; + --pagefind-ui-background: #ffffff; + --pagefind-ui-border: #e2e8f0; + --pagefind-ui-tag: #f1f5f9; + --pagefind-ui-border-width: 1px; + --pagefind-ui-border-radius: 0.5rem; + --pagefind-ui-font: var(--font-system-sans); } -.pagefind-ui__search-clear { - @apply rounded-md px-2 py-1 text-sm text-slate-500 hover:bg-slate-100 hover:text-slate-700 dark:text-slate-400 dark:hover:bg-slate-700 dark:hover:text-slate-200; -} - -.pagefind-ui__results { - @apply space-y-4; -} - -.pagefind-ui__result { - @apply rounded-lg border border-slate-200 bg-white p-4 transition-all hover:border-blue-300 hover:shadow-md dark:border-slate-700 dark:bg-slate-800 dark:hover:border-blue-600; -} - -.pagefind-ui__result-link { - @apply text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300; - text-decoration: none; +.dark { + --pagefind-ui-primary: #60a5fa; + --pagefind-ui-text: #f1f5f9; + --pagefind-ui-background: #0f172a; + --pagefind-ui-border: #475569; + --pagefind-ui-tag: #334155; } +/* Enhanced text colors for better readability */ .pagefind-ui__result-title { - @apply mb-2 text-lg font-semibold text-slate-900 dark:text-slate-100; + color: var(--pagefind-ui-text) !important; +} + +.dark .pagefind-ui__result-title { + color: #f8fafc !important; } .pagefind-ui__result-excerpt { - @apply text-sm text-slate-600 dark:text-slate-300; + color: #475569 !important; } +.dark .pagefind-ui__result-excerpt { + color: #cbd5e1 !important; +} + +.pagefind-ui__result-link { + color: var(--pagefind-ui-primary) !important; +} + +.dark .pagefind-ui__result-link { + color: #93c5fd !important; +} + +/* Additional custom styling for highlights */ .pagefind-ui__result-excerpt mark { @apply bg-yellow-200 font-semibold text-slate-900 dark:bg-yellow-600 dark:text-slate-100; padding: 0.125rem 0.25rem; border-radius: 0.25rem; } -.pagefind-ui__message { - @apply text-center text-sm text-slate-500 dark:text-slate-400; - padding: 2rem 0; -} - -.pagefind-ui__button { - @apply rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-blue-500 dark:hover:bg-blue-600; +.pagefind-ui__search-input:focus { + @apply ring-2 ring-blue-500 dark:ring-blue-400; } \ No newline at end of file