Skip to content

Commit e7c4f80

Browse files
SaraVieiraskeptrunedev
authored andcommitted
feat: add suggested queries to search component
1 parent 439a798 commit e7c4f80

File tree

12 files changed

+366
-221
lines changed

12 files changed

+366
-221
lines changed

clients/search-component/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@eslint/js": "^9.10.0",
2626
"@tailwindcss/forms": "^0.5.9",
2727
"@types/eslint__js": "^8.42.3",
28+
"@types/lodash.debounce": "^4.0.9",
2829
"@types/lodash.omit": "^4.5.9",
2930
"@types/lodash.throttle": "^4.1.9",
3031
"@types/react": "^18.3.5",
@@ -54,6 +55,7 @@
5455
"@radix-ui/react-dialog": "^1.1.1",
5556
"@thumbmarkjs/thumbmarkjs": "^0.14.8",
5657
"downshift": "^9.0.8",
58+
"lodash.debounce": "^4.0.8",
5759
"lodash.omit": "^4.5.0",
5860
"lodash.throttle": "^4.1.1",
5961
"react-markdown": "^9.0.1",

clients/search-component/src/TrieveModal/ChatMode.tsx

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
11
import React, { useEffect, useRef, useState } from "react";
2-
import { TrieveSDK } from "trieve-ts-sdk";
32
import Markdown from "react-markdown";
43
import SyntaxHighlighter from "react-syntax-highlighter";
54
import { nightOwl } from "react-syntax-highlighter/dist/esm/styles/hljs";
65
import { getFingerprint } from "@thumbmarkjs/thumbmarkjs";
76
import { BackIcon, CheckIcon, LoadingAIIcon, LoadingIcon } from "./icons";
87
import { Chunk } from "../utils/types";
8+
import { useModalState } from "../utils/hooks/modal-context";
99

