docs: add LLM dropdown menu to documentation pages (#12235)

* docs: add LLM dropdown menu to documentation pages

* fix build errors
This commit is contained in:
Shahed Nasser
2025-04-18 13:18:27 +03:00
committed by GitHub
parent 24af8f2d8e
commit db0fe0fc91
14 changed files with 127 additions and 21 deletions

View File

@@ -17,7 +17,7 @@ import ClientLibraries from "./client-libraries.mdx"
<DividedMarkdownContent>
<H1 className={"!h2-docs scroll-m-[184px] lg:scroll-m-[264px]"} id="introduction">Medusa V2 Admin API Reference</H1>
<H1 className={"!h2-docs scroll-m-[184px] lg:scroll-m-[264px]"} id="introduction" hideLlmDropdown>Medusa V2 Admin API Reference</H1>
This API reference includes Medusa v2's Admin APIs, which are REST APIs exposed by the Medusa application. They are used to perform admin functionalities or create an admin dashboard to access and manipulate your commerce store's data.

View File

@@ -17,7 +17,7 @@ import ClientLibraries from "./client-libraries.mdx"
<DividedMarkdownContent>
<H1 className={"!h2-docs scroll-m-[184px] lg:scroll-m-[264px]"} id="introduction">Medusa V2 Store API Reference</H1>
<H1 className={"!h2-docs scroll-m-[184px] lg:scroll-m-[264px]"} id="introduction" hideLlmDropdown>Medusa V2 Store API Reference</H1>
This API reference includes Medusa v2's Store APIs, which are REST APIs exposed by the Medusa application. They are used to create a storefront for your commerce store, such as a webshop or a commerce mobile app.

View File

@@ -1,4 +1,4 @@
import { CardList } from "docs-ui"
import { CardList, H1 } from "docs-ui"
import {
BookOpen,
AcademicCapSolid,
@@ -10,7 +10,7 @@ export const metadata = {
title: `Page Not Found`,
}
# {metadata.title}
<H1 hideLlmDropdown>{metadata.title}</H1>
The page you were looking for isn't available.

View File

@@ -1,4 +1,4 @@
import { CardList } from "docs-ui"
import { CardList, H1 } from "docs-ui"
import {
BookOpen,
AcademicCapSolid,
@@ -10,7 +10,7 @@ export const metadata = {
title: `Page Not Found`,
}
# {metadata.title}
<H1 hideLlmDropdown>{metadata.title}</H1>
The page you were looking for isn't available.

View File

@@ -5,6 +5,7 @@ import { notFound } from "next/navigation"
import { Mdx } from "@/components/mdx-components"
import { siteConfig } from "@/config/site"
import { Metadata } from "next"
import { H1 } from "docs-ui"
interface DocPageProps {
params: Promise<{
@@ -58,7 +59,7 @@ export default async function DocPage(props: DocPageProps) {
return (
<div className="flex flex-col">
<h1 className="h1-docs text-medusa-fg-base mb-2">{doc.title}</h1>
<H1>{doc.title}</H1>
<Text className="text-medusa-fg-subtle mb-6" size="large">
{doc.description}
</Text>

View File

@@ -1,4 +1,4 @@
import { CardList } from "docs-ui"
import { CardList, H1 } from "docs-ui"
import {
BookOpen,
AcademicCapSolid,
@@ -10,7 +10,7 @@ export const metadata = {
title: `Page Not Found`,
}
# {metadata.title}
<H1 hideLlmDropdown>{metadata.title}</H1>
The page you were looking for isn't available.

View File

@@ -20,7 +20,7 @@ export default function NotFound() {
return (
<div>
{/* @ts-expect-error React v19 doesn't recognize these as elements. */}
<H1>Page Not Found</H1>
<H1 hideLlmDropdown>Page Not Found</H1>
{/* @ts-expect-error React v19 doesn't recognize these as elements. */}
<P>The page you were looking for isn&apos;t available.</P>
{/* @ts-expect-error React v19 doesn't recognize these as elements. */}

View File

@@ -1,4 +1,4 @@
import { CardList } from "docs-ui"
import { CardList, H1 } from "docs-ui"
import {
BookOpen,
AcademicCapSolid,
@@ -10,7 +10,7 @@ export const metadata = {
title: `Page Not Found`,
}
# {metadata.title}
<H1 hideLlmDropdown>{metadata.title}</H1>
The page you were looking for isn't available.

View File

@@ -1,19 +1,24 @@
import clsx from "clsx"
import React from "react"
import { LlmDropdown } from "../../LlmDropdown"
type H1Props = React.HTMLAttributes<HTMLHeadingElement> & {
id?: string
hideLlmDropdown?: boolean
}
export const H1 = ({ className, ...props }: H1Props) => {
export const H1 = ({ className, hideLlmDropdown, ...props }: H1Props) => {
return (
<h1
className={clsx(
"h1-docs [&_code]:!h1-docs [&_code]:!font-mono mb-docs_1 text-medusa-fg-base",
props.id && "scroll-m-docs_7",
className
)}
{...props}
/>
<div className="flex items-start justify-between gap-2">
<h1
className={clsx(
"h1-docs [&_code]:!h1-docs [&_code]:!font-mono mb-docs_1 text-medusa-fg-base",
props.id && "scroll-m-docs_7",
className
)}
{...props}
/>
{!hideLlmDropdown && <LlmDropdown />}
</div>
)
}

View File

@@ -0,0 +1,25 @@
import React from "react"
import { IconProps } from "@medusajs/icons/dist/types"
export const MarkdownIcon = (props: IconProps) => {
return (
<svg
fill="currentColor"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg"
width={15}
height={15}
{...props}
>
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
<g
id="SVGRepo_tracerCarrier"
strokeLinecap="round"
strokeLinejoin="round"
></g>
<g id="SVGRepo_iconCarrier">
<path d="M 2.875 6 C 1.320313 6 0 7.253906 0 8.8125 L 0 23.1875 C 0 24.746094 1.320313 26 2.875 26 L 29.125 26 C 30.679688 26 32 24.746094 32 23.1875 L 32 8.8125 C 32 7.253906 30.679688 6 29.125 6 Z M 2.875 8 L 29.125 8 C 29.640625 8 30 8.382813 30 8.8125 L 30 23.1875 C 30 23.617188 29.640625 24 29.125 24 L 2.875 24 C 2.359375 24 2 23.617188 2 23.1875 L 2 8.8125 C 2 8.382813 2.359375 8 2.875 8 Z M 5 11 L 5 21 L 8 21 L 8 14.34375 L 11 18.3125 L 14 14.34375 L 14 21 L 17 21 L 17 11 L 14 11 L 11 15 L 8 11 Z M 22 11 L 22 16 L 19 16 L 23.5 21 L 28 16 L 25 16 L 25 11 Z"></path>
</g>
</svg>
)
}

View File

@@ -0,0 +1,72 @@
"use client"
import React, { useRef, useState } from "react"
import { useAiAssistant, useSiteConfig } from "../../providers"
import { usePathname } from "next/navigation"
import { Button } from "../Button"
import { AiAssistent, Book } from "@medusajs/icons"
import { Menu } from "../Menu"
import { MarkdownIcon } from "../Icons/Markdown"
import { useAiAssistantChat } from "../../providers/AiAssistant/Chat"
import clsx from "clsx"
import { useClickOutside } from "../.."
export const LlmDropdown = () => {
const {
config: { baseUrl, basePath },
} = useSiteConfig()
const pathname = usePathname()
const [open, setOpen] = useState(false)
const { setChatOpened } = useAiAssistant()
const { setQuestion, loading } = useAiAssistantChat()
const ref = useRef<HTMLButtonElement | null>(null)
useClickOutside({
elmRef: ref,
onClickOutside: () => {
setOpen(false)
},
})
const pageUrl = `${baseUrl}${basePath}${pathname}`
return (
<div className="relative hidden md:block">
<Button
variant="transparent"
onClick={() => setOpen(!open)}
className="!p-[6px] text-medusa-fg-subtle"
buttonRef={ref}
>
<Book />
</Button>
<Menu
items={[
{
type: "link",
title: "View as Markdown",
link: `${pageUrl}/index.html.md`,
icon: <MarkdownIcon width={19} height={19} />,
openInNewTab: true,
},
{
type: "action",
title: "Ask AI Assistant",
action: () => {
if (loading) {
return
}
setQuestion(`Explain the page ${pageUrl}`)
setChatOpened(true)
setOpen(false)
},
icon: <AiAssistent />,
},
]}
className={clsx(
"absolute right-0 top-[calc(100%+8px)] w-max",
!open && "hidden"
)}
/>
</div>
)
}

View File

@@ -22,6 +22,8 @@ export const MenuItem = ({ item, onClick }: MenuItemProps) => {
)}
href={item.link}
onClick={() => onClick?.(item)}
target={item.openInNewTab ? "_blank" : undefined}
rel={item.openInNewTab ? "noopener noreferrer" : undefined}
>
{item.icon && (
<span className="text-medusa-fg-subtle mt-[2.5px] block">

View File

@@ -3,6 +3,7 @@ export type MenuItemLink = {
icon?: React.ReactNode
title: string
link: string
openInNewTab?: boolean
}
export type MenuItemDivider = {