mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-10-05 17:53:54 +02:00
(Minor) Add cleaner search, feedback model, and connector view (#2098)
* add cleaner search, feedback model, and connector view * Update ChatPage.tsx
This commit is contained in:
@@ -417,7 +417,9 @@ export function CCPairIndexingStatusTable({
|
|||||||
{!shouldExpand ? "Collapse All" : "Expand All"}
|
{!shouldExpand ? "Collapse All" : "Expand All"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{sortedSources.map((source, ind) => {
|
{sortedSources
|
||||||
|
.filter((source) => source != "not_applicable")
|
||||||
|
.map((source, ind) => {
|
||||||
const sourceMatches = source
|
const sourceMatches = source
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(searchTerm.toLowerCase());
|
.includes(searchTerm.toLowerCase());
|
||||||
|
@@ -76,10 +76,6 @@ import { useSidebarVisibility } from "@/components/chat_search/hooks";
|
|||||||
import { SIDEBAR_TOGGLED_COOKIE_NAME } from "@/components/resizable/constants";
|
import { SIDEBAR_TOGGLED_COOKIE_NAME } from "@/components/resizable/constants";
|
||||||
import FixedLogo from "./shared_chat_search/FixedLogo";
|
import FixedLogo from "./shared_chat_search/FixedLogo";
|
||||||
import { getSecondsUntilExpiration } from "@/lib/time";
|
import { getSecondsUntilExpiration } from "@/lib/time";
|
||||||
import {
|
|
||||||
FullLLMProvider,
|
|
||||||
LLMProviderDescriptor,
|
|
||||||
} from "../admin/models/llm/interfaces";
|
|
||||||
|
|
||||||
const TEMP_USER_MESSAGE_ID = -1;
|
const TEMP_USER_MESSAGE_ID = -1;
|
||||||
const TEMP_ASSISTANT_MESSAGE_ID = -2;
|
const TEMP_ASSISTANT_MESSAGE_ID = -2;
|
||||||
|
@@ -6,6 +6,7 @@ import { FiThumbsDown, FiThumbsUp } from "react-icons/fi";
|
|||||||
import { ModalWrapper } from "./ModalWrapper";
|
import { ModalWrapper } from "./ModalWrapper";
|
||||||
import {
|
import {
|
||||||
DislikeFeedbackIcon,
|
DislikeFeedbackIcon,
|
||||||
|
FilledLikeIcon,
|
||||||
LikeFeedbackIcon,
|
LikeFeedbackIcon,
|
||||||
} from "@/components/icons/icons";
|
} from "@/components/icons/icons";
|
||||||
|
|
||||||
@@ -53,19 +54,19 @@ export const FeedbackModal = ({
|
|||||||
: predefinedNegativeFeedbackOptions;
|
: predefinedNegativeFeedbackOptions;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalWrapper onClose={onClose} modalClassName="max-w-5xl">
|
<ModalWrapper onClose={onClose} modalClassName="max-w-3xl">
|
||||||
<>
|
<>
|
||||||
<h2 className="text-2xl text-emphasis font-bold mb-4 flex">
|
<h2 className="text-2xl text-emphasis font-bold mb-4 flex">
|
||||||
<div className="mr-1 my-auto">
|
<div className="mr-1 my-auto">
|
||||||
{feedbackType === "like" ? (
|
{feedbackType === "like" ? (
|
||||||
<LikeFeedbackIcon
|
<FilledLikeIcon
|
||||||
size={20}
|
size={20}
|
||||||
className="text-green-500 my-auto mr-2"
|
className="text-green-500 my-auto mr-2"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<DislikeFeedbackIcon
|
<FilledLikeIcon
|
||||||
size={20}
|
size={20}
|
||||||
className="text-red-600 my-auto mr-2"
|
className="rotate-180 text-red-600 my-auto mr-2"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1695,6 +1695,29 @@ export const ThumbsUpIconSkeleton = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const FilledLikeIcon = ({
|
||||||
|
size = 16,
|
||||||
|
className = defaultTailwindCSS,
|
||||||
|
}: IconProps) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
style={{ width: `${size}px`, height: `${size}px` }}
|
||||||
|
className={`w-[${size}px] h-[${size}px] ` + className}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
viewBox="0 0 14 14"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M4.41 12.961a2.5 2.5 0 0 0 1.076.244h5.346a2.5 2.5 0 0 0 2.47-2.114l.626-4.003a2 2 0 0 0-1.976-2.31H8.67V2.422a1.625 1.625 0 0 0-3.044-.794l-2.077 3.71a1.5 1.5 0 0 0-.191.733v5.442a1.5 1.5 0 0 0 .854 1.354l.2.095Zm-3.366-7.44a.996.996 0 0 0-.997.996v5.112a.997.997 0 0 0 .997.997h.496a.5.5 0 0 0 .5-.5V6.02a.5.5 0 0 0-.5-.5h-.496Z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const LikeFeedbackIcon = ({
|
export const LikeFeedbackIcon = ({
|
||||||
size = 16,
|
size = 16,
|
||||||
className = defaultTailwindCSS,
|
className = defaultTailwindCSS,
|
||||||
|
174
web/src/components/search/SearchAnswer.tsx
Normal file
174
web/src/components/search/SearchAnswer.tsx
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Dispatch,
|
||||||
|
SetStateAction,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
import { HoverableIcon } from "../Hoverable";
|
||||||
|
import {
|
||||||
|
DislikeFeedbackIcon,
|
||||||
|
LikeFeedbackIcon,
|
||||||
|
ToggleDown,
|
||||||
|
} from "../icons/icons";
|
||||||
|
import { FeedbackType } from "@/app/chat/types";
|
||||||
|
import { searchState } from "./SearchSection";
|
||||||
|
import { SettingsContext } from "../settings/SettingsProvider";
|
||||||
|
import { AnswerSection } from "./results/AnswerSection";
|
||||||
|
import { Quote, SearchResponse } from "@/lib/search/interfaces";
|
||||||
|
import { QuotesSection } from "./results/QuotesSection";
|
||||||
|
|
||||||
|
export default function SearchAnswer({
|
||||||
|
searchAnswerExpanded,
|
||||||
|
setSearchAnswerExpanded,
|
||||||
|
isFetching,
|
||||||
|
dedupedQuotes,
|
||||||
|
searchResponse,
|
||||||
|
setCurrentFeedback,
|
||||||
|
searchState,
|
||||||
|
}: {
|
||||||
|
searchAnswerExpanded: boolean;
|
||||||
|
setSearchAnswerExpanded: Dispatch<SetStateAction<boolean>>;
|
||||||
|
isFetching: boolean;
|
||||||
|
dedupedQuotes: Quote[];
|
||||||
|
searchResponse: SearchResponse;
|
||||||
|
searchState: searchState;
|
||||||
|
setCurrentFeedback: Dispatch<SetStateAction<[FeedbackType, number] | null>>;
|
||||||
|
}) {
|
||||||
|
const [searchAnswerOverflowing, setSearchAnswerOverflowing] = useState(false);
|
||||||
|
|
||||||
|
const { quotes, answer, error } = searchResponse;
|
||||||
|
const answerContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleFeedback = (feedbackType: FeedbackType, messageId: number) => {
|
||||||
|
setCurrentFeedback([feedbackType, messageId]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const settings = useContext(SettingsContext);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkOverflow = () => {
|
||||||
|
if (answerContainerRef.current) {
|
||||||
|
const isOverflowing =
|
||||||
|
answerContainerRef.current.scrollHeight >
|
||||||
|
answerContainerRef.current.clientHeight;
|
||||||
|
setSearchAnswerOverflowing(isOverflowing);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkOverflow();
|
||||||
|
window.addEventListener("resize", checkOverflow);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("resize", checkOverflow);
|
||||||
|
};
|
||||||
|
}, [answer]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={answerContainerRef}
|
||||||
|
className={`my-4 ${searchAnswerExpanded ? "min-h-[16rem]" : "h-[16rem]"} overflow-y-hidden p-4 border-2 border-border rounded-lg relative`}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div className="flex gap-x-2">
|
||||||
|
<h2 className="text-emphasis font-bold my-auto mb-1 ">AI Answer</h2>
|
||||||
|
|
||||||
|
{searchState == "generating" && (
|
||||||
|
<div key={"generating"} className="relative inline-block">
|
||||||
|
<span className="loading-text">Generating response...</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{searchState == "citing" && (
|
||||||
|
<div key={"citing"} className="relative inline-block">
|
||||||
|
<span className="loading-text">Creating citations...</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{searchState == "searching" && (
|
||||||
|
<div key={"Reading"} className="relative inline-block">
|
||||||
|
<span className="loading-text">Searching...</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{searchState == "reading" && (
|
||||||
|
<div key={"Reading"} className="relative inline-block">
|
||||||
|
<span className="loading-text">
|
||||||
|
Reading{settings?.isMobile ? "" : " Documents"}
|
||||||
|
...
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{searchState == "analyzing" && (
|
||||||
|
<div key={"Generating"} className="relative inline-block">
|
||||||
|
<span className="loading-text">
|
||||||
|
Running
|
||||||
|
{settings?.isMobile ? "" : " Analysis"}...
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={`pt-1 h-auto border-t border-border w-full`}>
|
||||||
|
<AnswerSection
|
||||||
|
answer={answer}
|
||||||
|
quotes={quotes}
|
||||||
|
error={error}
|
||||||
|
isFetching={isFetching}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{searchAnswerExpanded ||
|
||||||
|
(!searchAnswerOverflowing && (
|
||||||
|
<div className="w-full">
|
||||||
|
{quotes !== null && quotes.length > 0 && answer && (
|
||||||
|
<QuotesSection quotes={dedupedQuotes} isFetching={isFetching} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{searchResponse.messageId !== null && (
|
||||||
|
<div className="absolute right-3 flex bottom-3">
|
||||||
|
<HoverableIcon
|
||||||
|
icon={<LikeFeedbackIcon />}
|
||||||
|
onClick={() =>
|
||||||
|
handleFeedback(
|
||||||
|
"like",
|
||||||
|
searchResponse?.messageId as number
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<HoverableIcon
|
||||||
|
icon={<DislikeFeedbackIcon />}
|
||||||
|
onClick={() =>
|
||||||
|
handleFeedback(
|
||||||
|
"dislike",
|
||||||
|
searchResponse?.messageId as number
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{!searchAnswerExpanded && searchAnswerOverflowing && (
|
||||||
|
<div className="absolute bottom-0 left-0 w-full h-[100px] bg-gradient-to-b from-background/5 via-background/60 to-background/90"></div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!searchAnswerExpanded && searchAnswerOverflowing && (
|
||||||
|
<div className="w-full h-12 absolute items-center content-center flex left-0 px-4 bottom-0">
|
||||||
|
<button
|
||||||
|
onClick={() => setSearchAnswerExpanded(true)}
|
||||||
|
className="flex gap-x-1 items-center justify-center hover:bg-background-100 cursor-pointer max-w-sm text-sm mx-auto w-full bg-background border py-2 rounded-full"
|
||||||
|
>
|
||||||
|
Show more
|
||||||
|
<ToggleDown />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@@ -31,22 +31,11 @@ import { SIDEBAR_TOGGLED_COOKIE_NAME } from "../resizable/constants";
|
|||||||
import { AGENTIC_SEARCH_TYPE_COOKIE_NAME } from "@/lib/constants";
|
import { AGENTIC_SEARCH_TYPE_COOKIE_NAME } from "@/lib/constants";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import FixedLogo from "@/app/chat/shared_chat_search/FixedLogo";
|
import FixedLogo from "@/app/chat/shared_chat_search/FixedLogo";
|
||||||
import { AnswerSection } from "./results/AnswerSection";
|
|
||||||
import { QuotesSection } from "./results/QuotesSection";
|
|
||||||
import { QAFeedbackBlock } from "./QAFeedback";
|
|
||||||
import { usePopup } from "../admin/connectors/Popup";
|
import { usePopup } from "../admin/connectors/Popup";
|
||||||
import { ToggleRight } from "@phosphor-icons/react";
|
|
||||||
import {
|
|
||||||
DislikeFeedbackIcon,
|
|
||||||
LikeFeedbackIcon,
|
|
||||||
ToggleDown,
|
|
||||||
ToggleUp,
|
|
||||||
} from "../icons/icons";
|
|
||||||
import { CustomTooltip, TooltipGroup } from "../tooltip/CustomTooltip";
|
|
||||||
import { HoverableIcon } from "../Hoverable";
|
|
||||||
import { FeedbackType } from "@/app/chat/types";
|
import { FeedbackType } from "@/app/chat/types";
|
||||||
import { FeedbackModal } from "@/app/chat/modal/FeedbackModal";
|
import { FeedbackModal } from "@/app/chat/modal/FeedbackModal";
|
||||||
import { handleChatFeedback } from "@/app/chat/lib";
|
import { handleChatFeedback } from "@/app/chat/lib";
|
||||||
|
import SearchAnswer from "./SearchAnswer";
|
||||||
|
|
||||||
export type searchState =
|
export type searchState =
|
||||||
| "input"
|
| "input"
|
||||||
@@ -111,7 +100,6 @@ export const SearchSection = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [agentic, setAgentic] = useState(agenticSearchEnabled);
|
const [agentic, setAgentic] = useState(agenticSearchEnabled);
|
||||||
const [searchAnswerExpanded, setSearchAnswerExpanded] = useState(false);
|
|
||||||
|
|
||||||
const toggleAgentic = () => {
|
const toggleAgentic = () => {
|
||||||
Cookies.set(
|
Cookies.set(
|
||||||
@@ -376,6 +364,7 @@ export const SearchSection = ({
|
|||||||
setSearchState("input");
|
setSearchState("input");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const [searchAnswerExpanded, setSearchAnswerExpanded] = useState(false);
|
||||||
|
|
||||||
const resetInput = (finalized?: boolean) => {
|
const resetInput = (finalized?: boolean) => {
|
||||||
setSweep(false);
|
setSweep(false);
|
||||||
@@ -546,32 +535,6 @@ export const SearchSection = ({
|
|||||||
[FeedbackType, number] | null
|
[FeedbackType, number] | null
|
||||||
>(null);
|
>(null);
|
||||||
|
|
||||||
//
|
|
||||||
const [searchAnswerOverflowing, setSearchAnswerOverflowing] = useState(false);
|
|
||||||
const answerContainerRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
const handleFeedback = (feedbackType: FeedbackType, messageId: number) => {
|
|
||||||
setCurrentFeedback([feedbackType, messageId]);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const checkOverflow = () => {
|
|
||||||
if (answerContainerRef.current) {
|
|
||||||
const isOverflowing =
|
|
||||||
answerContainerRef.current.scrollHeight >
|
|
||||||
answerContainerRef.current.clientHeight;
|
|
||||||
setSearchAnswerOverflowing(isOverflowing);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
checkOverflow();
|
|
||||||
window.addEventListener("resize", checkOverflow);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("resize", checkOverflow);
|
|
||||||
};
|
|
||||||
}, [answer]);
|
|
||||||
|
|
||||||
const onFeedback = async (
|
const onFeedback = async (
|
||||||
messageId: number,
|
messageId: number,
|
||||||
feedbackType: FeedbackType,
|
feedbackType: FeedbackType,
|
||||||
@@ -758,136 +721,15 @@ export const SearchSection = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{!firstSearch && (
|
{!firstSearch && (
|
||||||
<div
|
<SearchAnswer
|
||||||
ref={answerContainerRef}
|
|
||||||
className={`my-4 ${searchAnswerExpanded ? "min-h-[16rem]" : "h-[16rem]"} overflow-y-hidden p-4 border-2 border-border rounded-lg relative`}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div className="flex gap-x-2">
|
|
||||||
<h2 className="text-emphasis font-bold my-auto mb-1 ">
|
|
||||||
AI Answer
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{searchState == "generating" && (
|
|
||||||
<div
|
|
||||||
key={"generating"}
|
|
||||||
className="relative inline-block"
|
|
||||||
>
|
|
||||||
<span className="loading-text">
|
|
||||||
Generating response...
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{searchState == "citing" && (
|
|
||||||
<div
|
|
||||||
key={"citing"}
|
|
||||||
className="relative inline-block"
|
|
||||||
>
|
|
||||||
<span className="loading-text">
|
|
||||||
Creating citations...
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{searchState == "searching" && (
|
|
||||||
<div
|
|
||||||
key={"Reading"}
|
|
||||||
className="relative inline-block"
|
|
||||||
>
|
|
||||||
<span className="loading-text">Searching...</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{searchState == "reading" && (
|
|
||||||
<div
|
|
||||||
key={"Reading"}
|
|
||||||
className="relative inline-block"
|
|
||||||
>
|
|
||||||
<span className="loading-text">
|
|
||||||
Reading{settings?.isMobile ? "" : " Documents"}
|
|
||||||
...
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{searchState == "analyzing" && (
|
|
||||||
<div
|
|
||||||
key={"Generating"}
|
|
||||||
className="relative inline-block"
|
|
||||||
>
|
|
||||||
<span className="loading-text">
|
|
||||||
Running
|
|
||||||
{settings?.isMobile ? "" : " Analysis"}...
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={`pt-1 h-auto border-t border-border w-full`}
|
|
||||||
>
|
|
||||||
<AnswerSection
|
|
||||||
answer={answer}
|
|
||||||
quotes={quotes}
|
|
||||||
error={error}
|
|
||||||
isFetching={isFetching}
|
isFetching={isFetching}
|
||||||
|
dedupedQuotes={dedupedQuotes}
|
||||||
|
searchResponse={searchResponse}
|
||||||
|
setSearchAnswerExpanded={setSearchAnswerExpanded}
|
||||||
|
searchAnswerExpanded={searchAnswerExpanded}
|
||||||
|
setCurrentFeedback={setCurrentFeedback}
|
||||||
|
searchState={searchState}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
{searchAnswerExpanded ||
|
|
||||||
(!searchAnswerOverflowing && (
|
|
||||||
<div className="w-full">
|
|
||||||
{quotes !== null &&
|
|
||||||
quotes.length > 0 &&
|
|
||||||
answer && (
|
|
||||||
<QuotesSection
|
|
||||||
quotes={dedupedQuotes}
|
|
||||||
isFetching={isFetching}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{searchResponse.messageId !== null && (
|
|
||||||
<div className="absolute right-3 flex bottom-3">
|
|
||||||
<HoverableIcon
|
|
||||||
icon={<LikeFeedbackIcon />}
|
|
||||||
onClick={() =>
|
|
||||||
handleFeedback(
|
|
||||||
"like",
|
|
||||||
searchResponse?.messageId as number
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<HoverableIcon
|
|
||||||
icon={<DislikeFeedbackIcon />}
|
|
||||||
onClick={() =>
|
|
||||||
handleFeedback(
|
|
||||||
"dislike",
|
|
||||||
searchResponse?.messageId as number
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
{!searchAnswerExpanded && searchAnswerOverflowing && (
|
|
||||||
<div className="absolute bottom-0 left-0 w-full h-[100px] bg-gradient-to-b from-background/5 via-background/60 to-background/90"></div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!searchAnswerExpanded && searchAnswerOverflowing && (
|
|
||||||
<div className="w-full h-12 absolute items-center content-center flex left-0 px-4 bottom-0">
|
|
||||||
<button
|
|
||||||
onClick={() => setSearchAnswerExpanded(true)}
|
|
||||||
className="flex gap-x-1 items-center justify-center hover:bg-background-100 cursor-pointer max-w-sm text-sm mx-auto w-full bg-background border py-2 rounded-full"
|
|
||||||
>
|
|
||||||
Show more
|
|
||||||
<ToggleDown />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!settings?.isMobile && (
|
{!settings?.isMobile && (
|
||||||
|
Reference in New Issue
Block a user