docs: add anchor link to reference parameters (#6194)

- Added anchor links to items in parameter components
- Added sectionTitle prop in markdown theme

Note: Due to the second point, the change requires generating references to see the anchor links, which would result in a big diff in this PR. Instead, next time the references are generated for a release, this feature will available for use.
This commit is contained in:
Shahed Nasser
2024-01-24 10:42:55 +02:00
committed by GitHub
parent 75fd6b0c83
commit ddc0c9dfff
22 changed files with 229 additions and 63 deletions

View File

@@ -1,34 +1,53 @@
import {
CopyButton,
DetailsSummary,
ExpandableNotice,
FeatureFlagNotice,
InlineCode,
MarkdownContent,
} from "docs-ui"
import React from "react"
import React, { useEffect, useMemo, useRef, useState } from "react"
import Details from "../../../theme/Details"
import clsx from "clsx"
import { Parameter } from ".."
import {
ArrowDownLeftMini,
ArrowsPointingOutMini,
Link,
TriangleRightMini,
} from "@medusajs/icons"
import IconFlagMini from "../../../theme/Icon/FlagMini"
import decodeStr from "../../../utils/decode-str"
import { useLocation } from "@docusaurus/router"
import useDocusaurusContext from "@docusaurus/useDocusaurusContext"
import isInView from "../../../utils/is-in-view"
type ParameterTypesItemsProps = {
parameters: Parameter[]
type CommonProps = {
level?: number
expandUrl?: string
sectionTitle?: string
}
const ParameterTypesItems = ({
parameters,
type ParameterTypesItemProps = {
parameter: Parameter
elementKey: number
} & CommonProps &
React.AllHTMLAttributes<HTMLDivElement>
const ParameterTypesItem = ({
parameter,
level = 1,
expandUrl,
}: ParameterTypesItemsProps) => {
function getGroupName() {
elementKey,
sectionTitle,
}: ParameterTypesItemProps) => {
const location = useLocation()
const {
siteConfig: { url },
} = useDocusaurusContext()
const groupName = useMemo(() => {
switch (level) {
case 1:
return "group/parameterOne"
@@ -39,8 +58,8 @@ const ParameterTypesItems = ({
case 4:
return "group/parameterFour"
}
}
function getBorderForGroupName() {
}, [level])
const borderForGroupName = useMemo(() => {
switch (level) {
case 1:
return "group-open/parameterOne:border-solid group-open/parameterOne:border-0 group-open/parameterOne:border-b"
@@ -51,8 +70,8 @@ const ParameterTypesItems = ({
case 4:
return "group-open/parameterFour:border-solid group-open/parameterFour:border-0 group-open/parameterFour:border-b"
}
}
function getRotateForGroupName() {
}, [level])
const rotateForGroupName = useMemo(() => {
switch (level) {
case 1:
return "group-open/parameterOne:rotate-90"
@@ -63,15 +82,52 @@ const ParameterTypesItems = ({
case 4:
return "group-open/parameterFour:rotate-90"
}
}
}, [level])
function getItemClassNames(details = true) {
return clsx(
"odd:[&:not(:first-child):not(:last-child)]:!border-y last:not(:first-child):!border-t",
"first:!border-t-0 first:not(:last-child):!border-b last:!border-b-0 even:!border-y-0",
details && getGroupName(),
!details && getBorderForGroupName()
details && groupName,
!details && borderForGroupName
)
}
const formatId = (str: string) => {
return str.replaceAll(" ", "_")
}
const parameterId = useMemo(() => {
return sectionTitle
? `#${formatId(sectionTitle)}-${formatId(
parameter.name
)}-${level}-${elementKey}`
: ""
}, [sectionTitle, parameter, elementKey])
const parameterPath = useMemo(
() => `${location.pathname}${parameterId}`,
[location, parameterId]
)
const parameterUrl = useMemo(
() => `${url}${parameterPath}`,
[url, parameterPath]
)
const ref = useRef<HTMLDivElement>()
const [isSelected, setIsSelected] = useState(false)
useEffect(() => {
if (!parameterId.length) {
return
}
const shouldScroll = location.hash === parameterId
if (shouldScroll && !isSelected && ref.current && !isInView(ref.current)) {
ref.current.scrollIntoView({
block: "center",
})
}
setIsSelected(shouldScroll)
}, [parameterId])
function getSummary(parameter: Parameter, nested = true) {
return (
<DetailsSummary
@@ -102,7 +158,8 @@ const ParameterTypesItems = ({
level === 2 && "pl-3",
level === 3 && "pl-[120px]",
level === 4 && "pl-[160px]",
!nested && "cursor-default"
!nested && "cursor-default",
isSelected && "animate-flash animate-bg-surface"
)}
onClick={(e) => {
const targetElm = e.target as HTMLElement
@@ -112,13 +169,15 @@ const ParameterTypesItems = ({
return
}
}}
summaryRef={!nested ? ref : undefined}
id={!nested && parameterId ? parameterId : ""}
>
<div className="flex gap-0.5">
{nested && (
<TriangleRightMini
className={clsx(
"text-medusa-fg-subtle transition-transform",
getRotateForGroupName()
rotateForGroupName
)}
/>
)}
@@ -127,6 +186,21 @@ const ParameterTypesItems = ({
className={clsx("text-medusa-fg-subtle flip-y")}
/>
)}
{level === 1 && parameterId.length > 0 && (
<CopyButton
text={parameterUrl}
onCopy={(e: React.MouseEvent<HTMLSpanElement, MouseEvent>) => {
e.preventDefault()
e.stopPropagation()
}}
>
<Link
className={clsx(
"text-medusa-fg-interactive hover:text-medusa-fg-interactive-hover"
)}
/>
</CopyButton>
)}
<div className="flex gap-0.75 flex-wrap">
<InlineCode>{decodeStr(parameter.name)}</InlineCode>
<span className="font-monospace text-compact-small-plus text-medusa-fg-subtle">
@@ -168,32 +242,48 @@ const ParameterTypesItems = ({
)
}
return (
<>
{parameter.children?.length > 0 && (
<Details
summary={getSummary(parameter)}
className={clsx(getItemClassNames())}
heightAnimation={true}
ref={ref}
id={parameterId ? parameterId : ""}
>
{parameter.children && (
<ParameterTypesItems
parameters={parameter.children}
level={level + 1}
expandUrl={expandUrl}
/>
)}
</Details>
)}
{(parameter.children?.length || 0) === 0 && getSummary(parameter, false)}
</>
)
}
type ParameterTypesItemsProps = {
parameters: Parameter[]
} & CommonProps
const ParameterTypesItems = ({
parameters,
...rest
}: ParameterTypesItemsProps) => {
return (
<div>
{parameters.map((parameter, key) => {
return (
<>
{parameter.children?.length > 0 && (
<Details
summary={getSummary(parameter)}
key={key}
className={clsx(getItemClassNames())}
heightAnimation={true}
>
{parameter.children && (
<ParameterTypesItems
parameters={parameter.children}
level={level + 1}
expandUrl={expandUrl}
/>
)}
</Details>
)}
{(parameter.children?.length || 0) === 0 &&
getSummary(parameter, false)}
</>
)
})}
{parameters.map((parameter, key) => (
<ParameterTypesItem
parameter={parameter}
key={key}
elementKey={key}
{...rest}
/>
))}
</div>
)
}

View File

@@ -16,6 +16,7 @@ export type Parameter = {
type ParameterTypesType = {
parameters: Parameter[]
expandUrl?: string
sectionTitle?: string
} & React.HTMLAttributes<HTMLDivElement>
const ParameterTypesItems = lazy(async () => import("./Items"))
@@ -34,6 +35,7 @@ const ParameterTypes = ({
<ParameterTypesItems
parameters={parameters}
expandUrl={props.expandUrl}
sectionTitle={props.sectionTitle}
/>
</Suspense>
</div>