docs: changes to AI assistant icon + add button to code blocks (#11227)

* docs: changes to AI assistant icon + add button to code blocks

* fix code blocks in questions

* collapse code block in answer

* styling fixes

* fix new line at cursor position
This commit is contained in:
Shahed Nasser
2025-01-30 14:29:22 +02:00
committed by GitHub
parent 386ce4b857
commit be33a56290
21 changed files with 294 additions and 97 deletions
@@ -12,7 +12,7 @@ export const AiAssistantChatWindowFooter = () => {
)}
>
<span className="text-medusa-fg-muted">Chat is cleared on refresh</span>
<span className="h-full w-px bg-medusa-border-base"></span>
<span className="h-docs_0.75 w-px bg-medusa-border-base"></span>
<div className="flex items-center gap-docs_0.5">
<span className="text-medusa-fg-subtle">Line break</span>
<div className="flex items-center gap-[5px]">
@@ -23,7 +23,9 @@ export const AiAssistantChatWindowHeader = () => {
<Tooltip
tooltipChildren={
<>
This site is protected by reCAPTCHA and the{" "}
This site is protected by reCAPTCHA and
<br />
the{" "}
<Link href="https://policies.google.com/privacy">
Google Privacy Policy
</Link>{" "}
@@ -32,6 +34,7 @@ export const AiAssistantChatWindowHeader = () => {
</>
}
clickable={true}
tooltipClassName={"!text-compact-small-plus"}
>
<ShieldCheck className="text-medusa-fg-muted" />
</Tooltip>
@@ -2,6 +2,7 @@ import React, { useEffect, useRef } from "react"
import clsx from "clsx"
import { useAiAssistantChat } from "../../../../providers/AiAssistant/Chat"
import { ArrowUpCircleSolid } from "@medusajs/icons"
import { useAiAssistant } from "../../../../providers"
export const AiAssistantChatWindowInput = () => {
const {
@@ -12,6 +13,7 @@ export const AiAssistantChatWindowInput = () => {
loading,
getThreadItems,
} = useAiAssistantChat()
const { chatOpened } = useAiAssistant()
const formRef = useRef<HTMLFormElement | null>(null)
const onSubmit = (e?: React.FormEvent<HTMLFormElement>) => {
@@ -33,7 +35,17 @@ export const AiAssistantChatWindowInput = () => {
return
}
if (e.shiftKey) {
setQuestion((prev) => `${prev}\n`)
const { selectionStart, selectionEnd } = e.currentTarget
setQuestion(
(prev) =>
`${prev.substring(0, selectionStart)}\n${prev.substring(selectionEnd)}`
)
setTimeout(() => {
if (inputRef.current) {
inputRef.current.selectionStart = inputRef.current.selectionEnd =
selectionStart + 1
}
}, 0)
} else {
onSubmit()
}
@@ -52,6 +64,7 @@ export const AiAssistantChatWindowInput = () => {
useEffect(() => {
adjustTextareaHeight()
inputRef.current?.focus()
}, [question])
const handleTouch = (e: React.TouchEvent<HTMLTextAreaElement>) => {
@@ -61,6 +74,19 @@ export const AiAssistantChatWindowInput = () => {
})
}
useEffect(() => {
if (!chatOpened || !inputRef.current) {
return
}
const isCursorAtEnd =
inputRef.current.selectionStart === inputRef.current.value.length
if (isCursorAtEnd) {
inputRef.current.scrollTop = inputRef.current.scrollHeight
}
}, [chatOpened, inputRef.current])
return (
<div
className={clsx(
@@ -1,6 +1,13 @@
import clsx from "clsx"
import React from "react"
import { AiAssistantIcon, DotsLoading, MarkdownContent } from "@/components"
import {
AiAssistantIcon,
CodeMdx,
CodeMdxProps,
DotsLoading,
MarkdownContent,
MDXComponents,
} from "@/components"
import { AiAssistantThreadItemActions } from "./Actions"
import { AiAssistantThread } from "../../../providers/AiAssistant/Chat"
@@ -27,7 +34,7 @@ export const AiAssistantThreadItem = ({ item }: AiAssistantThreadItemProps) => {
"txt-small text-medusa-fg-base",
item.type === "question" && [
"rounded-docs_xl bg-medusa-tag-neutral-bg",
"px-docs_0.75 py-docs_0.5",
"px-docs_0.75 py-docs_0.5 max-w-full",
],
item.type !== "question" && "flex-1",
item.type === "answer" && "text-pretty flex-1 max-w-[calc(100%-20px)]"
@@ -38,6 +45,39 @@ export const AiAssistantThreadItem = ({ item }: AiAssistantThreadItemProps) => {
className="[&>*:last-child]:mb-0"
allowedElements={["br", "p", "code", "pre"]}
unwrapDisallowed={true}
components={{
...MDXComponents,
code: (props: CodeMdxProps) => {
return (
<CodeMdx
{...props}
noCopy
noReport
forceNoTitle
noAskAi
inlineCodeProps={{
...props.inlineCodeProps,
className: "!text-wrap !break-words",
variant: "grey-bg",
}}
collapsibleLines="11"
codeBlockProps={{
className: clsx(
"rounded-docs_lg p-[5px]",
props.className
),
wrapperClassName: "rounded-docs_lg",
innerClassName: "border rounded-docs_lg",
overrideColors: {
bg: "bg-medusa-contrast-bg-subtle",
innerBg: "bg-medusa-contrast-bg-subtle",
innerBorder: "border-medusa-contrast-border-bot",
},
}}
/>
)
},
}}
>
{item.content}
</MarkdownContent>
@@ -45,7 +85,15 @@ export const AiAssistantThreadItem = ({ item }: AiAssistantThreadItemProps) => {
{item.type === "answer" && (
<div className="flex flex-col gap-docs_0.75">
{!item.question_id && item.content.length === 0 && <DotsLoading />}
<MarkdownContent className="[&>*:last-child]:mb-0">
<MarkdownContent
className="[&>*:last-child]:mb-0"
components={{
...MDXComponents,
code: (props: CodeMdxProps) => {
return <CodeMdx {...props} noReport noAskAi />
},
}}
>
{item.content}
</MarkdownContent>
{item.question_id && <AiAssistantThreadItemActions item={item} />}
@@ -1,6 +1,6 @@
"use client"
import React, { useMemo, useState } from "react"
import React from "react"
import { Button } from "../../Button"
import { Tooltip } from "../../Tooltip"
import { Kbd } from "../../Kbd"
@@ -9,17 +9,13 @@ import { useAiAssistant, useSearch, useSiteConfig } from "../../../providers"
import { useKeyboardShortcut } from "../../../hooks"
import Image from "next/image"
const AI_ASSISTANT_ICON = "/images/ai-assistent-luminosity.png"
// const AI_ASSISTANT_ICON = "/images/ai-assistent-luminosity.png"
const AI_ASSISTANT_ICON_ACTIVE = "/images/ai-assistent.png"
export const AiAssistantTriggerButton = () => {
const [hovered, setHovered] = useState(false)
const { config } = useSiteConfig()
const { chatOpened, setChatOpened } = useAiAssistant()
const { setChatOpened } = useAiAssistant()
const { setIsOpen } = useSearch()
const isActive = useMemo(() => {
return hovered || chatOpened
}, [hovered, chatOpened])
const osShortcut = getOsShortcut()
useKeyboardShortcut({
@@ -35,36 +31,29 @@ export const AiAssistantTriggerButton = () => {
return (
<Tooltip
render={() => (
<span className="flex gap-[6px] items-center">
<span className="text-compact-x-small-plus text-medusa-fg-base">
Ask AI
</span>
<span className="flex gap-[5px] items-center">
<Kbd className="bg-medusa-bg-field-component border-medusa-border-strong w-[18px] h-[18px] inline-block">
{osShortcut}
</Kbd>
<Kbd className="bg-medusa-bg-field-component border-medusa-border-strong w-[18px] h-[18px] inline-block">
i
</Kbd>
</span>
<span className="flex gap-[5px] items-center">
<Kbd className="bg-medusa-bg-field-component border-medusa-border-strong w-[18px] h-[18px] inline-block">
{osShortcut}
</Kbd>
<Kbd className="bg-medusa-bg-field-component border-medusa-border-strong w-[18px] h-[18px] inline-block">
i
</Kbd>
</span>
)}
>
<Button
variant="transparent-clear"
className="!p-[6.5px]"
onMouseOver={() => setHovered(true)}
onMouseOut={() => setHovered(false)}
onTouchStart={() => setHovered(true)}
onTouchEnd={() => setHovered(false)}
onClick={() => setChatOpened((prev) => !prev)}
>
<Image
src={`${config.basePath}${isActive ? AI_ASSISTANT_ICON_ACTIVE : AI_ASSISTANT_ICON}`}
src={`${config.basePath}${AI_ASSISTANT_ICON_ACTIVE}`}
width={15}
height={15}
alt="AI Assistant"
/>
<span className="hidden md:inline-block text-medusa-fg-subtle">
Ask AI
</span>
</Button>
</Tooltip>
)