Merge pull request #7 from DocuBook/dev-7be3b3c

feat(search): implement algolia docsearch with new components and props
- add docsearch component and algolia search type
- update search component to handle different search types
- include algolia css and dependencies
- add environment variable configuration for algolia
- update changelog and version to 1.15.0
This commit is contained in:
Wildan Nursahidan
2025-08-06 02:24:14 +07:00
committed by GitHub
8 changed files with 244 additions and 23 deletions

View File

@@ -7,6 +7,7 @@ import { Footer } from "@/components/footer";
import docuConfig from "@/docu.json"; import docuConfig from "@/docu.json";
import { Toaster } from "@/components/ui/sonner"; import { Toaster } from "@/components/ui/sonner";
import "@/styles/globals.css"; import "@/styles/globals.css";
import "@/styles/algolia.css";
const { meta } = docuConfig; const { meta } = docuConfig;

View File

@@ -25,7 +25,7 @@ export default function Home() {
)} )}
> >
<AnimatedShinyText className="inline-flex items-center justify-center px-4 py-1 transition ease-out hover:text-neutral-100 hover:duration-300 hover:dark:text-neutral-200"> <AnimatedShinyText className="inline-flex items-center justify-center px-4 py-1 transition ease-out hover:text-neutral-100 hover:duration-300 hover:dark:text-neutral-200">
<span>🚀 New Version - Release v1.14.2</span> <span>🚀 New Version - Release v1.15.0</span>
<ArrowRightIcon className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" /> <ArrowRightIcon className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
</AnimatedShinyText> </AnimatedShinyText>
</div> </div>

33
components/DocSearch.tsx Normal file
View File

@@ -0,0 +1,33 @@
"use client";
import React from "react";
import { DocSearch } from "@docsearch/react";
import "@docsearch/css";
export default function DocSearchComponent() {
const appId = process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_APP_ID;
const apiKey = process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_API_KEY;
const indexName = process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_INDEX_NAME;
if (!appId || !apiKey || !indexName) {
console.error(
"DocSearch credentials are not set in the environment variables."
);
return (
<button className="text-sm text-muted-foreground" disabled>
Search... (misconfigured)
</button>
);
}
return (
<div className="docsearch">
<DocSearch
appId={appId}
apiKey={apiKey}
indexName={indexName}
placeholder="Type something to search..."
/>
</div>
);
}

View File

