diff --git a/package-lock.json b/package-lock.json
index 85a7b0d..2e62a1a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"clsx": "^2.1.0",
+ "fuse.js": "^7.0.0",
"gray-matter": "^4.0.3",
"highlight.js": "^11.9.0",
"marked": "^12.0.0",
@@ -4292,6 +4293,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/fuse.js": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz",
+ "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/get-east-asian-width": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz",
diff --git a/package.json b/package.json
index 006465e..1293554 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"clsx": "^2.1.0",
+ "fuse.js": "^7.0.0",
"gray-matter": "^4.0.3",
"highlight.js": "^11.9.0",
"marked": "^12.0.0",
diff --git a/src/components/ItemList/ItemList.module.css b/src/components/ItemList/ItemList.module.css
index d986332..9c41190 100644
--- a/src/components/ItemList/ItemList.module.css
+++ b/src/components/ItemList/ItemList.module.css
@@ -18,6 +18,7 @@
.ring {
flex: 0 0 auto;
+ margin-left: 16px;
align-self: baseline;
}
@@ -58,11 +59,10 @@
.link {
display: flex;
flex-wrap: wrap;
- padding: 16px;
}
.quadrant {
- margin: 0 16px 0 auto;
+ margin-left: auto;
}
@media (min-width: 768px) {
diff --git a/src/components/ItemList/ItemList.tsx b/src/components/ItemList/ItemList.tsx
index 5c94643..5c3cc0e 100644
--- a/src/components/ItemList/ItemList.tsx
+++ b/src/components/ItemList/ItemList.tsx
@@ -11,6 +11,7 @@ export interface ItemListProps {
items: Item[];
activeId?: string;
size?: "small" | "default" | "large";
+ hideRing?: boolean;
className?: string;
}
@@ -18,6 +19,7 @@ export function ItemList({
items,
activeId,
size = "default",
+ hideRing = false,
className,
}: ItemListProps) {
return (
@@ -48,11 +50,13 @@ export function ItemList({
{getQuadrant(item.quadrant)?.title}
-
+ {!hideRing && (
+
+ )}
)}
diff --git a/src/pages/overview.tsx b/src/pages/overview.tsx
index 8497536..0b8c06a 100644
--- a/src/pages/overview.tsx
+++ b/src/pages/overview.tsx
@@ -1,3 +1,4 @@
+import Fuse from "fuse.js";
import Head from "next/head";
import { useRouter } from "next/router";
import { useCallback, useMemo } from "react";
@@ -11,7 +12,7 @@ import { CustomPage } from "@/pages/_app";
const Overview: CustomPage = () => {
const router = useRouter();
const ring = router.query.ring as string | undefined;
- const query = router.query.query as string | undefined;
+ const query = (router.query.query as string) || "";
const onRingChange = useCallback(
(ring: string) => {
@@ -27,15 +28,38 @@ const Overview: CustomPage = () => {
[router, ring],
);
- const items = useMemo(() => {
- if (!ring && !query) return getItems();
- return getItems().filter((item) => {
- if (ring && item.ring !== ring) return false;
- return !(
- query && !item.title.toLowerCase().includes(query.toLowerCase())
- );
+ const { items, index } = useMemo(() => {
+ const items = getItems().filter((item) => !ring || item.ring === ring);
+ const index = new Fuse(items, {
+ threshold: 0.3,
+ includeScore: true,
+ keys: [
+ {
+ name: "title",
+ weight: 1.5,
+ },
+ {
+ name: "tags",
+ weight: 1,
+ },
+ {
+ name: "body",
+ weight: 0.9,
+ },
+ {
+ name: "revision.body",
+ weight: 0.7,
+ },
+ ],
});
- }, [query, ring]);
+
+ return { items, index };
+ }, [ring]);
+
+ const results = useMemo(() => {
+ if (!query) return items;
+ return index.search(query).map((result) => result.item);
+ }, [query, index, items]);
return (
<>
@@ -51,7 +75,7 @@ const Overview: CustomPage = () => {
onQueryChange={onQueryChange}
/>
-
+
>
);
};
diff --git a/src/styles/globals.css b/src/styles/globals.css
index c1b3f78..c4eff93 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -95,7 +95,7 @@ input {
color: var(--background);
border: 1px solid transparent;
padding: 10px 12px;
- border-radius: 6px;
+ border-radius: 3px;
width: 100%;
font-size: 16px;