10-
export const ChatMode = ({
11-
query,
12-
setMode,
13-
trieve,
14-
onNewMessage,
15-
}: {
16-
query: string;
17-
setMode: (value: string) => void;
18-
trieve: TrieveSDK;
19-
onNewMessage: () => void;
20-
}) => {
10+
export const ChatMode = () => {
11+
const { query, setMode, props, modalRef } = useModalState();
2112
const [currentQuestion, setCurrentQuestion] = useState(query);
2213
const [currentTopic, setCurrentTopic] = useState("");
2314
const called = useRef(false);
@@ -43,7 +34,7 @@ export const ChatMode = ({
4334
called.current = true;
4435
setIsLoading(true);
4536
const fingerprint = await getFingerprint();
46-
const topic = await trieve.createTopic({
37+
const topic = await props.trieve.createTopic({
4738
name: currentQuestion,
4839
owner_id: fingerprint.toString(),
4940
});
@@ -95,7 +86,7 @@ export const ChatMode = ({
9586

9687
const createQuestion = async (id?: string) => {
9788
setIsLoading(true);
98-
const reader = await trieve.createMessageReader({
89+
const reader = await props.trieve.createMessageReader({
9990
topic_id: id || currentTopic,
10091
new_message_content: currentQuestion,
10192
llm_options: {
@@ -124,7 +115,7 @@ export const ChatMode = ({
124115
]);
125116
createQuestion();
126117
setCurrentQuestion("");
127-
onNewMessage();
118+
modalRef.current?.scroll({ top: 0, behavior: "smooth" });
128119
}}
129120
>
130121
<input

clients/search-component/src/TrieveModal/SearchMode.tsx

Lines changed: 56 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,67 @@
11
import React from "react";
22
import { Item } from "./item";
3-
import { Chunk, ChunkWithHighlights } from "../utils/types";
4-
import { AIIcon, ArrowIcon } from "./icons";
3+
import { AIIcon, ArrowIcon, LoadingIcon } from "./icons";
4+
import { useSuggestedQueries } from "../utils/hooks/useSuggestedQueries";
5+
import { useModalState } from "../utils/hooks/modal-context";
6+
7+
export const SearchMode = () => {
8+
const { props, results, query, setQuery, inputRef, setMode } =
9+
useModalState();
10+
const { suggestedQueries, isFetchingSuggestedQueries } =
11+
useSuggestedQueries();
512

6-
export const SearchMode = ({
7-
results,
8-
query,
9-
setQuery,
10-
setMode,
11-
onUpOrDownClicked,
12-
onResultClick,
13-
showImages,
14-
placeholder,
15-
inputRef,
16-
chat,
17-
}: {
18-
results: ChunkWithHighlights[];
19-
query: string;
20-
setQuery: (value: string) => void;
21-
setMode: (value: string) => void;
22-
onUpOrDownClicked: (index: number, code: string) => void;
23-
onResultClick: (chunk: Chunk & { position: number }) => void;
24-
showImages?: boolean;
25-
placeholder?: string;
26-
inputRef: React.RefObject<HTMLInputElement>;
27-
chat: boolean;
28-
}) => {
2913
return (
3014
<>
3115
<div className="input-wrapper">
32-
<svg
33-
xmlns="http://www.w3.org/2000/svg"
34-
width="16"
35-
height="16"
36-
viewBox="0 0 24 24"
37-
fill="none"
38-
stroke="currentColor"
39-
strokeWidth="2"
40-
strokeLinecap="round"
41-
strokeLinejoin="round"
42-
className="search-icon"
43-
>
44-
<circle cx="11" cy="11" r="8"></circle>
45-
<path d="m21 21-4.3-4.3"></path>
46-
</svg>
47-
<input
48-
ref={inputRef}
49-
value={query}
50-
onChange={(e) => setQuery(e.target.value)}
51-
placeholder={placeholder || "Search for anything"}
52-
/>
53-
<div className="kbd-wrapper">
54-
<kbd>ESC</kbd>
16+
<div className="input-flex">
17+
<svg
18+
xmlns="http://www.w3.org/2000/svg"
19+
width="16"
20+
height="16"
21+
viewBox="0 0 24 24"
22+
fill="none"
23+
stroke="currentColor"
24+
strokeWidth="2"
25+
strokeLinecap="round"
26+
strokeLinejoin="round"
27+
className="search-icon"
28+
>
29+
<circle cx="11" cy="11" r="8"></circle>
30+
<path d="m21 21-4.3-4.3"></path>
31+
</svg>
32+
<input
33+
ref={inputRef}
34+
value={query}
35+
onChange={(e) => setQuery(e.target.value)}
36+
placeholder={props.placeholder || "Search for anything"}
37+
/>
38+
39+
<div className="kbd-wrapper">
40+
<kbd>ESC</kbd>
41+
</div>
42+
</div>
43+
<div className="suggested-queries-wrapper">
44+
<p>Suggested Queries: </p>
45+
{isFetchingSuggestedQueries
46+
? Array.from(Array(2).keys()).map((k) => (
47+
<button key={k} disabled className="suggested-query">
48+
<LoadingIcon className="w-5 h-4" />
49+
</button>
50+
))
51+
: suggestedQueries.map((q) => (
52+
<button
53+
onClick={() => setQuery(q)}
54+
key={q}
55+
className="suggested-query"
56+
>
57+
{q}
58+
</button>
59+
))}
5560
</div>
5661
</div>
62+
5763
<ul className="trieve-elements-search">
58-
{results.length && chat ? (
64+
{results.length && props.chat ? (
5965
<li>
6066
<button className="item start-chat" onClick={() => setMode("chat")}>
6167
<div>
@@ -72,14 +78,7 @@ export const SearchMode = ({
7278
</li>
7379
) : null}
7480
{results.map((result, index) => (
75-
<Item
76-
onUpOrDownClicked={onUpOrDownClicked}
77-
item={result}
78-
index={index}
79-
onResultClick={onResultClick}
80-
showImages={showImages}
81-
key={result.chunk.id}
82-
/>
81+
<Item item={result} index={index} key={result.chunk.id} />
8382
))}
8483
</ul>
8584
</>

clients/search-component/src/TrieveModal/icons.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import React from "react";
2-
export const LoadingIcon = () => (
1+
import React, { SVGAttributes } from "react";
2+
export const LoadingIcon = (props: SVGAttributes<SVGElement>) => (
33
<svg
44
xmlns="http://www.w3.org/2000/svg"
55
width="120"
66
height="30"
7-
className="loading-system"
7+
className={props.className}
88
viewBox="0 0 120 30"
99
>
10-
<circle cx="15" cy="15" r="15">
10+
<circle cx="15" cy="15" r="15" fill="currentColor">
1111
<animate
1212
attributeName="r"
1313
begin="0s"
@@ -29,7 +29,7 @@ export const LoadingIcon = () => (
2929
values="1;.5;1"
3030
></animate>
3131
</circle>
32-
<circle cx="60" cy="15" r="9" fillOpacity="0.3">
32+
<circle cx="60" cy="15" r="9" fillOpacity="0.3" fill="currentColor">
3333
<animate
3434
attributeName="r"
3535
begin="0s"
@@ -51,7 +51,7 @@ export const LoadingIcon = () => (
5151
values=".5;1;.5"
5252
></animate>
5353
</circle>
54-
<circle cx="105" cy="15" r="15">
54+
<circle cx="105" cy="15" r="15" fill="currentColor">
5555
<animate
5656
attributeName="r"
5757
begin="0s"

clients/search-component/src/TrieveModal/index.css

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,30 @@ body {
107107
}
108108

109109
.input-wrapper {
110-
@apply sticky top-0 bg-zinc-50 pt-2 flex items-center z-10 mt-1;
110+
@apply sticky top-0 bg-zinc-50 pt-2 z-10 mt-1 flex flex-col gap-2;
111+
112+
.input-flex {
113+
@apply flex items-center;
114+
}
115+
116+
.suggested-queries-wrapper {
117+
@apply flex gap-2 items-center flex-wrap;
118+
119+
> p {
120+
@apply text-xs text-zinc-600;
121+
}
122+
}
123+
124+
.suggested-query {
125+
@apply inline-flex items-center rounded-md bg-purple-100 px-2 py-1 text-xs font-medium text-purple-600 text-left;
126+
127+
&:disabled {
128+
@apply px-8;
129+
}
130+
}
111131

112132
&::after {
113-
@apply absolute h-[17px] w-full z-50 block top-[56px] bg-gradient-to-b from-zinc-50 via-zinc-50 to-transparent;
133+
@apply absolute h-[17px] w-full z-50 block -bottom-[16px] bg-gradient-to-b from-zinc-50 via-zinc-50 to-transparent;
114134
content: "";
115135
}
116136

0 commit comments

Comments
 (0)