@@ -26,7 +26,7 @@ export function Navbar() {
<NavMenu /> <NavMenu />
</div> </div>
<Separator className="hidden lg:flex my-4 h-9" orientation="vertical" /> <Separator className="hidden lg:flex my-4 h-9" orientation="vertical" />
<Search /> <Search type="algolia" />
</div> </div>
</div> </div>
</nav> </nav>

View File

@@ -4,11 +4,12 @@ import { useState, useEffect } from "react";
import { Dialog } from "@/components/ui/dialog"; import { Dialog } from "@/components/ui/dialog";
import { SearchTrigger } from "@/components/SearchTrigger"; import { SearchTrigger } from "@/components/SearchTrigger";
import { SearchModal } from "@/components/SearchModal"; import { SearchModal } from "@/components/SearchModal";
import DocSearchComponent from "@/components/DocSearch";
import { DialogTrigger } from "@radix-ui/react-dialog";
// Define props for the Search component
interface SearchProps { interface SearchProps {
/** /**
* Specify the type of search engine to use. * Specify which search engine to use.
* @default 'default' * @default 'default'
*/ */
type?: "default" | "algolia"; type?: "default" | "algolia";
@@ -17,33 +18,36 @@ interface SearchProps {
export default function Search({ type = "default" }: SearchProps) { export default function Search({ type = "default" }: SearchProps) {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
// Effect to handle keyboard shortcut (Cmd/Ctrl + K) // The useEffect below is ONLY for the 'default' type, which is correct.
// DocSearch handles its own keyboard shortcut.
useEffect(() => { useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => { if (type === 'default') {
if ((event.ctrlKey || event.metaKey) && event.key === "k") { const handleKeyDown = (event: KeyboardEvent) => {
event.preventDefault(); if ((event.ctrlKey || event.metaKey) && event.key === "k") {
setIsOpen((open) => !open); event.preventDefault();
} setIsOpen((open) => !open);
}; }
};
window.addEventListener("keydown", handleKeyDown); window.addEventListener("keydown", handleKeyDown);
return () => { return () => {
window.removeEventListener("keydown", handleKeyDown); window.removeEventListener("keydown", handleKeyDown);
}; };
}, []); }
}, [type]);
// Here you can add logic for different search types if needed in the future
if (type === "algolia") { if (type === "algolia") {
// return <AlgoliaSearchComponent />; // Example for future implementation // Just render the component without passing any state props
console.warn("Tipe pencarian 'algolia' belum diimplementasikan."); return <DocSearchComponent />;
// For now, we will fall back to the default search implementation
} }
// Render the default search components // Logic for 'default' search
return ( return (
<div> <div>
<Dialog open={isOpen} onOpenChange={setIsOpen}> <Dialog open={isOpen} onOpenChange={setIsOpen}>
<SearchTrigger /> <DialogTrigger asChild>
<SearchTrigger />
</DialogTrigger>
<SearchModal isOpen={isOpen} setIsOpen={setIsOpen} /> <SearchModal isOpen={isOpen} setIsOpen={setIsOpen} />
</Dialog> </Dialog>
</div> </div>

View File

@@ -8,6 +8,29 @@ date: 02-08-2025
This changelog contains a list of all the changes made to the DocuBook template. It will be updated with each new release and will include information about new features, bug fixes, and other improvements. This changelog contains a list of all the changes made to the DocuBook template. It will be updated with each new release and will include information about new features, bug fixes, and other improvements.
</Note> </Note>
<div className="sr-only">
### v 1.15.0
</div>
<Release version="1.15.0" date="2025-08-06" title="Algolia DocSearch for better search result">
<Changes type="added">
- new DocSearch.tsx components
- add props type algolia
- add searchprops
- add algolia.css
</Changes>
</Release>
<Note type="warning" title="environment">
To use Algolia DocSearch, you need to configure the following environment variables:
```plaintext
NEXT_PUBLIC_ALGOLIA_DOCSEARCH_APP_ID="your_app_id"
NEXT_PUBLIC_ALGOLIA_DOCSEARCH_API_KEY="your_api_key"
NEXT_PUBLIC_ALGOLIA_DOCSEARCH_INDEX_NAME="your_index_name"
```
</Note>
<div className="sr-only"> <div className="sr-only">
### v 1.14.2 ### v 1.14.2
</div> </div>

View File

@@ -1,6 +1,6 @@
{ {
"name": "docubook", "name": "docubook",
"version": "1.14.2", "version": "1.15.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -9,6 +9,8 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@docsearch/css": "3",
"@docsearch/react": "^3.9.0",
"@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-accordion": "^1.2.0",
"@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-collapsible": "^1.1.0", "@radix-ui/react-collapsible": "^1.1.0",
@@ -21,12 +23,14 @@
"@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toggle": "^1.1.2", "@radix-ui/react-toggle": "^1.1.2",
"@radix-ui/react-toggle-group": "^1.1.2", "@radix-ui/react-toggle-group": "^1.1.2",
"algoliasearch": "^5.35.0",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cmdk": "1.0.0", "cmdk": "1.0.0",
"framer-motion": "^12.4.1", "framer-motion": "^12.4.1",
"geist": "^1.3.1", "geist": "^1.3.1",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"install": "^0.13.0",
"lucide-react": "^0.511.0", "lucide-react": "^0.511.0",
"next": "^14.2.6", "next": "^14.2.6",
"next-mdx-remote": "^5.0.0", "next-mdx-remote": "^5.0.0",

156
styles/algolia.css Normal file
View File

@@ -0,0 +1,156 @@
/*
================================================================================
DocSearch Component Styling (Themed Version)
- This version uses the CSS variables defined in :root and .dark
to automatically adapt to your site's light and dark themes.
================================================================================
*/
.docsearch {
/* Map theme variables to DocSearch's internal variables */
--docsearch-primary-color: hsl(var(--primary));
--docsearch-text-color: hsl(var(--foreground));
--docsearch-container-background: hsla(var(--background) / 0.8); /* Use theme background with transparency */
--docsearch-modal-background: hsl(var(--card)); /* Modals should use card color */
--docsearch-modal-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--docsearch-searchbox-background: hsl(var(--secondary));
--docsearch-searchbox-focus-background: hsl(var(--secondary));
--docsearch-hit-color: hsl(var(--foreground));
--docsearch-hit-background: hsl(var(--card));
--docsearch-hit-shadow: none;
--docsearch-hit-active-color: hsl(var(--primary-foreground));
--docsearch-selected-background: hsl(var(--secondary)); /* Use secondary for selection */
--docsearch-footer-background: hsl(var(--card));
--docsearch-footer-shadow: inset 0 1px 0 0 hsl(var(--border));
--docsearch-key-gradient: transparent;
--docsearch-key-shadow: none;
--docsearch-muted-color: hsl(var(--muted-foreground)); /* Use muted for less important text */
}
/*
* =====================================
* 1. Initial Search Button Styling
* =====================================
*/
.docsearch .DocSearch-Button {
background-color: hsl(var(--secondary)); /* Use secondary for the button background */
border: 1px solid hsl(var(--border)); /* Use the standard border color */
border-radius: 9999px; /* Pill shape */
width: 160px; /* Lebar default untuk desktop */
height: 40px;
color: hsl(var(--muted-foreground)); /* Use muted text color for the placeholder */
transition: width 0.3s ease; /* Transisi untuk perubahan lebar */
}
.docsearch .DocSearch-Button:hover {
border-color: var(--docsearch-primary-color);
box-shadow: none;
}
/* Magnifying glass icon */
.docsearch .DocSearch-Search-Icon {
color: hsl(var(--muted-foreground));
}
/* The 'Search' placeholder text */
.docsearch .DocSearch-Button-Placeholder {
font-style: normal;
}
/* Styling for the '⌘K' keys */
.docsearch .DocSearch-Button-Key {
background: hsl(var(--primary)); /* Use primary color for the key background */
border-radius: 6px;
color: hsl(var(--primary-foreground)); /* Use primary-foreground for the key text */
font-size: 14px;
font-weight: 500;
height: 24px;
padding: 0 6px;
border: none;
box-shadow: none;
top: 0;
}
/*
* =====================================
* 2. Modal and Results Styling
* =====================================
*/
/* Main modal window */
.docsearch .DocSearch-Modal {
backdrop-filter: blur(8px);
}
.docsearch .DocSearch-Container {
box-shadow: var(--docsearch-modal-shadow);
}
/* Search input form */
.docsearch .DocSearch-Form {
border: 1px solid hsl(var(--border));
box-shadow: none;
background-color: transparent;
}
/* The 'Return' and 'Esc' hints */
.docsearch .DocSearch-Reset-Icon,
.docsearch .DocSearch-Cancel {
color: hsl(var(--muted-foreground));
}
/* Style for each search result item */
.docsearch .DocSearch-Hit a {
border-radius: 4px;
}
/* Selected search result */
.docsearch .DocSearch-Hit[aria-selected="true"] a {
background: var(--docsearch-selected-background); /* Highlight color for selected item */
}
/* Hide category headers if not needed */
.docsearch .DocSearch-Hit-source {
display: none;
}
/* Icon next to each result title */
.docsearch .DocSearch-Hit-icon {
color: hsl(var(--muted-foreground));
}
/* Footer instructions ('to navigate', 'to select', etc.) */
.docsearch .DocSearch-Footer {
border-top: 1px solid hsl(var(--border));
}
.docsearch .DocSearch-Footer--commands kbd {
background: hsl(var(--muted)); /* Use muted for the background of keyboard hints */
border: 1px solid hsl(var(--border));
border-radius: 4px;
color: hsl(var(--muted-foreground));
}
/*
* =====================================
* 3. Responsive Styling (Mobile)
* =====================================
*/
@media (max-width: 768px) {
/* Aturan ini akan aktif pada layar 768px ke bawah */
.docsearch .DocSearch-Button {
width: 40px; /* Mengubah lebar tombol menjadi seukuran ikon */
height: 40px; /* Memastikan tinggi tetap sama */
padding: 0; /* Menghapus padding agar ikon bisa di tengah */
justify-content: center; /* Memusatkan ikon di dalam tombol */
background: none;
border: none;
}
/* Menyembunyikan teks "Search..." dan shortcut keyboard */
.docsearch .DocSearch-Button-Placeholder,
.docsearch .DocSearch-Button-Key {
display: none;
}
}