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:
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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't available.</P>
|
||||
{/* @ts-expect-error React v19 doesn't recognize these as elements. */}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
25
www/packages/docs-ui/src/components/Icons/Markdown/index.tsx
Normal file
25
www/packages/docs-ui/src/components/Icons/Markdown/index.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
72
www/packages/docs-ui/src/components/LlmDropdown/index.tsx
Normal file
72
www/packages/docs-ui/src/components/LlmDropdown/index.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
@@ -3,6 +3,7 @@ export type MenuItemLink = {
|
||||
icon?: React.ReactNode
|
||||
title: string
|
||||
link: string
|
||||
openInNewTab?: boolean
|
||||
}
|
||||
|
||||
export type MenuItemDivider = {
|
||||
|
||||
Reference in New Issue
Block a user