docs: redesign search + re-introduce ai assistant in v2 docs (#8678)

* docs: redesign search + re-introduce ai assistant in v2

* change version in ui

* show icon in case of error

* fixes based on feedback
This commit is contained in:
Shahed Nasser
2024-08-23 10:42:37 +03:00
committed by GitHub
parent c63a08fb03
commit 320b01f45d
23 changed files with 553 additions and 347 deletions
@@ -1,13 +1,8 @@
import React, { useState } from "react"
import { ThreadType } from "../.."
import clsx from "clsx"
import {
Button,
type ButtonProps,
ThumbDownIcon,
ThumbUpIcon,
} from "@/components"
import { Check, SquareTwoStack } from "@medusajs/icons"
import { Button, type ButtonProps } from "@/components"
import { Check, SquareTwoStackMini, ThumbDown, ThumbUp } from "@medusajs/icons"
import { useCopy } from "@/hooks"
import { AiAssistantFeedbackType, useAiAssistant } from "@/providers"
@@ -43,21 +38,17 @@ export const AiAssistantThreadItemActions = ({
return (
<div
className={clsx(
"hidden md:flex gap-docs_0.25",
"text-medusa-fg-muted",
"sticky top-docs_1"
)}
className={clsx("hidden md:flex gap-docs_0.25", "text-medusa-fg-muted")}
>
<ActionButton onClick={handleCopy}>
{isCopied ? <Check /> : <SquareTwoStack />}
{isCopied ? <Check /> : <SquareTwoStackMini />}
</ActionButton>
{(feedback === null || feedback === "upvote") && (
<ActionButton
onClick={async () => handleFeedback("upvote", item.question_id)}
className={clsx(feedback === "upvote" && "!text-medusa-fg-subtle")}
>
<ThumbUpIcon />
<ThumbUp />
</ActionButton>
)}
{(feedback === null || feedback === "downvote") && (
@@ -65,7 +56,7 @@ export const AiAssistantThreadItemActions = ({
onClick={async () => handleFeedback("downvote", item.question_id)}
className={clsx(feedback === "downvote" && "!text-medusa-fg-subtle")}
>
<ThumbDownIcon />
<ThumbDown />
</ActionButton>
)}
</div>
@@ -79,7 +70,7 @@ const ActionButton = ({ children, className, ...props }: ButtonProps) => {
className={clsx(
"text-medusa-fg-muted hover:text-medusa-fg-subtle",
"hover:bg-medusa-bg-subtle-hover",
"p-docs_0.125 rounded-docs_sm",
"!p-[4.5px] rounded-docs_sm",
className
)}
{...props}
@@ -1,8 +1,7 @@
import clsx from "clsx"
import React from "react"
import { ThreadType } from ".."
import { DotsLoading, MarkdownContent, QuestionMarkIcon } from "@/components"
import { ExclamationCircle, Sparkles } from "@medusajs/icons"
import { AiAssistantIcon, DotsLoading, MarkdownContent } from "@/components"
import { AiAssistantThreadItemActions } from "./Actions"
export type AiAssistantThreadItemProps = {
@@ -13,39 +12,37 @@ export const AiAssistantThreadItem = ({ item }: AiAssistantThreadItemProps) => {
return (
<div
className={clsx(
"p-docs_1 flex justify-start gap-docs_1 items-start",
"text-medusa-fg-subtle border-solid border-0 border-b",
"border-medusa-border-base text-medium relative",
item.type === "question" && "bg-medusa-bg-base",
item.type === "answer" && "bg-medusa-bg-subtle"
"p-docs_0.5 flex gap-docs_0.75 items-start",
item.type === "question" && "justify-end",
item.type === "answer" && "!pr-[20px]"
)}
>
<span
{item.type !== "question" && <AiAssistantIcon />}
<div
className={clsx(
"border border-solid border-medusa-border-base",
"rounded-docs_sm p-docs_0.125 bg-medusa-bg-component",
"text-medusa-fg-muted flex"
"txt-small text-medusa-fg-subtle",
item.type === "question" && [
"rounded-docs_xl bg-medusa-tag-neutral-bg",
"px-docs_0.75 py-docs_0.5",
],
item.type !== "question" && "flex-1",
item.type === "answer" && "text-pretty"
)}
>
{item.type === "question" && <QuestionMarkIcon />}
{item.type === "answer" && <Sparkles />}
{item.type === "error" && <ExclamationCircle />}
</span>
<div className="md:max-w-[calc(100%-134px)] md:w-[calc(100%-134px)]">
{item.type === "question" && <>{item.content}</>}
{item.type === "answer" && (
<>
<div className="flex flex-col gap-docs_0.75">
{!item.question_id && item.content.length === 0 && <DotsLoading />}
<MarkdownContent>{item.content}</MarkdownContent>
</>
<MarkdownContent className="[&>*:last-child]:mb-0">
{item.content}
</MarkdownContent>
{item.question_id && <AiAssistantThreadItemActions item={item} />}
</div>
)}
{item.type === "error" && (
<span className="text-medusa-fg-error">{item.content}</span>
)}
</div>
{item.type === "answer" && item.question_id && (
<AiAssistantThreadItemActions item={item} />
)}
</div>
)
}
@@ -11,10 +11,9 @@ import {
SearchHitGroupName,
Tooltip,
Link,
AiAssistantIcon,
} from "@/components"
import { useAiAssistant, useSearch } from "@/providers"
import { ArrowUturnLeft, XMarkMini } from "@medusajs/icons"
import { ArrowUturnLeft } from "@medusajs/icons"
import clsx from "clsx"
import { useSearchNavigation } from "@/hooks"
import { AiAssistantThreadItem } from "./ThreadItem"
@@ -77,26 +76,50 @@ export const AiAssistant = () => {
const [answer, setAnswer] = useState("")
const [identifiers, setIdentifiers] = useState<IdentifierType | null>(null)
const [loading, setLoading] = useState(false)
const { getAnswer } = useAiAssistant()
const { getAnswer, version } = useAiAssistant()
const { setCommand } = useSearch()
const inputRef = useRef<HTMLInputElement>(null)
const contentRef = useRef<HTMLDivElement>(null)
const suggestions: SearchSuggestionType[] = [
{
title: "FAQ",
items: [
"What is Medusa?",
"How can I create an ecommerce store with Medusa?",
"How can I build a marketplace with Medusa?",
"How can I build subscription-based purchases with Medusa?",
"How can I build digital products with Medusa?",
"What can I build with Medusa?",
"What is Medusa Admin?",
"How do I configure the database in Medusa?",
],
},
]
const suggestions: SearchSuggestionType[] = useMemo(() => {
return version === "v2"
? [
{
title: "FAQ",
items: [
"What is Medusa?",
"How can I create a module?",
"How can I create a data model?",
"How do I create a workflow?",
"How can I extend a data model in the Product Module?",
],
},
{
title: "Recipes",
items: [
"How do I build a marketplace with Medusa?",
"How do I build digital products with Medusa?",
"How do I build subscription-based purchases with Medusa?",
"What other recipes are available in the Medusa documentation?",
],
},
]
: [
{
title: "FAQ",
items: [
"What is Medusa?",
"How can I create an ecommerce store with Medusa?",
"How can I build a marketplace with Medusa?",
"How can I build subscription-based purchases with Medusa?",
"How can I build digital products with Medusa?",
"What can I build with Medusa?",
"What is Medusa Admin?",
"How do I configure the database in Medusa?",
],
},
]
}, [version])
const handleSubmit = (selectedQuestion?: string) => {
if (!selectedQuestion?.length && !question.length) {
@@ -292,6 +315,22 @@ export const AiAssistant = () => {
return (
<div className="h-full">
<div className={clsx("px-docs_1 pt-docs_1")}>
<Tooltip
tooltipChildren={
<>
This site is protected by reCAPTCHA and the{" "}
<Link href="https://policies.google.com/privacy">
Google Privacy Policy
</Link>{" "}
and <Link href="https://policies.google.com/terms">ToS</Link>{" "}
apply
</>
}
>
<Badge variant="neutral">AI Assistant</Badge>
</Tooltip>
</div>
<div
className={clsx(
"flex gap-docs_1 px-docs_1 py-docs_0.75",
@@ -302,7 +341,7 @@ export const AiAssistant = () => {
<Button
variant="transparent"
onClick={() => setCommand(null)}
className="text-medusa-fg-subtle p-[5px]"
className="text-medusa-fg-muted p-[6.5px]"
>
<ArrowUturnLeft />
</Button>
@@ -311,7 +350,7 @@ export const AiAssistant = () => {
onChange={(e) => setQuestion(e.target.value)}
className={clsx(
"bg-transparent border-0 focus:outline-none hover:!bg-transparent",
"shadow-none flex-1 text-medusa-fg-base",
"!shadow-none flex-1 text-medusa-fg-base",
"disabled:!bg-transparent disabled:cursor-not-allowed"
)}
placeholder="Ask me a question about Medusa..."
@@ -319,23 +358,22 @@ export const AiAssistant = () => {
passedRef={inputRef}
disabled={loading}
/>
<Button
variant="transparent"
<span
onClick={() => {
setQuestion("")
inputRef.current?.focus()
}}
className={clsx(
"text-medusa-fg-subtle p-[5px]",
"text-medusa-fg-muted hover:text-medusa-fg-subtle",
"absolute top-docs_0.75 right-docs_1",
"hover:bg-medusa-bg-base-hover rounded-docs_sm",
"cursor-pointer",
question.length === 0 && "hidden"
)}
>
<XMarkMini />
</Button>
Clear
</span>
</div>
<div className="h-[calc(100%-120px)] md:h-[calc(100%-114px)] lg:max-h-[calc(100%-114px)] lg:min-h-[calc(100%-114px)] overflow-auto">
<div className="h-[calc(100%-95px)] lg:max-h-[calc(100%-140px)] lg:min-h-[calc(100%-140px)] overflow-auto">
<div ref={contentRef}>
{!thread.length && (
<div className="mx-docs_0.5">
@@ -372,35 +410,12 @@ export const AiAssistant = () => {
</div>
<div
className={clsx(
"py-docs_0.75 flex items-center justify-between px-docs_1",
"border-0 border-solid",
"py-docs_0.75 hidden md:flex items-center justify-end px-docs_1",
"border-medusa-border-base border-t",
"bg-medusa-bg-base h-[57px]"
"bg-medusa-bg-field-component"
)}
>
<Tooltip
tooltipChildren={
<>
This site is protected by reCAPTCHA and the{" "}
<Link href="https://policies.google.com/privacy">
Google Privacy Policy
</Link>{" "}
and <Link href="https://policies.google.com/terms">ToS</Link>{" "}
apply
</>
}
>
<div
className={clsx(
"flex items-center gap-docs_0.75 text-compact-small-plus"
)}
>
<AiAssistantIcon />
<span className="text-medusa-fg-subtle">Medusa AI Assistant</span>
<Badge variant="purple">Beta</Badge>
</div>
</Tooltip>
<div className="hidden items-center gap-docs_1 md:flex">
<div className="flex items-center gap-docs_0.75">
<div className="flex items-center gap-docs_0.5">
{thread.length === 0 && (
<>
@@ -412,9 +427,23 @@ export const AiAssistant = () => {
>
Navigate FAQ
</span>
<span className="gap-docs_0.25 flex">
<Kbd></Kbd>
<Kbd></Kbd>
<span className="gap-[5px] flex">
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
</span>
</>
)}
@@ -426,13 +455,23 @@ export const AiAssistant = () => {
</span>
)}
</div>
<div
className={clsx("h-docs_0.75 w-px bg-medusa-border-strong")}
></div>
<div className="flex items-center gap-docs_0.5">
<span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}
>
Ask Question
</span>
<Kbd></Kbd>
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
</div>
</div>
</div>