.
This commit is contained in:
@@ -107,7 +107,7 @@ export default async function LocaleLayout({
|
||||
const messages = await getMessages({ locale });
|
||||
|
||||
return (
|
||||
<html lang={locale}>
|
||||
<html lang={locale} suppressHydrationWarning>
|
||||
<head>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
|
||||
@@ -4,15 +4,24 @@ import dynamic from 'next/dynamic';
|
||||
import type { DocsLocale } from '@/docs/navigation';
|
||||
import { defaultDocSlug } from '@/docs/registry';
|
||||
|
||||
// Loading component for MDX content
|
||||
const LoadingDocs = () => (
|
||||
<div style={{ padding: '2rem', textAlign: 'center' }}>
|
||||
<p>Loading documentation...</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const docsRegistry = {
|
||||
en: {
|
||||
'getting-started': dynamic(() => import('../../../content/docs/en/templates/README.md'), {
|
||||
ssr: false
|
||||
'getting-started': dynamic(() => import('../../../../../docs/en/templates/README.md'), {
|
||||
loading: () => <LoadingDocs />,
|
||||
ssr: true
|
||||
})
|
||||
},
|
||||
vi: {
|
||||
'getting-started': dynamic(() => import('../../../content/docs/vi/templates/README.md'), {
|
||||
ssr: false
|
||||
'getting-started': dynamic(() => import('../../../../../docs/vi/templates/README.md'), {
|
||||
loading: () => <LoadingDocs />,
|
||||
ssr: true
|
||||
})
|
||||
}
|
||||
} as const;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useState, useEffect, useRef, useMemo } from 'react';
|
||||
import { useRouter, usePathname } from 'next/navigation';
|
||||
import { Search, X, FileText } from 'lucide-react';
|
||||
import { docsNavigation } from '@/docs/navigation';
|
||||
@@ -23,7 +23,6 @@ type SearchResult = {
|
||||
export default function DocsSearch({ placeholder, locale = 'en' }: DocsSearchProps) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [query, setQuery] = useState('');
|
||||
const [results, setResults] = useState<SearchResult[]>([]);
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const router = useRouter();
|
||||
@@ -33,7 +32,7 @@ export default function DocsSearch({ placeholder, locale = 'en' }: DocsSearchPro
|
||||
const currentLocale = (pathname?.split('/')[1] as DocsLocale) || locale;
|
||||
|
||||
// Build search index from navigation
|
||||
const searchIndex: SearchResult[] = docsNavigation.flatMap(group =>
|
||||
const searchIndex: SearchResult[] = useMemo(() => docsNavigation.flatMap(group =>
|
||||
group.items.map(item => ({
|
||||
id: item.id,
|
||||
slug: item.slug,
|
||||
@@ -41,13 +40,12 @@ export default function DocsSearch({ placeholder, locale = 'en' }: DocsSearchPro
|
||||
category: group.label[currentLocale],
|
||||
href: `/${currentLocale}/docs/${item.slug}`
|
||||
}))
|
||||
);
|
||||
), [currentLocale]);
|
||||
|
||||
// Search function
|
||||
useEffect(() => {
|
||||
// Calculate search results using useMemo instead of useEffect
|
||||
const results = useMemo(() => {
|
||||
if (!query.trim()) {
|
||||
setResults([]);
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
const searchTerm = query.toLowerCase().trim();
|
||||
@@ -67,9 +65,8 @@ export default function DocsSearch({ placeholder, locale = 'en' }: DocsSearchPro
|
||||
return a.title.localeCompare(b.title);
|
||||
});
|
||||
|
||||
setResults(sorted.slice(0, 10)); // Limit to 10 results
|
||||
setSelectedIndex(0);
|
||||
}, [query, currentLocale]);
|
||||
return sorted.slice(0, 10); // Limit to 10 results
|
||||
}, [query, searchIndex]);
|
||||
|
||||
// Keyboard shortcuts
|
||||
useEffect(() => {
|
||||
@@ -149,7 +146,10 @@ export default function DocsSearch({ placeholder, locale = 'en' }: DocsSearchPro
|
||||
className={styles.searchInput}
|
||||
placeholder={placeholder ?? 'Search documentation…'}
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setQuery(e.target.value);
|
||||
setSelectedIndex(0); // Reset selected index when query changes
|
||||
}}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<button
|
||||
@@ -168,9 +168,8 @@ export default function DocsSearch({ placeholder, locale = 'en' }: DocsSearchPro
|
||||
{results.map((result, index) => (
|
||||
<li key={result.id}>
|
||||
<button
|
||||
className={`${styles.resultItem} ${
|
||||
index === selectedIndex ? styles.resultItemActive : ''
|
||||
}`}
|
||||
className={`${styles.resultItem} ${index === selectedIndex ? styles.resultItemActive : ''
|
||||
}`}
|
||||
onClick={() => handleSelect(result)}
|
||||
>
|
||||
<FileText size={16} className={styles.resultIcon} />
|
||||
|
||||
Reference in New Issue
Block a user