Fix search modal z-index and improve text readability
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faMagnifyingGlass, faXmark } from '@fortawesome/free-solid-svg-icons';
|
import { faMagnifyingGlass, faXmark } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
@@ -17,6 +18,9 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOpen) return;
|
if (!isOpen) return;
|
||||||
|
|
||||||
|
let link: HTMLLinkElement | null = null;
|
||||||
|
let script: HTMLScriptElement | null = null;
|
||||||
|
|
||||||
// Load Pagefind UI dynamically when modal opens
|
// Load Pagefind UI dynamically when modal opens
|
||||||
const loadPagefind = async () => {
|
const loadPagefind = async () => {
|
||||||
if (pagefindUIRef.current) {
|
if (pagefindUIRef.current) {
|
||||||
@@ -26,18 +30,19 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Load Pagefind UI CSS
|
// Load Pagefind UI CSS
|
||||||
const link = document.createElement('link');
|
link = document.createElement('link');
|
||||||
link.rel = 'stylesheet';
|
link.rel = 'stylesheet';
|
||||||
link.href = '/pagefind/pagefind-ui.css';
|
link.href = '/pagefind/pagefind-ui.css';
|
||||||
document.head.appendChild(link);
|
document.head.appendChild(link);
|
||||||
|
|
||||||
// Load Pagefind UI JS
|
// Load Pagefind UI JS
|
||||||
const script = document.createElement('script');
|
script = document.createElement('script');
|
||||||
script.src = '/pagefind/pagefind-ui.js';
|
script.src = '/pagefind/pagefind-ui.js';
|
||||||
script.onload = () => {
|
script.onload = () => {
|
||||||
if (searchContainerRef.current && (window as any).PagefindUI) {
|
if (searchContainerRef.current && (window as any).PagefindUI) {
|
||||||
pagefindUIRef.current = new (window as any).PagefindUI({
|
pagefindUIRef.current = new (window as any).PagefindUI({
|
||||||
element: searchContainerRef.current,
|
element: searchContainerRef.current,
|
||||||
|
bundlePath: '/pagefind/',
|
||||||
showSubResults: true,
|
showSubResults: true,
|
||||||
showImages: false,
|
showImages: false,
|
||||||
excerptLength: 15,
|
excerptLength: 15,
|
||||||
@@ -75,6 +80,20 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
loadPagefind();
|
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]);
|
}, [isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -102,9 +121,12 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
|
|||||||
|
|
||||||
if (!isOpen) return null;
|
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(
|
||||||
<div
|
<div
|
||||||
className="fixed inset-0 z-50 flex items-start justify-center bg-black/50 backdrop-blur-sm pt-20 px-4"
|
className="fixed inset-0 z-[9999] flex items-start justify-center bg-black/50 backdrop-blur-sm pt-20 px-4"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -153,7 +175,8 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
|
document.body
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,47 +267,59 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pagefind Search Styles */
|
/* Pagefind Search Styles - Use CSS variables to override defaults */
|
||||||
.pagefind-ui__search-input {
|
:root {
|
||||||
@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-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 {
|
.dark {
|
||||||
@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-primary: #60a5fa;
|
||||||
}
|
--pagefind-ui-text: #f1f5f9;
|
||||||
|
--pagefind-ui-background: #0f172a;
|
||||||
.pagefind-ui__results {
|
--pagefind-ui-border: #475569;
|
||||||
@apply space-y-4;
|
--pagefind-ui-tag: #334155;
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enhanced text colors for better readability */
|
||||||
.pagefind-ui__result-title {
|
.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 {
|
.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 {
|
.pagefind-ui__result-excerpt mark {
|
||||||
@apply bg-yellow-200 font-semibold text-slate-900 dark:bg-yellow-600 dark:text-slate-100;
|
@apply bg-yellow-200 font-semibold text-slate-900 dark:bg-yellow-600 dark:text-slate-100;
|
||||||
padding: 0.125rem 0.25rem;
|
padding: 0.125rem 0.25rem;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagefind-ui__message {
|
.pagefind-ui__search-input:focus {
|
||||||
@apply text-center text-sm text-slate-500 dark:text-slate-400;
|
@apply ring-2 ring-blue-500 dark:ring-blue-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;
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user