docs: DX improvements to a workflow / step reference page (#10906)

This commit is contained in:
Shahed Nasser
2025-01-10 13:47:08 +02:00
committed by GitHub
parent 428fce5313
commit a126f40bbe
23 changed files with 138116 additions and 73 deletions

View File

@@ -0,0 +1,37 @@
import React from "react"
import { Link } from "../Link"
import { Badge } from "../Badge"
import { Github } from "@medusajs/icons"
import clsx from "clsx"
type SourceCodeLinkProps = {
link: string
text?: string
icon?: React.ReactNode
className?: string
}
export const SourceCodeLink = ({
link,
text,
icon,
className,
}: SourceCodeLinkProps) => {
return (
<Link
href={link}
target="_blank"
rel="noreferrer"
className={clsx("my-docs_0.5 align-middle inline-block", className)}
>
<Badge
variant="neutral"
className="inline-flex hover:bg-medusa-tag-neutral-bg-hover cursor-pointer"
childrenWrapperClassName="inline-flex flex-row gap-[3px] items-center"
>
{icon || <Github />}
<span>{text || "Source Code"}</span>
</Badge>
</Link>
)
}

View File

@@ -1,6 +1,6 @@
"use client"
import React, { useId } from "react"
import React, { forwardRef, useId } from "react"
import { Tooltip as ReactTooltip } from "react-tooltip"
import type { ITooltip } from "react-tooltip"
import clsx from "clsx"
@@ -15,47 +15,52 @@ export type TooltipProps = {
} & React.HTMLAttributes<HTMLSpanElement> &
ITooltip
export const Tooltip = ({
text = "",
tooltipClassName = "",
children,
html = "",
tooltipChildren,
className,
innerClassName,
...tooltipProps
}: TooltipProps) => {
const elementId = useId()
export const Tooltip = forwardRef<HTMLSpanElement, TooltipProps>(
function Tooltip(
{
text = "",
tooltipClassName = "",
children,
html = "",
tooltipChildren,
className,
innerClassName,
...tooltipProps
},
ref
) {
const elementId = useId()
return (
<span className={clsx(className, "notranslate")} translate="no">
<span
id={elementId}
data-tooltip-content={text}
data-tooltip-html={html}
data-tooltip-id={elementId}
className={innerClassName}
>
{children}
return (
<span className={clsx(className, "notranslate")} translate="no" ref={ref}>
<span
id={elementId}
data-tooltip-content={text}
data-tooltip-html={html}
data-tooltip-id={elementId}
className={innerClassName}
>
{children}
</span>
<ReactTooltip
anchorId={elementId}
// anchorSelect={elementId ? `#${elementId}` : undefined}
className={clsx(
"!text-compact-x-small !shadow-elevation-tooltip dark:!shadow-elevation-tooltip-dark !rounded-docs_DEFAULT",
"!py-docs_0.25 !z-[399] hidden !px-docs_0.5 lg:block",
"!bg-medusa-bg-component",
"!text-medusa-fg-base text-center",
tooltipClassName
)}
wrapper="span"
noArrow={true}
positionStrategy={"fixed"}
opacity={1}
{...tooltipProps}
>
{tooltipChildren}
</ReactTooltip>
</span>
<ReactTooltip
anchorId={elementId}
// anchorSelect={elementId ? `#${elementId}` : undefined}
className={clsx(
"!text-compact-x-small !shadow-elevation-tooltip dark:!shadow-elevation-tooltip-dark !rounded-docs_DEFAULT",
"!py-docs_0.25 !z-[399] hidden !px-docs_0.5 lg:block",
"!bg-medusa-bg-component",
"!text-medusa-fg-base text-center",
tooltipClassName
)}
wrapper="span"
noArrow={true}
positionStrategy={"fixed"}
opacity={1}
{...tooltipProps}
>
{tooltipChildren}
</ReactTooltip>
</span>
)
}
)
}
)

View File

@@ -41,6 +41,7 @@ const TypeListItem = ({
elementKey,
sectionTitle,
referenceType = "method",
openedLevel = 0,
}: TypeListItemProps) => {
const { isBrowser } = useIsBrowser()
const pathname = usePathname()
@@ -249,6 +250,7 @@ const TypeListItem = ({
className={clsx(getItemClassNames())}
heightAnimation={true}
id={typeId ? typeId : ""}
openInitial={openedLevel >= level}
>
{typeItem.children && (
<TypeListItems

View File

@@ -5,6 +5,7 @@ import { Loading } from "@/components"
export type CommonProps = {
expandUrl?: string
sectionTitle?: string
openedLevel?: number
}
export type Type = {
@@ -31,6 +32,7 @@ export const TypeList = ({
className,
sectionTitle,
expandUrl,
openedLevel,
...props
}: ParameterTypesType) => {
return (
@@ -47,6 +49,7 @@ export const TypeList = ({
types={types}
expandUrl={expandUrl}
sectionTitle={sectionTitle}
openedLevel={openedLevel}
/>
</Suspense>
</div>

View File

@@ -0,0 +1,37 @@
import React from "react"
import { InlineCode } from "../../../InlineCode"
import { Text } from "@medusajs/ui"
import { Bolt, InformationCircle } from "@medusajs/icons"
export const WorkflowDiagramLegend = () => {
return (
<div className="flex gap-docs_0.5 mt-1">
<div className="flex items-center gap-docs_0.5">
<div className="flex size-[20px] items-center justify-center text-medusa-tag-orange-icon">
<Bolt />
</div>
<Text
size="xsmall"
leading="compact"
weight="plus"
className="select-none"
>
Workflow Hook
</Text>
</div>
<div className="flex items-center gap-docs_0.5">
<div className="flex size-[20px] items-center justify-center text-medusa-tag-green-icon">
<InformationCircle />
</div>
<Text
size="xsmall"
leading="compact"
weight="plus"
className="select-none"
>
Step conditioned by <InlineCode>when</InlineCode>
</Text>
</div>
</div>
)
}

View File

@@ -3,7 +3,7 @@
import { Text } from "@medusajs/ui"
import clsx from "clsx"
import Link from "next/link"
import React, { useMemo } from "react"
import React, { useEffect, useMemo, useRef, useState } from "react"
import { WorkflowStepUi } from "types"
import { InlineCode, MarkdownContent, Tooltip } from "../../.."
import { Bolt, InformationCircle } from "@medusajs/icons"
@@ -14,11 +14,34 @@ export type WorkflowDiagramNodeProps = {
export const WorkflowDiagramStepNode = ({ step }: WorkflowDiagramNodeProps) => {
const stepId = step.name.split(".").pop()
const [offset, setOffset] = useState<number | undefined>(undefined)
const ref = useRef<HTMLSpanElement>(null)
const description = useMemo(() => {
return step.description?.replaceAll(/:::[a-z]*/g, "") || ""
}, [step.description])
useEffect(() => {
if (!ref.current) {
return
}
// find parent
const diagramParent = ref.current.closest(".workflow-list-diagram")
const nodeParent = ref.current.closest(".workflow-node-group")
if (!diagramParent || !nodeParent) {
return
}
const nodeBoundingRect = nodeParent.getBoundingClientRect()
const diagramBoundingRect = diagramParent.getBoundingClientRect()
setOffset(
Math.max(diagramBoundingRect.width - nodeBoundingRect.width + 10, 10)
)
}, [ref.current])
return (
<Tooltip
tooltipClassName="!text-left max-w-[300px] text-pretty overflow-scroll"
@@ -43,6 +66,8 @@ export const WorkflowDiagramStepNode = ({ step }: WorkflowDiagramNodeProps) => {
}
clickable={true}
place="right"
offset={offset}
ref={ref}
>
<Link
href={step.link || `#${step.name}`}

View File

@@ -14,7 +14,7 @@ export const WorkflowDiagramListDepth = ({
cluster,
}: WorkflowDiagramListDepthProps) => {
return (
<div className="flex items-start">
<div className="flex items-start workflow-node-group w-fit">
<WorkflowDiagramLine step={cluster} />
<div className="flex flex-col justify-center gap-y-docs_0.5">
{cluster.map((step, index) => (

View File

@@ -4,6 +4,7 @@ import React from "react"
import { createNodeClusters, getNextCluster } from "../../../utils"
import { WorkflowDiagramCommonProps } from "../../.."
import { WorkflowDiagramListDepth } from "./Depth"
import { WorkflowDiagramLegend } from "../Common/Legend"
export const WorkflowDiagramList = ({
workflow,
@@ -11,7 +12,7 @@ export const WorkflowDiagramList = ({
const clusters = createNodeClusters(workflow.steps)
return (
<div className="flex flex-col gap-docs_0.5 my-docs_1">
<div className="flex flex-col gap-docs_0.5 my-docs_1 workflow-list-diagram w-fit">
{Object.entries(clusters).map(([depth, cluster]) => {
const next = getNextCluster(clusters, Number(depth))
@@ -19,6 +20,7 @@ export const WorkflowDiagramList = ({
<WorkflowDiagramListDepth cluster={cluster} next={next} key={depth} />
)
})}
<WorkflowDiagramLegend />
</div>
)
}

View File

@@ -66,6 +66,7 @@ export * from "./Search/Suggestions/Item"
export * from "./Select"
export * from "./Sidebar"
export * from "./Sidebar/Item"
export * from "./SourceCodeLink"
export * from "./Table"
export * from "./Tabs"
export * from "./TextArea"